Uploaded image for project: 'Camel'
  1. Camel
  2. CAMEL-16235

camel-servlet-starter does not ServletComponent

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • 3.7.0
    • 3.9.0
    • camel-servlet
    • None
    • Unknown

    Description

      Below is my dependency configuration in build.gradle script of my project

      ext {
          versions = [
              camel : "3.5.0",
              springBoot : "2.3.0.RELEASE",
          ]
      }
      
      dependencies {
          compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: versions.springBoot    
          compile group: 'org.apache.camel.springboot', name: 'camel-servlet-starter', version: versions.camel    
          compile group: 'javax.inject', name: 'javax.inject', version: '1'    
      
          compile group: 'org.apache.camel', name: 'camel-core',          version: versions.camel
          compile group: 'org.apache.camel', name: 'camel-http',          version: versions.camel
          compile group: 'org.apache.camel', name: 'camel-jackson',       version: versions.camel
          compile group: 'org.apache.camel', name: 'camel-rest-openapi',  version: versions.camel
          compile group: 'org.apache.camel', name: 'camel-aws2-s3',       version: versions.camel    
          compile group: 'org.apache.camel', name: 'camel-swagger-java',  version: versions.camel    
      }
      

       Below is a RouteBuilder class

      public class MyRouteBuilder extends RouteBuilder {
          @Override
          public void configure() throws Exception {
              this.restConfiguration().bindingMode(RestBindingMode.json)
                  .clientRequestValidation(true).apiProperty("api.title", "MyAPI") 
                  .apiProperty("api.version", "1.0").apiProperty("cors", "true")
                  .apiContextPath("api-doc");
          }
      }

       

      When I start the Spring Boot application the camel-servlet-starter starts the ServletComponent and I can access the api-doc URL. But the same code fails when I upgrade the Camel version to 3.7.0.

      This is what I discovered when I tried to understand why camel-servlet-starter starts in 3.5.0 and fails in 3.7.0

      Below is the definition of Servlet Component Bean in org.apache.camel.component.servlet.springboot.ServletComponentAutoConfiguration class of camel-servlet-starter-3.5.x

      @Lazy    
      @Bean(name = "servlet-component")    
      @ConditionalOnMissingBean(ServletComponent.class)    
      public ServletComponent configureServletComponent() throws Exception {          
          ServletComponent component = new ServletComponent();        
          component.setCamelContext(camelContext);
      }

      When Spring starts Camel routes, it asks RestApiEndpoint to create REST API Consumer and Spring initializes the Servlet Component by invoking ServletComponentAutoConfiguration.configureServletComponent(). 

      This is changed in camel-servlet-starter-3.7.x

      @Lazy 
      @Bean 
      public ComponentCustomizer configureServletComponent() { 
          return new ComponentCustomizer() { 
              @Override 
              public void configure(String name, Component target) {  
                  CamelPropertiesHelper.copyProperties(camelContext, configuration, target); 
              } 
      
              @Override 
              public boolean isEnabled(String name, Component target) { 
                  return HierarchicalPropertiesEvaluator.evaluate(applicationContext,   
                               "camel.component.customizer", 
                                "camel.component.servlet.customizer") 
                          && target instanceof ServletComponent; } 
              }; 
      }

      Spring fails to start CamelContext with the below exception stack trace:

      org.apache.camel.FailedToStartRouteException: Failed to start route route1 because of null 
        at org.apache.camel.impl.engine.RouteService.warmUp(RouteService.java:122) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.InternalRouteStartupManager.doWarmUpRoutes(InternalRouteStartupManager.java:270) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.InternalRouteStartupManager.safelyStartRouteServices(InternalRouteStartupManager.java:157) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.InternalRouteStartupManager.doStartOrResumeRoutes(InternalRouteStartupManager.java:115) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.AbstractCamelContext.doStartCamel(AbstractCamelContext.java:2889) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.AbstractCamelContext.doStartContext(AbstractCamelContext.java:2702) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.AbstractCamelContext.doStart(AbstractCamelContext.java:2665) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.spring.boot.SpringBootCamelContext.doStart(SpringBootCamelContext.java:43) ~[camel-spring-boot-3.7.0.jar:3.7.0] 
        at org.apache.camel.support.service.BaseService.start(BaseService.java:115) ~[camel-api-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.AbstractCamelContext.start(AbstractCamelContext.java:2431) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.spring.SpringCamelContext.start(SpringCamelContext.java:130) ~[camel-spring-3.7.0.jar:3.7.0] 
        at org.apache.camel.spring.SpringCamelContext.onApplicationEvent(SpringCamelContext.java:167) ~[camel-spring-3.7.0.jar:3.7.0] 
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:203) ~[spring-context-5.3.1.jar:5.3.1] 
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:196) ~[spring-context-5.3.1.jar:5.3.1] 
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:161) ~[spring-context-5.3.1.jar:5.3.1] 
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:426) ~[spring-context-5.3.1.jar:5.3.1] 
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:383) ~[spring-context-5.3.1.jar:5.3.1] 
        at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:945) ~[spring-context-5.3.1.jar:5.3.1] 
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:591) ~[spring-context-5.3.1.jar:5.3.1] 
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144) ~[spring-boot-2.4.0.jar:2.4.0] 
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767) ~[spring-boot-2.4.0.jar:2.4.0] 
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) ~[spring-boot-2.4.0.jar:2.4.0] 
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426) ~[spring-boot-2.4.0.jar:2.4.0] 
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:326) ~[spring-boot-2.4.0.jar:2.4.0] 
        at com.guidewire.surepath.document.management.box.DocumentManagementBoxApplication.main(DocumentManagementBoxApplication.java:16) ~[main/:na]
      Caused by: java.lang.IllegalStateException: Cannot find RestApiConsumerFactory in Registry or as a Component to use 
        at org.apache.camel.component.rest.RestApiEndpoint.createConsumer(RestApiEndpoint.java:278) ~[camel-rest-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.DefaultRoute.addServices(DefaultRoute.java:575) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.DefaultRoute.onStartingServices(DefaultRoute.java:160) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.RouteService.doWarmUp(RouteService.java:150) ~[camel-base-engine-3.7.0.jar:3.7.0] 
        at org.apache.camel.impl.engine.RouteService.warmUp(RouteService.java:120) ~[camel-base-engine-3.7.0.jar:3.7.0]

      Spring starts CamelContext successfully if I register the servlet component in the RouteBuilder class

      Below is a RouteBuilder class

      public class MyRouteBuilder extends RouteBuilder {
          @Override
          public void configure() throws Exception {
              this.restConfiguration().bindingMode(RestBindingMode.json)
                  .clientRequestValidation(true).apiProperty("api.title", "MyAPI") 
                  .apiProperty("api.version", "1.0").apiProperty("cors", "true")
                  .component("servlet")             
                  .apiContextPath("api-doc");
          }
      }

       

      Are developers mandated to register ServletComponent in the RouteBuilder class?

       

      Attachments

        Activity

          People

            davsclaus Claus Ibsen
            skuna Siva Kuna
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: