CucumberBackendException: No qualifying bean of type - spring

When trying to run step defs with abstract class contains all the context configuration spring sees 2 differnt beans parent and stepdef
I'm using spring boot version: 2.6.4 , with Junit 5 and cucumber version 7.2.3
#SpringBootTest(classes = CoreApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ContextConfiguration(classes = AbstractIntegrationTest.Config.class)
#CucumberContextConfiguration
public abstract class AbstractIntegrationTest implements En {}
#Suite
#IncludeEngines("cucumber")
#SelectClasspathResource("com/example/bdd")
#ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "com.example.bdd")
public class CucumberIntegrationTest {
}
public class MyStepdefs extends AbstractIntegrationTest{
public MyStepdefs() {
When("^client post to \"([^\"]*)\" with valid data$", (String arg0) -> {
});
Then("^the client receives status code of (\\d+)$", (Integer arg0) -> {
});
}
}
Exception Stack trace:
io.cucumber.core.backend.CucumberBackendException: No qualifying bean of type 'com.orange.ces.core.bdd.AbstractIntegrationTest' available: expected single matching bean but found 2: com.orange.ces.core.bdd.MyStepdefs,com.orange.ces.core.bdd.AbstractIntegrationTest
at io.cucumber.spring.TestContextAdaptor.notifyTestContextManagerAboutAfterTestMethod(TestContextAdaptor.java:124)
at io.cucumber.spring.TestContextAdaptor.stop(TestContextAdaptor.java:107)
at io.cucumber.spring.SpringFactory.stop(SpringFactory.java:161)
at io.cucumber.core.runner.Runner.disposeBackendWorlds(Runner.java:156)
at io.cucumber.core.runner.Runner.runPickle(Runner.java:78)
at io.cucumber.core.runtime.Runtime.lambda$executePickle$6(Runtime.java:128)
at io.cucumber.core.runtime.CucumberExecutionContext.lambda$runTestCase$3(CucumberExecutionContext.java:151)
at io.cucumber.core.runtime.RethrowingThrowableCollector.executeAndThrow(RethrowingThrowableCollector.java:23)
at io.cucumber.core.runtime.CucumberExecutionContext.runTestCase(CucumberExecutionContext.java:151)
at io.cucumber.core.runtime.Runtime.lambda$executePickle$7(Runtime.java:128)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at io.cucumber.core.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:249)
at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:118)
at io.cucumber.core.runtime.Runtime.lambda$runFeatures$3(Runtime.java:110)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.SliceOps$1$1.accept(SliceOps.java:199)
at java.base/java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1632)
at java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
at java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
at io.cucumber.core.runtime.Runtime.runFeatures(Runtime.java:111)
at io.cucumber.core.runtime.Runtime.lambda$run$0(Runtime.java:82)
at io.cucumber.core.runtime.Runtime.execute(Runtime.java:94)
at io.cucumber.core.runtime.Runtime.run(Runtime.java:80)
at io.cucumber.core.cli.Main.run(Main.java:87)
at io.cucumber.core.cli.Main.main(Main.java:30)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.orange.ces.core.bdd.AbstractIntegrationTest' available: expected single matching bean but found 2: com.orange.ces.core.bdd.MyStepdefs,com.orange.ces.core.bdd.AbstractIntegrationTest
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1271)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:494)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:349)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1172)
at io.cucumber.spring.TestContextAdaptor.notifyTestContextManagerAboutAfterTestMethod(TestContextAdaptor.java:120)
... 30 more

In case you have several step definition classes, you can create a stub class with annotations only
#ContextConfiguration(classes = AbstractIntegrationTest.Config.class)
#CucumberContextConfiguration
public class StubConfig { }
Place it into a separate package and mention it in #CucumberOptions (if you have it)
Another ugly workaround:(

Related

conditional class not detected on mvn clean package

I have the following conditional class that should be unseen unless some other class annotates itself with a custom annotation:
#ConditionalOnBean(MyConf.class)
#Service
#RequiredArgsConstructor
public class CondClass{
public void method() throws MessagingException
Then I have a spring boot test:
#SpringBootTest
public void myTest{
It works fine if I manually execute it, but if I do:
mvn clean package
I get:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: java.lang.IllegalStateException: Failed to introspect Class
[it.bmed.medmad.arch.common.websocket.service.impl.CondClass] from ClassLoader
[sun.misc.Launcher$AppClassLoader#18b4aac2]
Caused by: java.lang.NoClassDefFoundError: org/springframework/messaging/MessagingException
Caused by: java.lang.ClassNotFoundException:
org.springframework.messaging.MessagingException
Indeed that MessagingException is on a dependency that is not included, but I would expect that the whole class is not inspected because of the annotation.
Add #ConditionalOnClass(MyConf.class), too:
#ConditionalOnClass(MyConf.class)
#ConditionalOnBean(MyConf.class)
#Service
#RequiredArgsConstructor
public class CondClass {
// ...
}
sample: official usage

how to override Spring Boot autowired component during testing

I'm trying to write tests for a Spring Boot batch application.
I have an interface "WsaaClient" and two implementations, I need to use one of them for normal execution and the other for testing purposes.
In the project, I have FCEClient class that has an autowired field "LoginManager", which has an autowired field "WsaaClient".
#Component
#Profile("!dev")
public class FCEClient implements IFCEClient {
#Autowired
LoginManager loginManager;
#Component
public class LoginManager {
#Autowired
WsaaClient client;
#Component
public class AfipWsaaClientSpring extends AfipWsaaClient {
AfipWsaaClient is in a non-spring maven dependency. It implements WsaaClient.
Running the Spring Batch application works well and AfipWsaaClientSpring is picked.
Now I want to write a test and need to use a dummy implementation for WsaaClient.
So I put under src/test/java this class:
#Component
public class TestWsaaClientSpring implements WsaaClient {
And this test:
#RunWith(SpringRunner.class)
#SpringBootTest
#ContextConfiguration
public class FceBatchApplicationTests {
private JobLauncherTestUtils jobLauncherTestUtils;
#Test
public void testJob() throws Exception {
JobExecution jobExecution = jobLauncherTestUtils.launchJob();
Assert.assertEquals("COMPLETED", jobExecution.getExitStatus().getExitCode());
}
}
Running it from JUnit Launcher on Eclipse throws:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'afipWsaaClientSpring' defined in file [/home/guish/vmshare/eclipsews/ec/ec-batch/target/classes/com/mycompany/AfipWsaaClientSpring.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mycompany.AfipWsaaClientSpring]: Constructor threw exception; nested exception is java.io.FileNotFoundException: ./wsaa_client.properties (No such file or directory)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1303) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1197) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
The FileNotFoundException is not relevant, the file is not present because of running as a test and Spring Boot should not pick the AfipWsaaClientSpring implementation.
How can I override the Autowired option in my test code and choose TestWsaaClientSpring instead?
And just in case, how can I prevent Spring Boot from instantiating the AfipWsaaClientSpring when running as a test?
Annotation #SpringBootTest has 'properties' attribute (https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/context/SpringBootTest.html).
so, you can specify spring profile like this,
#SpringBootTest(properties = {"spring.profiles.active=test"}, classes=MyConfiguration.class)
As mentioned by Charles Lee you could provide the active profile for SpringBootTest. Also you could do this with the annotation #ActiveProfile("theprofile") on your FceBatchApplicationTests class.

Testing Apache Camel with TestNG being enabled with Spring Boot

I have created an Apache Camel project using Spring Boot where I configure the routes in a #Component annotated class.
#Component
public final class EdlRouteBuilder extends RouteBuilder {
#Override
public final void configure() throws Exception {
//here is the setup of my Camel routes
...
}
}
Additionally I have a test class which extends AbstractCamelTestNGSpringContextTests containing one test method for testing my route.
Within the test class I need to start the CamelContext manually as I need to startup an embedded FTP server prior to testing.
#ActiveProfiles("test")
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = EdlApplication.class)
#DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
#DisableJmx(false)
#UseAdviceWith
#MockEndpoints("*")
#ContextConfiguration(classes=EdlRouteBuilder.class)
public class RouteTest extends AbstractCamelTestNGSpringContextTests {
private static final Logger LOG = LoggerFactory.getLogger(RouteTest.class);
#Autowired
private CamelContext camelContext;
...
#BeforeClass
public final void beforeClass() throws Exception {
private FtpServer ftpServer;
...
}
#BeforeClass
public final void beforeClass() throws Exception {
...
}
}
Problem is that the CamelContext is not autowired but I get the following excetption:
15:56:15.438 [main] ERROR org.springframework.test.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener#6ce139a4] to prepare test instance [com.rwetrading.integration.camel.mft.edl.RouteTest#7ee955a8]
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.rwetrading.integration.camel.mft.edl.RouteTest': Unsatisfied dependency expressed through field 'camelContext'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.apache.camel.CamelContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:581)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:367)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1340)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireBeanProperties(AbstractAutowireCapableBeanFactory.java:400)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:242)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:145)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:108)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:523)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:224)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:146)
at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:165)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:105)
at org.testng.TestRunner.privateRun(TestRunner.java:776)
at org.testng.TestRunner.run(TestRunner.java:634)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:425)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:420)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:385)
at org.testng.SuiteRunner.run(SuiteRunner.java:334)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1318)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1243)
at org.testng.TestNG.runSuites(TestNG.java:1161)
at org.testng.TestNG.run(TestNG.java:1129)
at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:132)
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:193)
at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:94)
at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:147)
at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.apache.camel.CamelContext' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1502)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1099)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1060)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:578)
... 37 common frames omitted
15:56:15.485 [main] INFO com.rwetrading.integration.camel.mft.edl.RouteTest - ********************************************************************************
15:56:15.485 [main] INFO com.rwetrading.integration.camel.mft.edl.RouteTest - Testing done: test(com.rwetrading.integration.camel.mft.edl.RouteTest)
15:56:15.487 [main] INFO com.rwetrading.integration.camel.mft.edl.RouteTest - Took: 0.001 seconds (1 millis)
15:56:15.487 [main] INFO com.rwetrading.integration.camel.mft.edl.RouteTest - ********************************************************************************

spring boot and camel throws direct.DirectConsumerNotAvailableException

I'm trying to get simple example of springboot and camel working but come undone. Not sure what i'm doing wrong. in the gradle build i've included so far
dependencies {
compile 'org.apache.camel:camel-spring-boot-starter:2.18.4'
compile 'org.apache.camel:camel-groovy:2.18.4'
compile 'org.apache.camel:camel-stream:2.18.4'
compile 'org.codehaus.groovy:groovy-all:2.4.11'
testCompile group: 'junit', name: 'junit', version: '4.11'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
i've create a DirectRoute component like this
#Component
class DirectRoute extends RouteBuilder{
#Override
void configure () throws Exception {
from ("direct:in") //tried stream:in also
.to ("stream:out")
}
}
I then have a driver bean that try's to invoke the route
#Component
public class HelloImpl implements Hello {
#Produce(uri = "direct:in")
private ProducerTemplate template;
#Override
public String say(String value) throws ExecutionException, InterruptedException {
assert template
println "def endpoint is : " + template.getDefaultEndpoint()
return template.sendBody (template.getDefaultEndpoint(), value)
}
}
lastly in the springboot application class i added a command line runner like this, that gets my bean from the spring context, and invokes the say method. I'm using groovy so i just passed a closure to the command line runner.
#Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
//return closure to run on startup - just list the beans enabled
{args ->
println("Let's inspect the beans provided by Spring Boot:")
String[] beanNames = ctx.getBeanDefinitionNames()
Arrays.sort(beanNames)
for (String beanName : beanNames) {
println(beanName)
}
println("call the direct:start route via the service")
Hello service = ctx.getBean("helloService")
def result = service.say("William")
println "service returned : $result "
}
}
when i run my application i get all the bean names printed out (that's ok), however when i invoke the direct:in via producer template i get this error (org.apache.camel.component.direct.DirectConsumerNotAvailableException) see below.
I was expecting the route to be triggered the name sent to see that arrive in the output stream - but this is what i get.
Caused by: org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange: Exchange[ID-MONSTER-PC2-58911-1496920205300-0-2]
at org.apache.camel.util.ObjectHelper.wrapCamelExecutionException(ObjectHelper.java:1795) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.util.ExchangeHelper.extractResultBody(ExchangeHelper.java:677) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:515) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.extractResultBody(DefaultProducerTemplate.java:511) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:163) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.ProducerTemplate$sendBody$0.call(Unknown Source) ~[na:na]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) [groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) [groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133) [groovy-all-2.4.11.jar:2.4.11]
at services.HelloImpl.say(HelloImpl.groovy:29) ~[main/:na]
at services.Hello$say.call(Unknown Source) ~[na:na]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) [groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) [groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) [groovy-all-2.4.11.jar:2.4.11]
at application.Application$_commandLineRunner_closure1.doCall(Application.groovy:47) ~[main/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93) ~[groovy-all-2.4.11.jar:2.4.11]
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325) ~[groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294) ~[groovy-all-2.4.11.jar:2.4.11]
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022) ~[groovy-all-2.4.11.jar:2.4.11]
at groovy.lang.Closure.call(Closure.java:414) ~[groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:54) ~[groovy-all-2.4.11.jar:2.4.11]
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:124) ~[groovy-all-2.4.11.jar:2.4.11]
at com.sun.proxy.$Proxy44.run(Unknown Source) ~[na:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776) [spring-boot-1.5.2.RELEASE.jar:1.5.2.RELEASE]
... 10 common frames omitted
Caused by: org.apache.camel.component.direct.DirectConsumerNotAvailableException: No consumers available on endpoint: direct://in. Exchange[ID-MONSTER-PC2-58911-1496920205300-0-2]
at org.apache.camel.component.direct.DirectProducer.process(DirectProducer.java:55) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:197) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.processor.DelegateAsyncProcessor.process(DelegateAsyncProcessor.java:97) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerCache.java:529) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache$1.doInProducer(ProducerCache.java:497) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache.doInProducer(ProducerCache.java:365) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache.sendExchange(ProducerCache.java:497) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.ProducerCache.send(ProducerCache.java:225) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.send(DefaultProducerTemplate.java:144) ~[camel-core-2.18.4.jar:2.18.4]
at org.apache.camel.impl.DefaultProducerTemplate.sendBody(DefaultProducerTemplate.java:161) ~[camel-core-2.18.4.jar:2.18.4]
What have i done wrong - and why does the producer template invocation on 'direct:in' (also tried stream in with same problem) not work? I thought that .to("stream:out") would be a consumer.
any pointers or advice gratefully received at this point
I have an update on my problems:
I had a subpackage with the application class annotated with #SpringBootApplication. So yes, unadorned it only scans subpackages.
you can add scanBasePackages= or scanBaseClasses= parameter, however when I tried doing a scan for single class, it seemed to scan the whole directory any way and grabbed the others as well.
I refactored the app to have a single root package with subpackages and elected to set the 'scanBasePakages to the new root package. but left the Application class in its own subpackage (personal preference only - documentation suggests leaving the Application in the root package)
you can now add other classes annotated with #Configuration to generate beans or use the basic #Component.
if you create Camel routes annotated with #Component they will be auto configured in the camelContext for you.
it appears by default that Spring isnt not starting the camelContext for you. When I checked the status of the context it shows as starting and not started. so in my commandLineRunner I had to start get the spring injected camelContext and had to start it myself, and exited it when I finished. I was slightly suprised as I thought SpringBootStarter would auto start the camelContext, but it appears not.
once you have Spring component scanning etc working and you start the camelContext, then problems with the org.apache.camel.component.direct.DirectConsumerNotAvailableException exception went away and things started to work - at least the baby examples I'm trying.
So revised structure now looks like this:
The revised ApplicationClass now looks like this with some simple println output to see the state of the context, and beans in the spring ctx. The helleoService bean is still the proxy I use to setup the producer template to call the DirectRoute.
package com.softwood.application
import groovy.util.logging.Slf4j
import org.apache.camel.CamelContext
import org.springframework.beans.factory.annotation.Autowired
import com.softwood.services.Hello
/**
* Created by willw on 07/06/2017.
*/
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean
#Slf4j //inject logger
#SpringBootApplication (scanBasePackages = ["com.softwood"]) //forces scan at parent
// same as #Configuration #EnableAutoConfiguration #ComponentScan with 'defaults' e.g. sub packages
public class Application {
#Autowired
ApplicationContext ctx
#Autowired
CamelContext camelContext
public static void main(String[] args) {
SpringApplication.run(Application.class, args)
}
#Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
//return closure to run on startup - just list the beans enabled
{args ->
println("Let's inspect the beans provided by Spring Boot:")
String[] beanNames = ctx.getBeanDefinitionNames()
Arrays.sort(beanNames)
for (String beanName : beanNames) {
println(beanName)
}
/* when component scan is working - bean routes are added
automatically to camel context via springBoot, however you do have to start
the camel context, yourself
*/
println "camelCtx has following components : " + camelContext.componentNames
println "camelCtx state is : " + camelContext.status
println "starting camel context"
camelContext.start()
println "camelCtx state now is : " + camelContext.status
//log.debug "wills logging call "
println("call the direct:start route via the service")
Hello service = ctx.getBean("helloService")
def result = service.say("William")
println "service returned : $result "
println "sleep 5 seconds "
sleep (5000)
println "stop camel context"
camelContext.stop()
println "camelCtx state now is : " + camelContext.status
}
}
}
That proxy is just registered as a simple bean like this in the spring context
package com.softwood.services
/**
* Created by willw on 07/06/2017.
*/
import org.apache.camel.Produce;
import org.apache.camel.ProducerTemplate
import org.springframework.stereotype.Component;
import java.util.concurrent.ExecutionException
#Component
public class HelloImpl implements Hello {
#Produce(uri = "direct:in") /* ?block=true */
private ProducerTemplate template
#Override
public String say(String value) throws ExecutionException, InterruptedException {
assert template
println "def endpoint is : " + template.getDefaultEndpoint()
//Future future = template.asyncSendBody(template.getDefaultEndpoint(), value)
//return future.get()
return template.sendBody (template.getDefaultEndpoint(), value)
}
}
The TimedRoute just sorts itself out with no template required to invoke in
package com.softwood.camelRoutes
/**
* Created by willw on 07/06/2017.
*/
import org.apache.camel.builder.RouteBuilder
import org.springframework.stereotype.Component
#Component
class TimedRoute extends RouteBuilder {
#Override
void configure () throws Exception {
from ("timer:foo")
.to ("log:com.softwood.application.Application?level=WARN")
}
}
My simple no-op file route isn't working (yet) and not sure why. I suspect I've not got the file config right somehow; some playing is required.
package com.softwood.camelRoutes
import org.apache.camel.builder.RouteBuilder
import org.springframework.stereotype.Component
/**
* Created by willw on 08/06/2017.
*/
#Component
class FileNoOpRoute extends RouteBuilder{
#Override
void configure () throws Exception {
from ("file:../com.softwood.file-inbox?recursive=true&noop=true&idempotent=true")
.to ("file:../com.softwood.file-outbox")
}
}
However the basics are not working and least camel is doing something whereas before I just had the exception and nothing.
I have found another question on Spring config highlighting some of the above also.

