Uploaded image for project: 'RESTEasy'
  1. RESTEasy
  2. RESTEASY-1580

Broken spring MVC Integration

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • Major
    • 3.1.1.Final, 3.0.21.Final
    • 3.1.0.Final
    • None
    • None
    • Hide

      Just boot in spring MVC integration mode. This is my code...

      // Some comments here
      public String getFoo()
      {
          return foo;
      }
      
      package com.smashit.common.config.resteasy;
      
      import java.util.HashMap;
      
      import org.jboss.resteasy.plugins.spring.SpringBeanProcessor;
      import org.jboss.resteasy.spi.ResteasyDeployment;
      import org.jboss.resteasy.spi.ResteasyProviderFactory;
      import org.jboss.resteasy.springmvc.ResteasyHandlerAdapter;
      import org.jboss.resteasy.springmvc.ResteasyHandlerMapping;
      import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
      import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
      import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
      import org.springframework.boot.context.properties.ConfigurationProperties;
      import org.springframework.boot.context.properties.EnableConfigurationProperties;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.core.Ordered;
      
      import com.smashit.common.http.HttpCommonBusiness;
      import com.smashit.common.http.HttpCommonBusinessImpl;
      
      // https://dzone.com/articles/resteasy-spring
      
      @ConditionalOnClass(ResteasyHandlerMapping.class)
      @EnableConfigurationProperties
      @Configuration
      @ConditionalOnWebApplication
      public class SpringMvcResteasyConfig {
      	
      	public static String API_PATH_PREFIX="api";
      	
      	@ConditionalOnMissingBean(ResteasyDeployment.class)
      	@ConfigurationProperties(prefix="resteasy.deployment")
      	@Bean(initMethod="start", destroyMethod="stop")
      	public ResteasyDeployment resteasyDeployment(final SpringBeanProcessor springBeanProcessor) {
      		ResteasyDeployment resteasyDeployment = new ResteasyDeployment() {
      			public void start() {
      				super.start();
      				if (springBeanProcessor.getRegistry() == null) {
      					springBeanProcessor.setRegistry(this.getRegistry());
      				}
      			}
      		};
      		resteasyDeployment.setProviderFactory(springBeanProcessor.getProviderFactory());
      		
      		// produce an Accept header on GET with the right content type. COOL!!!
      		resteasyDeployment.setMediaTypeMappings(new HashMap<String, String>() {
      			private static final long serialVersionUID = 1L;
      
      			{
      				put("pdf", HttpCommonBusinessImpl.CONTENT_TYPE_PDF);
      				put("json", HttpCommonBusinessImpl.CONTENT_TYPE_JSON);
      				put("xml", HttpCommonBusinessImpl.CONTENT_TYPE_XML);
      				put("csv", HttpCommonBusinessImpl.CONTENT_TYPE_CSV);
      				put("html", HttpCommonBusinessImpl.CONTENT_TYPE_HMTL);
      				put("xls", HttpCommonBusinessImpl.CONTENT_TYPE_OFFICE_XLS);
      				put("xlsx", HttpCommonBusinessImpl.CONTENT_TYPE_OFFICE_XLSX);
      				put("doc", HttpCommonBusinessImpl.CONTENT_TYPE_OFFICE_DOC);
      				put("docx", HttpCommonBusinessImpl.CONTENT_TYPE_OFFICE_DOCX);
      				put("rtf", HttpCommonBusinessImpl.CONTENT_TYPE_RTF);
      				put("ods", HttpCommonBusinessImpl.CONTENT_TYPE_OPENOFFICE_ODS);
      				put("odt", HttpCommonBusinessImpl.CONTENT_TYPE_OPENOFFICE_ODT);
      			}
      		});
      
      		// produce an Accept header on GET with the right content type. COOL!!!
      		resteasyDeployment.setLanguageExtensions(new HashMap<String, String>() {
      			private static final long serialVersionUID = 1L;
      
      			{
      				put("en", "en-US");
      				put("fr", "fr-FR");
      				put("it", "it-IT");
      				put("de", "de-DE");
      			}
      		});
      		
      		return resteasyDeployment;
      	}
      
      	@ConditionalOnMissingBean(SpringBeanProcessor.class)
      	@Bean
      	public SpringBeanProcessor springBeanProcessor() {
      		SpringBeanProcessor springBeanProcessor = new SpringBeanProcessor();
      		springBeanProcessor.setProviderFactory(new ResteasyProviderFactory());
      		return springBeanProcessor;
      	}
      	
      	/** Receive requests from spring MVC dispatcher servlet. There is no RestEasy Servlet at all
      	 * 
      	 * @param deployment
      	 * @return
      	 */
      	@ConditionalOnMissingBean(ResteasyHandlerMapping.class)
      	@Bean
      	public ResteasyHandlerMapping resteasyHandlerMapper(ResteasyDeployment deployment) {
      		ResteasyHandlerMapping handlerMapping = new ResteasyHandlerMapping(deployment);
      		// TODO: Here it should be AFTER PATH RESOLVER NOT THE LAST, BUT IT JUST WORKS!
      		handlerMapping.setOrder(Ordered.LOWEST_PRECEDENCE);
      		handlerMapping.setPrefix("/"+API_PATH_PREFIX);
      		return handlerMapping;
      	}
      
      	@ConditionalOnMissingBean(ResteasyHandlerAdapter.class)
      	@Bean
      	public ResteasyHandlerAdapter resteasyHandlerAdapter(ResteasyDeployment deployment) {
      		return new ResteasyHandlerAdapter(deployment);
      	}
      }
      
      Show
      Just boot in spring MVC integration mode. This is my code... // Some comments here public String getFoo() { return foo; } package com.smashit.common.config.resteasy; import java.util.HashMap; import org.jboss.resteasy.plugins.spring.SpringBeanProcessor; import org.jboss.resteasy.spi.ResteasyDeployment; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.springmvc.ResteasyHandlerAdapter; import org.jboss.resteasy.springmvc.ResteasyHandlerMapping; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import com.smashit.common.http.HttpCommonBusiness; import com.smashit.common.http.HttpCommonBusinessImpl; // https://dzone.com/articles/resteasy-spring @ConditionalOnClass(ResteasyHandlerMapping.class) @EnableConfigurationProperties @Configuration @ConditionalOnWebApplication public class SpringMvcResteasyConfig { public static String API_PATH_PREFIX= "api" ; @ConditionalOnMissingBean(ResteasyDeployment.class) @ConfigurationProperties(prefix= "resteasy.deployment" ) @Bean(initMethod= "start" , destroyMethod= "stop" ) public ResteasyDeployment resteasyDeployment( final SpringBeanProcessor springBeanProcessor) { ResteasyDeployment resteasyDeployment = new ResteasyDeployment() { public void start() { super .start(); if (springBeanProcessor.getRegistry() == null ) { springBeanProcessor.setRegistry( this .getRegistry()); } } }; resteasyDeployment.setProviderFactory(springBeanProcessor.getProviderFactory()); // produce an Accept header on GET with the right content type. COOL!!! resteasyDeployment.setMediaTypeMappings( new HashMap< String , String >() { private static final long serialVersionUID = 1L; { put( "pdf" , HttpCommonBusinessImpl.CONTENT_TYPE_PDF); put( "json" , HttpCommonBusinessImpl.CONTENT_TYPE_JSON); put( "xml" , HttpCommonBusinessImpl.CONTENT_TYPE_XML); put( "csv" , HttpCommonBusinessImpl.CONTENT_TYPE_CSV); put( "html" , HttpCommonBusinessImpl.CONTENT_TYPE_HMTL); put( "xls" , HttpCommonBusinessImpl.CONTENT_TYPE_OFFICE_XLS); put( "xlsx" , HttpCommonBusinessImpl.CONTENT_TYPE_OFFICE_XLSX); put( "doc" , HttpCommonBusinessImpl.CONTENT_TYPE_OFFICE_DOC); put( "docx" , HttpCommonBusinessImpl.CONTENT_TYPE_OFFICE_DOCX); put( "rtf" , HttpCommonBusinessImpl.CONTENT_TYPE_RTF); put( "ods" , HttpCommonBusinessImpl.CONTENT_TYPE_OPENOFFICE_ODS); put( "odt" , HttpCommonBusinessImpl.CONTENT_TYPE_OPENOFFICE_ODT); } }); // produce an Accept header on GET with the right content type. COOL!!! resteasyDeployment.setLanguageExtensions( new HashMap< String , String >() { private static final long serialVersionUID = 1L; { put( "en" , "en-US" ); put( "fr" , "fr-FR" ); put( "it" , "it-IT" ); put( "de" , "de-DE" ); } }); return resteasyDeployment; } @ConditionalOnMissingBean(SpringBeanProcessor.class) @Bean public SpringBeanProcessor springBeanProcessor() { SpringBeanProcessor springBeanProcessor = new SpringBeanProcessor(); springBeanProcessor.setProviderFactory( new ResteasyProviderFactory()); return springBeanProcessor; } /** Receive requests from spring MVC dispatcher servlet. There is no RestEasy Servlet at all * * @param deployment * @ return */ @ConditionalOnMissingBean(ResteasyHandlerMapping.class) @Bean public ResteasyHandlerMapping resteasyHandlerMapper(ResteasyDeployment deployment) { ResteasyHandlerMapping handlerMapping = new ResteasyHandlerMapping(deployment); // TODO: Here it should be AFTER PATH RESOLVER NOT THE LAST, BUT IT JUST WORKS! handlerMapping.setOrder(Ordered.LOWEST_PRECEDENCE); handlerMapping.setPrefix( "/" +API_PATH_PREFIX); return handlerMapping; } @ConditionalOnMissingBean(ResteasyHandlerAdapter.class) @Bean public ResteasyHandlerAdapter resteasyHandlerAdapter(ResteasyDeployment deployment) { return new ResteasyHandlerAdapter(deployment); } }

    Description

      Reasteasy 3.1.0 / Spring MVC Integration: npe at row 132 of SpringBeanProcessor. deployment is null. 3.0.19 was ok. It seems that deployment is not initialized in this class except in one of constructor . In my case the empty one is used.

               else if (bean instanceof ResteasyDeployment) {
                  ResteasyDeployment beanDeployment = (ResteasyDeployment) bean;
      *            deployment.merge(beanDeployment);* NPE HERE
                  deployment.start();
               }
      

      Attachments

        Issue Links

          Activity

            People

              rhn-support-asoldano Alessio Soldano
              denis.miorandi_jira Denis Miorandi (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: