You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Bede Bignell <Be...@msd.govt.nz.INVALID> on 2020/12/16 00:20:30 UTC

camel-spring-javaconfig test issue

Kia ora,

I'm having an issue writing a camel-spring-javaconfig test of a camel route where the RouteBuilder bean relies on Spring to inject fields annotated with @Value.

This repo: https://github.com/bedebignell/camel-bug-repro/ is able to reproduce the error by running 'mvn test -Dtest=nz.bignell.bede.camel.ReproduceUnableToLoadProperties'

The project uses the BOM versions Camel 3.6.0 and Spring 5.1.15.RELEASE and the dependencies (pom here: https://github.com/bedebignell/camel-bug-repro/blob/main/pom.xml): 
 * camel-core
 * camel-spring-javaconfig
 * camel-spring
 * spring-web
// Testing deps
 * camel-test
 * camel-test-spring
 * spring-test


The class extending RouteBuilder relies on Spring to inject to field with a value (@Value("${rankOfCamel}")   int rankOfCamel). When the Spring @TestPropertySource hasn't been loaded/processed so the int property is attempted to be loaded with the literal string "${rankOfCamel}" which errors throwing a NumberFormatException.

Here is the test class (class here: https://github.com/bedebignell/camel-bug-repro/blob/main/src/test/java/nz/bignell/bede/camel/ReproduceUnableToLoadProperties.java): 

package nz.bignell.bede.camel;

import org.apache.camel.ExchangePattern;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spring.javaconfig.SingleRouteCamelConfiguration;
import org.apache.camel.test.spring.CamelSpringDelegatingTestContextLoader;
import org.apache.camel.test.spring.CamelSpringRunner;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

@RunWith(CamelSpringRunner.class)
@ContextConfiguration(classes = {ReproduceUnableToLoadProperties.ExampleRouteBuilder.class, ReproduceUnableToLoadProperties.ContextConfig.class}, loader = CamelSpringDelegatingTestContextLoader.class)
@TestPropertySource(
    properties = {
        "rankOfCamel=1"
    }
)
public class ReproduceUnableToLoadProperties extends AbstractJUnit4SpringContextTests {
  @Autowired
  ProducerTemplate genericProducer;

  @Test
  public void checkProducer() {
    Assert.assertTrue(true);
    Assert.assertNotNull(genericProducer);
    Object resp = genericProducer.sendBody("direct:testA", ExchangePattern.InOut, "Klaus");
    Assert.assertEquals("hi Klaus", resp);
  }

  @Component
  public static class ExampleRouteBuilder extends RouteBuilder {
    @Value("${rankOfCamel}")
    int rankOfCamel;

    @Override
    public void configure() throws Exception {
      from("direct:testA")
          .log("Camel is number: " + rankOfCamel)
          .setBody(constant("hi ").append(body().convertToString()))
      ;
    }
  }

  @Configuration
  public static class ContextConfig extends SingleRouteCamelConfiguration {
    ReproduceUnableToLoadProperties.ExampleRouteBuilder exampleRouteBuilder;

    // Constructor Injection of Spring bean 'ExampleRouteBuilder'
    ContextConfig(ReproduceUnableToLoadProperties.ExampleRouteBuilder exampleRouteBuilder) {
      this.exampleRouteBuilder = exampleRouteBuilder;
    }

    @Override
    @Bean
    public RouteBuilder route() {
      return exampleRouteBuilder;
    }
  }
}

Regards
Bede


-------------------------------
This email and any attachments may contain information that is confidential and subject to legal privilege. If you are not the intended recipient, any use, dissemination, distribution or duplication of this email and attachments is prohibited. If you have received this email in error please notify the author immediately and erase all copies of the email and attachments. The Ministry of Social Development accepts no responsibility for changes made to this message or attachments after transmission from the Ministry.

-------------------------------

RE: camel-spring-javaconfig test issue

Posted by Bede Bignell <Be...@msd.govt.nz.INVALID>.
Nevermind, I have the solution.

My issue was a missing spring bean of type 'PropertySourcesPlaceholderConfigurer' that would then be able to use the property sources defined with the @TestPropertySource annotation.

The code change:

Add ' PropertySourcesPlaceholderConfigurer.class' to @ContextConfiguration(classes = {...}):

 - @ContextConfiguration(classes = {ReproduceUnableToLoadProperties.ExampleRouteBuilder.class, ReproduceUnableToLoadProperties.ContextConfig.class}, loader = CamelSpringDelegatingTestContextLoader.class)
 + @ContextConfiguration(classes = {PropertySourcesPlaceholderConfigurer.class, ReproduceUnableToLoadProperties.ExampleRouteBuilder.class, ReproduceUnableToLoadProperties.ContextConfig.class}, loader = CamelSpringDelegatingTestContextLoader.class)


Cheers
Bede

-----Original Message-----
From: Bede Bignell <Be...@msd.govt.nz.INVALID> 
Sent: Wednesday, 16 December 2020 1:21 PM
To: users@camel.apache.org
Subject: WARNING: Suspicious Sender: WARNING: Suspicious Sender: camel-spring-javaconfig test issue

Kia ora,

I'm having an issue writing a camel-spring-javaconfig test of a camel route where the RouteBuilder bean relies on Spring to inject fields annotated with @Value.

This repo: https://github.com/bedebignell/camel-bug-repro/ is able to reproduce the error by running 'mvn test -Dtest=nz.bignell.bede.camel.ReproduceUnableToLoadProperties'

The project uses the BOM versions Camel 3.6.0 and Spring 5.1.15.RELEASE and the dependencies (pom here: https://github.com/bedebignell/camel-bug-repro/blob/main/pom.xml): 
 * camel-core
 * camel-spring-javaconfig
 * camel-spring
 * spring-web
// Testing deps
 * camel-test
 * camel-test-spring
 * spring-test


The class extending RouteBuilder relies on Spring to inject to field with a value (@Value("${rankOfCamel}")   int rankOfCamel). When the Spring @TestPropertySource hasn't been loaded/processed so the int property is attempted to be loaded with the literal string "${rankOfCamel}" which errors throwing a NumberFormatException.

Here is the test class (class here: https://github.com/bedebignell/camel-bug-repro/blob/main/src/test/java/nz/bignell/bede/camel/ReproduceUnableToLoadProperties.java): 

package nz.bignell.bede.camel;

import org.apache.camel.ExchangePattern; import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.spring.javaconfig.SingleRouteCamelConfiguration;
import org.apache.camel.test.spring.CamelSpringDelegatingTestContextLoader;
import org.apache.camel.test.spring.CamelSpringRunner;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

@RunWith(CamelSpringRunner.class)
@ContextConfiguration(classes = {ReproduceUnableToLoadProperties.ExampleRouteBuilder.class, ReproduceUnableToLoadProperties.ContextConfig.class}, loader = CamelSpringDelegatingTestContextLoader.class)
@TestPropertySource(
    properties = {
        "rankOfCamel=1"
    }
)
public class ReproduceUnableToLoadProperties extends AbstractJUnit4SpringContextTests {
  @Autowired
  ProducerTemplate genericProducer;

  @Test
  public void checkProducer() {
    Assert.assertTrue(true);
    Assert.assertNotNull(genericProducer);
    Object resp = genericProducer.sendBody("direct:testA", ExchangePattern.InOut, "Klaus");
    Assert.assertEquals("hi Klaus", resp);
  }

  @Component
  public static class ExampleRouteBuilder extends RouteBuilder {
    @Value("${rankOfCamel}")
    int rankOfCamel;

    @Override
    public void configure() throws Exception {
      from("direct:testA")
          .log("Camel is number: " + rankOfCamel)
          .setBody(constant("hi ").append(body().convertToString()))
      ;
    }
  }

  @Configuration
  public static class ContextConfig extends SingleRouteCamelConfiguration {
    ReproduceUnableToLoadProperties.ExampleRouteBuilder exampleRouteBuilder;

    // Constructor Injection of Spring bean 'ExampleRouteBuilder'
    ContextConfig(ReproduceUnableToLoadProperties.ExampleRouteBuilder exampleRouteBuilder) {
      this.exampleRouteBuilder = exampleRouteBuilder;
    }

    @Override
    @Bean
    public RouteBuilder route() {
      return exampleRouteBuilder;
    }
  }
}

Regards
Bede


-------------------------------
This email and any attachments may contain information that is confidential and subject to legal privilege. If you are not the intended recipient, any use, dissemination, distribution or duplication of this email and attachments is prohibited. If you have received this email in error please notify the author immediately and erase all copies of the email and attachments. The Ministry of Social Development accepts no responsibility for changes made to this message or attachments after transmission from the Ministry.

-------------------------------

-------------------------------
This email and any attachments may contain information that is confidential and subject to legal privilege. If you are not the intended recipient, any use, dissemination, distribution or duplication of this email and attachments is prohibited. If you have received this email in error please notify the author immediately and erase all copies of the email and attachments. The Ministry of Social Development accepts no responsibility for changes made to this message or attachments after transmission from the Ministry.

-------------------------------