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

Spring integration (for Spring Boot) is broken

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Done
    • Icon: Major Major
    • 3.0.14.Final
    • 3.0.10.Final, 3.0.11.Final, 3.0.12.Final, 3.0.13.Final
    • None
    • None
    • Hide

      Develop a simple Spring Boot web application that has a Configuration class that creates a bean for org.jboss.resteasy.plugins.spring.SpringBeanProcessor. Then start the application.

      Example:

      1. Go to Spring Initialzr, select only Web as Project Dependency, and generate a Spring Boot app.
      2. Add these Resteasy dependencies to your pom file (version can be 3.0.10 or later, up to 3.0.13):
        1. org.jboss.resteasy:resteasy-jaxrs
        2. org.jboss.resteasy:async-http-servlet-3.0
        3. org.jboss.resteasy:resteasy-servlet-initializer
        4. org.jboss.resteasy:resteasy-spring.
      3. Add the method below to your application class
      4. Try to build the application and you will see that junit will fail (if you build the application with -DskipTests=true, and then start it, you will also get the exact same Exception)
          @Bean
          public SpringBeanProcessor springBeanProcessor() { 
              return new SpringBeanProcessor();
          }
      
      Show
      Develop a simple Spring Boot web application that has a Configuration class that creates a bean for org.jboss.resteasy.plugins.spring.SpringBeanProcessor . Then start the application. Example: Go to Spring Initialzr , select only Web as Project Dependency , and generate a Spring Boot app. Add these Resteasy dependencies to your pom file (version can be 3.0.10 or later, up to 3.0.13): org.jboss.resteasy:resteasy-jaxrs org.jboss.resteasy:async-http-servlet-3.0 org.jboss.resteasy:resteasy-servlet-initializer org.jboss.resteasy:resteasy-spring. Add the method below to your application class Try to build the application and you will see that junit will fail (if you build the application with -DskipTests=true , and then start it, you will also get the exact same Exception) @Bean public SpringBeanProcessor springBeanProcessor() { return new SpringBeanProcessor(); }
    • Hide

      No known workaround, unfortunately.

      Show
      No known workaround, unfortunately.

      I have developed a Spring Boot starter for Resteasy.
      At first, I wrote it based in Resteasy 3.0.9. Then, I upgraded it to Resteasy 3.0.12 and now this exception is thrown during application start-up:

      Exception in thread "main" java.lang.IllegalStateException: could not find the type for bean named mvcContentNegotiationManager
      	at org.jboss.resteasy.plugins.spring.SpringBeanProcessor.getBeanClass(SpringBeanProcessor.java:456)
      	at org.jboss.resteasy.plugins.spring.SpringBeanProcessor.processBean(SpringBeanProcessor.java:280)
      	at org.jboss.resteasy.plugins.spring.SpringBeanProcessor.postProcessBeanFactory(SpringBeanProcessor.java:258)
      	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:284)
      	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:181)
      	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:673)
      	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:519)
      	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
      	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:687)
      	at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
      	at org.springframework.boot.SpringApplication.run(SpringApplication.java:967)
      	at org.springframework.boot.SpringApplication.run(SpringApplication.java:956)
      	at com.paypal.init.SampleRaptorSpringBootApp.main(SampleRaptorSpringBootApp.java:20)
      

      Root cause

      I have found the root cause and also confirmed that there is a bug in Resteasy 3.0.12 that breaks Resteasy integration Spring (more specifically with SpringBoot 1.2.6).
      This bug was actually introduced in Resteasy 3.0.10.

      The bug is at this line of code in class SpringBeanProcessor (3.0.12 version).
      In version 3.0.9 that line is beanClass.getMethods() instead of beanClass.getDeclaredMethods(). Method getMethods considers parent classes, but getDeclaredMethods does not.

      The problem is that the bean in this case (named mvcContentNegotiationManager) is created from a factory bean class that actually is a parent class of the one referred by beanClass. Variable beanClass refers to WebMvcAutoConfiguration$EnableWebMvcConfiguration, and this Spring Configuration class has no @Bean annotated method called mvcContentNegotiationManager. However, its "grandparent" class, WebMvcConfigurationSupport, has it.

      Potential solution

      Probably changing this line back to beanClass.getMethods(), instead of beanClass.getDeclaredMethods(), would solve the problem, but I don't know why that was changed in the first place (starting in Resteasy 3.0.10).

              patriot1burke@gmail.com Bill Burke (Inactive)
              fabiocarvalho_jira Fábio Carvalho (Inactive)
              Votes:
              7 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved: