@UseOverridePropertiesWithPropertiesComponent does not seem to work for field/method injected properties when using CamelTestContextBootstrapper

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

@UseOverridePropertiesWithPropertiesComponent does not seem to work for field/method injected properties when using CamelTestContextBootstrapper

Stig Døssing
Hi,

I'm trying to override properties in a Camel Spring project. In my production code, I have a field injected with

@Component
public class MyRouteBuilder extends  SpringRouteBuilder {

  @PropertyInject("{{MY_PROPERTY}} ")
  private String myProperty;

}

I normally load the value from a properties file using a BridgePropertyPlaceholderConfigurer.

In one of my tests, I'd like to replace the property. My test looks as follows:

@RunWith(CamelSpringRunner.class)
@BootstrapWith(CamelTestContextBootstrapper.class)
@ContextConfiguration(locations = {
    "classpath:META-INF/spring/my-properties.xml"
})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@UseAdviceWith
public class CitizenLookupPatientByOIDRouteTest {
  @Test
   public void test() {
      ...
   }

   @UseOverridePropertiesWithPropertiesComponent
  public static Properties overrideProperties() {
    Properties overrides = new Properties();
    overrides.setProperty("MY_PROPERTY", "some-value");
    return overrides;
  }
}

What I am seeing is that the injected field gets the value from the properties file, rather than the overridden value. Debugging this, I see that the field injection happens during Spring bean postprocessing, which is before the overrideProperties method is called.

parseUri:190, PropertiesComponent (org.apache.camel.component.properties)
parseUri:178, PropertiesComponent (org.apache.camel.component.properties)
resolvePropertyPlaceholders:2547, DefaultCamelContext (org.apache.camel.impl)
getInjectionPropertyValue:276, CamelPostProcessorHelper (org.apache.camel.impl)
injectFieldProperty:214, DefaultCamelBeanPostProcessor (org.apache.camel.impl)
doWith:174, DefaultCamelBeanPostProcessor$1 (org.apache.camel.impl)
doWithFields:74, ReflectionHelper (org.apache.camel.util)
injectFields:170, DefaultCamelBeanPostProcessor (org.apache.camel.impl)
postProcessBeforeInitialization:83, DefaultCamelBeanPostProcessor (org.apache.camel.impl)
postProcessBeforeInitialization:154, CamelBeanPostProcessor (org.apache.camel.spring)
applyBeanPostProcessorsBeforeInitialization:419, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1737, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:576, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:498, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:320, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 1286771084 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$40)
getSingleton:222, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:318, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:199, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:846, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:863, AbstractApplicationContext (org.springframework.context.support)
refresh:546, AbstractApplicationContext (org.springframework.context.support)
loadContext:152, CamelSpringTestContextLoader (org.apache.camel.test.spring)
loadContext:89, CamelSpringTestContextLoader (org.apache.camel.test.spring)
loadContextInternal:99, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache)
loadContext:117, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache)
getApplicationContext:108, DefaultTestContext (org.springframework.test.context.support)
injectDependencies:118, DependencyInjectionTestExecutionListener (org.springframework.test.context.support)
prepareTestInstance:83, DependencyInjectionTestExecutionListener (org.springframework.test.context.support)
prepareTestInstance:246, TestContextManager (org.springframework.test.context)
createTest:227, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)

The code causing the injection in CamelSpringContextLoader is this https://github.com/apache/camel/blob/camel-2.23.1/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java#L152. A few lines below, the properties override code is called.

It is possible to work around this by never field/method injecting properties, but I think it would be nicer if this worked. Is there something I can do to delay the field injection until after the property override? Should I raise an issue for this on the Camel issue tracker?

Reply | Threaded
Open this post in threaded view
|

Re: @UseOverridePropertiesWithPropertiesComponent does not seem to work for field/method injected properties when using CamelTestContextBootstrapper

Claus Ibsen-2
Hi

You can try to patch the code and move that handle method up before
and see what happens.

On Thu, May 16, 2019 at 2:14 PM Stig Døssing
<[hidden email]> wrote:

>
> Hi,
>
> I'm trying to override properties in a Camel Spring project. In my production code, I have a field injected with
>
> @Component
> public class MyRouteBuilder extends  SpringRouteBuilder {
>
>   @PropertyInject("{{MY_PROPERTY}} ")
>   private String myProperty;
>
> }
>
> I normally load the value from a properties file using a BridgePropertyPlaceholderConfigurer.
>
> In one of my tests, I'd like to replace the property. My test looks as follows:
>
> @RunWith(CamelSpringRunner.class)
> @BootstrapWith(CamelTestContextBootstrapper.class)
> @ContextConfiguration(locations = {
>     "classpath:META-INF/spring/my-properties.xml"
> })
> @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
> @UseAdviceWith
> public class CitizenLookupPatientByOIDRouteTest {
>   @Test
>    public void test() {
>       ...
>    }
>
>    @UseOverridePropertiesWithPropertiesComponent
>   public static Properties overrideProperties() {
>     Properties overrides = new Properties();
>     overrides.setProperty("MY_PROPERTY", "some-value");
>     return overrides;
>   }
> }
>
> What I am seeing is that the injected field gets the value from the properties file, rather than the overridden value. Debugging this, I see that the field injection happens during Spring bean postprocessing, which is before the overrideProperties method is called.
>
> parseUri:190, PropertiesComponent (org.apache.camel.component.properties)
> parseUri:178, PropertiesComponent (org.apache.camel.component.properties)
> resolvePropertyPlaceholders:2547, DefaultCamelContext (org.apache.camel.impl)
> getInjectionPropertyValue:276, CamelPostProcessorHelper (org.apache.camel.impl)
> injectFieldProperty:214, DefaultCamelBeanPostProcessor (org.apache.camel.impl)
> doWith:174, DefaultCamelBeanPostProcessor$1 (org.apache.camel.impl)
> doWithFields:74, ReflectionHelper (org.apache.camel.util)
> injectFields:170, DefaultCamelBeanPostProcessor (org.apache.camel.impl)
> postProcessBeforeInitialization:83, DefaultCamelBeanPostProcessor (org.apache.camel.impl)
> postProcessBeforeInitialization:154, CamelBeanPostProcessor (org.apache.camel.spring)
> applyBeanPostProcessorsBeforeInitialization:419, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
> initializeBean:1737, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
> doCreateBean:576, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
> createBean:498, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
> lambda$doGetBean$0:320, AbstractBeanFactory (org.springframework.beans.factory.support)
> getObject:-1, 1286771084 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$40)
> getSingleton:222, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
> doGetBean:318, AbstractBeanFactory (org.springframework.beans.factory.support)
> getBean:199, AbstractBeanFactory (org.springframework.beans.factory.support)
> preInstantiateSingletons:846, DefaultListableBeanFactory (org.springframework.beans.factory.support)
> finishBeanFactoryInitialization:863, AbstractApplicationContext (org.springframework.context.support)
> refresh:546, AbstractApplicationContext (org.springframework.context.support)
> loadContext:152, CamelSpringTestContextLoader (org.apache.camel.test.spring)
> loadContext:89, CamelSpringTestContextLoader (org.apache.camel.test.spring)
> loadContextInternal:99, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache)
> loadContext:117, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache)
> getApplicationContext:108, DefaultTestContext (org.springframework.test.context.support)
> injectDependencies:118, DependencyInjectionTestExecutionListener (org.springframework.test.context.support)
> prepareTestInstance:83, DependencyInjectionTestExecutionListener (org.springframework.test.context.support)
> prepareTestInstance:246, TestContextManager (org.springframework.test.context)
> createTest:227, SpringJUnit4ClassRunner (org.springframework.test.context.junit4)
>
> The code causing the injection in CamelSpringContextLoader is this https://github.com/apache/camel/blob/camel-2.23.1/components/camel-test-spring/src/main/java/org/apache/camel/test/spring/CamelSpringTestContextLoader.java#L152. A few lines below, the properties override code is called.
>
> It is possible to work around this by never field/method injecting properties, but I think it would be nicer if this worked. Is there something I can do to delay the field injection until after the property override? Should I raise an issue for this on the Camel issue tracker?
>


--
Claus Ibsen
-----------------
http://davsclaus.com @davsclaus
Camel in Action 2: https://www.manning.com/ibsen2