Setting up a 2nd Springboot application to use a #Autowired repository #Component from App 1 caused incorrect loading and REST requests broke

I have setup 2 Spring Boot applications. I am trying to #Autowire the repository from Application 1 in Application 2.
Both of these applications will be using REST to communicate back and forth. When I ran application 2 alone without the #Autowire of the repository for Application 1 I could correctly communicate with http://localhost:8082/runTestExecution via the #RestController HomeController class without an issue.
When I setup the #Autowire and #ComponentScan({"com.miw.mcb.server.repositories"}) so that I have access to the repositories of Application 1, Application 2 no longer functions correctly.
I am unable to reach the #RestController at http://localhost:8082/runTestExecution.
I also had a class which implemented CommandLineRunner which would run when I started up Spring Boot and this no longer runs either.
#Component
public class InitialRunner implements CommandLineRunner
Is this a issue because Application 1 also has a main class which loads #SpringBootApplication?
Can anyone suggest what is going wrong?
Below I have outlined my steps I took to add the jar of Application 1 and #Autowired class to Application 2
Here are the steps I took:
Setup maven to have the new library dependency and add it to the maven library mvn:install
Add Autowired bean to the HomeController class:
#RestController
public class HomeController {
#Autowired
TestSuiteRepository repo;
#RequestMapping(value = "/")
public String index() {
return "index";
}
#RequestMapping("runTestExecution")
public String runTestExecution(#RequestParam(value = "testExecutionID", required = true) String testExecutionID) {
return "Good";
}
}
Main class
#SpringBootApplication
public class AdbService {
public static void main(String[] args) {
SpringApplication.run(AdbService.class, args);
}
TestResultRepository class
package com.miw.mcb.server.repositories;
#Component
public interface TestResultRepository extends PagingAndSortingRepository<TestResult, Long> {
}
Add #Configuration and #ComponentScan, only supply the comment scan for the repositories package of the JAR file
Application 2 main class
#Configuration
#ComponentScan({"com.miw.mcb.server.repositories"})
#SpringBootApplication
public class AdbService {
public static void main(String[] args) {
SpringApplication.run(AdbService.class, args);
}
}
Application 1 Config Class
#Configuration
#ComponentScan({"com.miw.mcb.server.repositories"})
public class AppConfig {
}
Application 1 Main class
#SpringBootApplication
public class ReactAndSpringDataRestApplication {
public static void main(String[] args) {
SpringApplication.run(ReactAndSpringDataRestApplication.class, args);
}
}
Prior to adding the #ComponentScan I got the following stack trace:
2016-04-14 13:29:56 - Application startup failed
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'homeController': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: com.miw.mcb.server.repositories.TestSuiteRepository
com.miw.mcb.adbservice.HomeController.repo; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[com.miw.mcb.server.repositories.TestSuiteRepository] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
at
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766)
at
org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361)
at
org.springframework.boot.SpringApplication.run(SpringApplication.java:307)
at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1191)
at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1180)
at com.miw.mcb.adbservice.AdbService.main(AdbService.java:38) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497) at
org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:478)
at java.lang.Thread.run(Thread.java:745)
Try to use #EnableJpaRepositories instead of #ComponentScan for JpaRepositories:
#Configuration
//#ComponentScan({"com.miw.mcb.server.repositories"})
#EnableJpaRepositories("com.miw.mcb.server.repositories")
#SpringBootApplication
public class AdbService {
public static void main(String[] args) {
SpringApplication.run(AdbService.class, args);
}
}

Resources