Kotlin - lateinit TestRestTemplate not initializing for integration tests - spring

I have a spring-boot app in development using kotlin - overall things are going well. (spring 1.5.6.RELEASE, kotlin 1.1.4-3)
Anyway, I was adding my first controller test after reviewing some example code, and am running into this annoying error:
kotlin.UninitializedPropertyAccessException: lateinit property restTemplate has not been initialized
kotlin.UninitializedPropertyAccessException: lateinit property testRestTemplate has not been initialized
at com.thingy.controllers.ProductSetControllerTest.getTestRestTemplate(ProductSetControllerTest.kt:16)
at com.thingy.controllers.ProductSetControllerTest.testGet(ProductSetControllerTest.kt:20)
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:80)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1198)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1123)
at org.testng.TestNG.run(TestNG.java:1031)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:123)
Here's the test class
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.test.context.junit4.SpringRunner
import org.testng.Assert
import org.testng.annotations.Test
#RunWith(SpringRunner::class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ProductSetControllerTest {
#Autowired
lateinit var restTemplate: TestRestTemplate
#Test
fun testGet() {
val forObject = restTemplate.getForObject("/", String::class.java)
Assert.assertEquals(forObject, "gettest")
}
}
Some addl things I've tried:
- ensured I'm not using deprecated TestRestTemplate
- tried using setter injection instead of field injection, but was a waste of time.
- disabled kotlin compiler plugins

Spring Boot does not automatically instantiate TestRestTemplate bean(duh!).
You need to define it yourself and then you will be able to use it.
#Bean
open fun restTemplate(): TestRestTemplate {
return TestRestTemplate()
}

Related

Dropwizard testing - ResourceTestRule throwing NoClassDefFoundError: ch/qos/logback/core/filter/Filter

I am using dropwizard 1.2.4 with log4j 1.2.17. I have followed the instructions as mentioned below
https://github.com/arteam/dropwizard-nologback/
It is throwing the exception like below during unit testing.
java.lang.NoClassDefFoundError: ch/qos/logback/core/filter/Filter
at io.dropwizard.testing.junit.ResourceTestRule.<clinit>(ResourceTestRule.java:34)
at com.vnera.restapilayer.api.resources.ApiInfoControllerTest.<clinit>(ApiInfoControllerTest.java:25)
at sun.misc.Unsafe.ensureClassInitialized(Native Method)
at sun.reflect.UnsafeFieldAccessorFactory.newFieldAccessor(UnsafeFieldAccessorFactory.java:43)
at sun.reflect.ReflectionFactory.newFieldAccessor(ReflectionFactory.java:156)
at java.lang.reflect.Field.acquireFieldAccessor(Field.java:1088)
at java.lang.reflect.Field.getFieldAccessor(Field.java:1069)
at java.lang.reflect.Field.get(Field.java:393)
at org.junit.runners.model.FrameworkField.get(FrameworkField.java:73)
at org.junit.runners.model.TestClass.getAnnotatedFieldValues(TestClass.java:230)
at org.junit.runners.ParentRunner.classRules(ParentRunner.java:255)
at org.junit.runners.ParentRunner.withClassRules(ParentRunner.java:244)
at org.junit.runners.ParentRunner.classBlock(ParentRunner.java:194)
at org.junit.runners.ParentRunner.run(ParentRunner.java:362)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ClassNotFoundException: ch.qos.logback.core.filter.Filter
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 19 more
My test code looks like below
import io.dropwizard.testing.junit.ResourceTestRule;
import org.junit.Assert;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import javax.ws.rs.core.Response;
import static org.mockito.Mockito.mock;
#Category(value = UnitTest.class)
public class ApiInfoControllerTest {
private static ApiNonFunctionalHandler nonFunctionalHandler = mock(ApiNonFunctionalHandler.class);
private static ApiFilter apiFilter = new ApiFilter(nonFunctionalHandler);
private static final String authToken = "NetworkInsight xTyAGJmZ8nU8yJDP7LnA8Q==";
#ClassRule
public static final ResourceTestRule resources = ResourceTestRule.builder()
.addResource(new ApiInfoController())
.addProvider(apiFilter).build();
#Test
public void testApiVersion() throws Exception {
Response response = resources.client()
.target(ApiConstants.INFO_BASE_URL + "/version")
.request()
.header("Authorization", authToken)
.buildGet().invoke();
Assert.assertNotNull(response);
Assert.assertEquals(response.toString(), Response.Status.OK.getStatusCode(), response.getStatus());
final VersionResponse actualError = response.readEntity(VersionResponse.class);
Assert.assertEquals(actualError.getApiVersion(), ApiConstants.API_VERSION);
}
}
My main application is working fine. The configuration.yaml for main application looks like below
# Change default server ports
server:
applicationConnectors:
- type: http
port: 8123
adminConnectors:
- type: http
port: 8124
requestLog:
type: external
logging:
type: external
Can someone let me know what could be going wrong and how can I get around this?
EDIT
Output of mvn dependency:tree is placed here as I am hitting the character limit here.
This is a bug in dropwizard 1.2.4 as discussed below
https://github.com/dropwizard/dropwizard/pull/2338

Mockito/Powermock not working as expected with Kotlin

I'm using mockito/powermock version 1.7.0, Spring Boot 2.0.0 M2, Kotlin 1.3.0.
I'm testing a Spring #Service class, that inject a Repository.
I want to mock that repository on my tests, so I can just test the class itself.
I'm new to Kotlin, but I come from Java, so I tried doing this "the java way", but probably I'm missing something...
Here is my Service interface:
interface MyService {
fun create(myObject: MyObject): MyObject
}
... and its implementation:
#Service
class DefaultMyService : MyService {
#Autowired
lateinit var myRepository: MyRepository
override fun create(myObject: MyObject): MyObject = this.myRepository.insert(myObject)
}
Here is my repository (I'm using Spring Data with Mongo):
interface MyRepository: MongoRepository<MyObject, String>
Here is my test class:
#RunWith(PowerMockRunner::class)
#PrepareForTest(MyService::class)
class MyServiceTest {
#Mock
lateinit var myRepository: MyRepository
#InjectMocks
lateinit var myService: MyService
#Test
fun shouldDoSomething() {
val myObject = MyObject(name = "Marco")
`when`(myRepository.insert(myObject)).thenReturn(myObject)
assertEquals(myObject.name, this.myService.create(myObject).name)
}
}
When I run this test, an exception occurs:
Exception in thread "main" java.lang.NoClassDefFoundError: org/mockito/exceptions/Reporter
at sun.reflect.GeneratedSerializationConstructorAccessor5.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
at org.powermock.reflect.internal.WhiteboxImpl.newInstance(WhiteboxImpl.java:260)
at org.powermock.reflect.Whitebox.newInstance(Whitebox.java:139)
at org.powermock.api.extension.reporter.AbstractMockingFrameworkReporterFactory.getInstanceForClassLoader(AbstractMockingFrameworkReporterFactory.java:41)
at org.powermock.api.extension.reporter.AbstractMockingFrameworkReporterFactory.create(AbstractMockingFrameworkReporterFactory.java:35)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.getMockingFrameworkReporter(JUnit4TestSuiteChunkerImpl.java:140)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:119)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:57)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.ClassNotFoundException: org.mockito.exceptions.Reporter
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:202)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass1(DeferSupportingClassLoader.java:89)
at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:79)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 16 more
What am I doing wrong? I think it's an issue with some configuration, but I can't understand exactly where the mistake is.
It seems like that your mockito and powermock versions are not working very well together. You have to use versions which are compatible. See the compatibility matrix of powermock https://github.com/powermock/powermock/wiki/Mockito#supported-versions
Latest compatible is Mockito: 2.8.x with PowerMock: 1.7.0

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.

Why the cryptic MultipleFailureException error message with the SpringJUnit4ClassRunner.withAfterClasses method

Why is my spring test set up failing with the following not-so-useful error messages below? All suggestions are appreciated.
JUnit Output
java.lang.NoClassDefFoundError: org/junit/runners/model/MultipleFailureException
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.withAfterClasses(SpringJUnit4ClassRunner.java:188)
at org.junit.runners.ParentRunner.classBlock(ParentRunner.java:145)
at org.junit.runners.ParentRunner.run(ParentRunner.java:235)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run (SpringJUnit4ClassRunner.java:163)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: java.lang.ClassNotFoundException: org.junit.runners.model.MultipleFailureException
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 10 more
Console Output
INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Could not instantiate TestExecutionListener [org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttribute]
INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Could not instantiate TestExecutionListener [org.springframework.test.context.transaction.TransactionalTestExecutionListener]. Specify custom listener classes or make the default listener classes (and their required dependencies) available. Offending class: [org/springframework/transaction/interceptor/TransactionAttributeSource]
INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener#76959acc, org.springframework.test.context.support.DependencyInjectionTestExecutionListener#57e603e6, org.springframework.test.context.support.DirtiesContextTestExecutionListener#3e0a1e1f]
Here is the target snippet
#Service
public class PipApps {
#Resource( name = "apps" )
private Properties apps;
#Autowired
private SitePreferenceHandler sitePreferenceHandler;
#Autowired
private PipsTable pipsTable;
private SitePreference sitePreference;
private Device device;
public PipApps( HttpServletRequest request, HttpServletResponse response ){
sitePreference = sitePreferenceHandler.handleSitePreference( request, response );
device = DeviceUtils.getRequiredCurrentDevice( request );
}
public Properties getApps(){
return apps;
}
public Device getDevice(){
return device;
}
public SitePreference getSitePreference(){
return sitePreference;
}
public DeviceRouteTable getPipsTable(){
return pipsTable;
}
}
And the test snippet
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration( locations={"src/test/resources/PipAppsTest-context.xml"} )
public class PipAppsTest {
#Mock
SitePreferenceHandler sitePreferenceHandler;
#Autowired
PipApps pipApps;
...
}
Update -- September 2015
Spring Framework 4.2.2 throws a more meaningful exception if JUnit 4.9 is not in the classpath. See SPR-13521 for details.
The following is an excerpt from the class-level Javadoc for SpringJUnit4ClassRunner:
NOTE: As of Spring Framework 4.1, this class requires JUnit 4.9 or higher.
The class in question, MultipleFailureException, was introduced in JUnit 4.9.
So that's why your test is failing with the ClassNotFoundException.
Upgrading to JUnit 4.9 (or preferably 4.12) will therefore solve your problem.
Regards,
Sam (author of the Spring TestContext Framework)

Spring issue with profile

I am trying to get the variables uploaded directly based on environment in which the code is running. I wrote some code and ran into issues. Can you please point me what i am doing wrong.
WebAppInitializer.java
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext sc) throws ServletException {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.scan("com.configs");
root.getEnvironment().setActiveProfiles("dev");
root.refresh();
// Manages the lifecycle of the root application context
sc.addListener(new ContextLoaderListener(root));
// Handles requests into the application
ServletRegistration.Dynamic appServlet = sc.addServlet("appServlet",
new DispatcherServlet(new GenericWebApplicationContext()));
appServlet.setLoadOnStartup(1);
Set<String> mappingConflicts = appServlet.addMapping("/");
if (!mappingConflicts.isEmpty()) {
throw new IllegalStateException(
"'appServlet' could not be mapped to '/' due "
+ "to an existing mapping. This is a known issue under Tomcat versions "
+ "<= 7.0.14; see https://issues.apache.org/bugzilla/show_bug.cgi?id=51278");
}
}
}
DynamicConfig.java
#Configuration
#Profile("dev")
#PropertySource("classpath:/devel.properties")
public class DynamicConfig {
#Autowired
Environment env;
#Bean
public TestClass testClass(){
TestClass testClass = new TestClass();
testClass.setEnvironment(env.getProperty("environment"));
return testClass;
}
}
TestClass is simple class with one instance variable which will come from config based on environment.
TestCase:
package com.tester;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.configs.DynamicConfig;
import com.configs.EnvironmentDetector;
import com.tester.TestClass;
public class TestClassTest {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DynamicConfig.class);
#Test
public void test(){
ApplicationContext context = new AnnotationConfigApplicationContext(DynamicConfig.class);
context.getEnvironment().setActiveProfiles("dev");
context.scan("com.configs");
TestClass test = context.getBean(TestClass.class);
System.out.println(test.getEnvironment());
}
}
Now I am getting below error
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.282 sec <<< FAILURE!
test(com.tester.TestClassTest) Time elapsed: 0.279 sec <<< ERROR!
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.tester.TestClass] is defined: expected single bean but found 0:
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:280)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1106)
at com.tester.TestClassTest.test(TestClassTest.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:146)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
at $Proxy0.invoke(Unknown Source)
at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:145)
at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:87)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)
When i remove the line #profile("dev") from the DynamicConfig.java code is running fine. But i want that. I want to create similar classes for prod.
Please help
Thanks
Update your test class to activate the profile. Currently you are activating it by adding the property in the WebApplicationInitializer which is not run in the context of your test.
One way to activate it would be doing the following, however it is not the only way:
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles({"dev"})
#ContextConfiguration(classes = {DynamicConfig.class})
public class TestClassTest {
#Autowired
TestClass testClass;
#Test
public void test(){
System.out.println(testClass.getEnvironment());
}

Resources