Redis cluster client creation in spring with spark - spring

I have a project which was connecting to standalone redis with client creation as :
public RedisConnectionFactory clientCreation() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(5);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
JedisConnectionFactory client = new JedisConnectionFactory(poolConfig);
client.setHostName(redisEastEndpoint);
client.setPort(redisEastPort);
client.setTimeout(redisTimeout);
return client;
the library version used for jedis and spring-data-redis are:
[INFO] +- redis.clients:jedis:jar:2.9.3:compile
[INFO] | \- org.apache.commons:commons-pool2:jar:2.6.2:compile
[INFO] +- org.springframework.data:spring-data-redis:jar:2.1.8.RELEASE:compile
[INFO] | +- org.springframework.data:spring-data-keyvalue:jar:2.1.8.RELEASE:compile
[INFO] | +- org.springframework:spring-oxm:jar:5.1.7.RELEASE:compile
[INFO] | +- org.springframework:spring-aop:jar:5.1.7.RELEASE:compile
[INFO] | \- org.springframework:spring-context-support:jar:5.1.7.RELEASE:compile
Now I have a requirement to move to cluster redis, and changed the client creation as
public RedisConnectionFactory clientCreation() {
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(5);
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(redisEastEndpoint);
if(StringUtils.isNotBlank(redisPassword)) {
redisClusterConfiguration.setPassword(redisPassword);
}
JedisClientConfiguration.JedisClientConfigurationBuilder jedisClientConfiguration = JedisClientConfiguration.builder();
jedisClientConfiguration.connectTimeout(Duration.ofSeconds(redisTimeout));
jedisClientConfiguration.usePooling().poolConfig(poolConfig);
return new JedisConnectionFactory(redisClusterConfiguration,
jedisClientConfiguration.build());
with this code change I am getting No reachable node in cluster as :
Caused by: org.springframework.data.redis.RedisConnectionFailureException: No reachable node in cluster; nested exception is redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster
at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:67)
at org.springframework.data.redis.connection.jedis.JedisExceptionConverter.convert(JedisExceptionConverter.java:41)
at org.springframework.data.redis.PassThroughExceptionTranslationStrategy.translate(PassThroughExceptionTranslationStrategy.java:44)
at org.springframework.data.redis.FallbackExceptionTranslationStrategy.translate(FallbackExceptionTranslationStrategy.java:42)
at org.springframework.data.redis.connection.jedis.JedisClusterConnection.convertJedisAccessException(JedisClusterConnection.java:760)
at org.springframework.data.redis.connection.jedis.JedisClusterStringCommands.convertJedisAccessException(JedisClusterStringCommands.java:556)
at org.springframework.data.redis.connection.jedis.JedisClusterStringCommands.setNX(JedisClusterStringCommands.java:186)
at org.springframework.data.redis.connection.DefaultedRedisConnection.setNX(DefaultedRedisConnection.java:288)
at org.springframework.data.redis.core.DefaultValueOperations.lambda$setIfAbsent$10(DefaultValueOperations.java:296)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:224)
at org.springframework.data.redis.core.RedisTemplate.execute(RedisTemplate.java:184)
at org.springframework.data.redis.core.AbstractOperations.execute(AbstractOperations.java:95)
at org.springframework.data.redis.core.DefaultValueOperations.setIfAbsent(DefaultValueOperations.java:296)
at org.springframework.data.redis.support.atomic.RedisAtomicLong.initializeIfAbsent(RedisAtomicLong.java:147)
at org.springframework.data.redis.support.atomic.RedisAtomicLong.<init>(RedisAtomicLong.java:92)
at org.springframework.data.redis.support.atomic.RedisAtomicLong.<init>(RedisAtomicLong.java:62)
at com.capitalone.api.customers.customerapi.service.config.RedisConfig.westESCID(RedisConfig.java:126)
at com.capitalone.api.customers.customerapi.service.config.RedisConfig$$EnhancerBySpringCGLIB$$88e1d043.CGLIB$westESCID$4(<generated>)
at com.capitalone.api.customers.customerapi.service.config.RedisConfig$$EnhancerBySpringCGLIB$$88e1d043$$FastClassBySpringCGLIB$$7889c704.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.capitalone.api.customers.customerapi.service.config.RedisConfig$$EnhancerBySpringCGLIB$$88e1d043.westESCID(<generated>)
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.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 39 more
Caused by: redis.clients.jedis.exceptions.JedisNoReachableClusterNodeException: No reachable node in cluster
at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnection(JedisSlotBasedConnectionHandler.java:61)
at redis.clients.jedis.JedisSlotBasedConnectionHandler.getConnectionFromSlot(JedisSlotBasedConnectionHandler.java:78)
at redis.clients.jedis.JedisClusterCommand.runWithRetries(JedisClusterCommand.java:113)
at redis.clients.jedis.JedisClusterCommand.runBinary(JedisClusterCommand.java:58)
at redis.clients.jedis.BinaryJedisCluster.setnx(BinaryJedisCluster.java:273)
at org.springframework.data.redis.connection.jedis.JedisClusterStringCommands.setNX(JedisClusterStringCommands.java:184)
... 59 more
}
since we have a spark application running in spark-2.1.3,due to version dependency I need to stick with the same spring-data-redis.
How would I be able to connect to cluster redis without the version upgrade of jedis and spring-data-redis?

It was spark 2.1.3 which was the bottleneck. Once spark was upgraded to 2.4.4, it worked as expected.

Related

Spring Webclient, The connection observed an error io.netty.handler.ssl.SslClosedEngineException: SSLEngine closed already

To make a call to an external payment gateway from the spring boot application, we are making use of webclient that comes along with webflux.
Stack:
spring-boot-starter-parent 2.5.3
spring-boot-starter-webflux 2.5.6
This API calls although at times, with negligible load (on our test environments) fail with the error The connection observed an error io.netty.handler.ssl.SslClosedEngineException: SSLEngine closed already
Here's the trace
[id:31e016c9-2, L:/x.xx.xxx.xx:56499 - R:xxx.payu.in/xy.xyy.xyyy.xyy:443] The connection observed an error
io.netty.handler.ssl.SslClosedEngineException: SSLEngine closed already
at io.netty.handler.ssl.SslHandler.wrap(SslHandler.java:861)
at io.netty.handler.ssl.SslHandler.wrapAndFlush(SslHandler.java:800)
at io.netty.handler.ssl.SslHandler.flush(SslHandler.java:781)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:750)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:742)
at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:728)
at io.netty.handler.logging.LoggingHandler.flush(LoggingHandler.java:304)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:750)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush(AbstractChannelHandlerContext.java:742)
at io.netty.channel.AbstractChannelHandlerContext.flush(AbstractChannelHandlerContext.java:728)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.flush(CombinedChannelDuplexHandler.java:531)
at io.netty.channel.ChannelOutboundHandlerAdapter.flush(ChannelOutboundHandlerAdapter.java:125)
at io.netty.channel.CombinedChannelDuplexHandler.flush(CombinedChannelDuplexHandler.java:356)
at io.netty.channel.AbstractChannelHandlerContext.invokeFlush0(AbstractChannelHandlerContext.java:750)
at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:765)
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:790)
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:758)
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:808)
at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1025)
at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:306)
at reactor.netty.http.HttpOperations.lambda$send$0(HttpOperations.java:128)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:125)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onNext(ScopePassingSpanSubscriber.java:90)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:127)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:169)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.request(ScopePassingSpanSubscriber.java:76)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:110)
at org.springframework.cloud.sleuth.instrument.reactor.ScopePassingSpanSubscriber.onSubscribe(ScopePassingSpanSubscriber.java:69)
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:96)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55)
at reactor.core.publisher.Mono.subscribe(Mono.java:4338)
at reactor.core.publisher.FluxConcatIterable$ConcatIterableSubscriber.onComplete(FluxConcatIterable.java:147)
at reactor.core.publisher.FluxConcatIterable.subscribe(FluxConcatIterable.java:60)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:110)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onSubscribe(MonoFlatMap.java:110)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.netty.http.client.HttpClientConnect$HttpIOHandlerObserver.onStateChange(HttpClientConnect.java:424)
at reactor.netty.ReactorNetty$CompositeConnectionObserver.onStateChange(ReactorNetty.java:654)
at reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.run(DefaultPooledConnectionProvider.java:287)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:384)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Unknown Source)
The web client bean that is used is as shown below
#Bean
public WebClient apiClient() {
HttpClient httpClient = HttpClient.create()
.wiretap("reactor.netty.http.client.HttpClient", LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL)
.responseTimeout(Duration.of(5, ChronoUnit.SECONDS));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
Dependency tree
+- org.springframework.boot:spring-boot-starter-webflux:jar:2.5.6:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-json:jar:2.5.3:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.12.4:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.12.4:compile
[INFO] | | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.12.4:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-reactor-netty:jar:2.5.3:compile
[INFO] | | \- io.projectreactor.netty:reactor-netty-http:jar:1.0.9:compile
[INFO] | | +- io.netty:netty-codec-http2:jar:4.1.66.Final:compile
[INFO] | | +- io.netty:netty-resolver-dns:jar:4.1.66.Final:compile
[INFO] | | | \- io.netty:netty-codec-dns:jar:4.1.66.Final:compile
[INFO] | | +- io.netty:netty-resolver-dns-native-macos:jar:osx-x86_64:4.1.66.Final:compile
[INFO] | | | \- io.netty:netty-transport-native-unix-common:jar:4.1.66.Final:compile
[INFO] | | +- io.netty:netty-transport-native-epoll:jar:linux-x86_64:4.1.66.Final:compile
[INFO] | | \- io.projectreactor.netty:reactor-netty-core:jar:1.0.9:compile
[INFO] | | \- io.netty:netty-handler-proxy:jar:4.1.66.Final:compile
[INFO] | | \- io.netty:netty-codec-socks:jar:4.1.66.Final:compile
[INFO] | +- org.springframework:spring-web:jar:5.3.9:compile
[INFO] | | \- org.springframework:spring-beans:jar:5.3.9:compile
[INFO] | \- org.springframework:spring-webflux:jar:5.3.9:compile
I know there are a lot of threads around this lately, but none of them have a solution.
Related threads:
javax.net.ssl.SSLException: SSLEngine closed already SSLEngine closed already in webclient (Springboot)
Spring WebClient: SSLEngine closed already
https://github.com/reactor/reactor-netty/issues/782
I updated the spring-boot-starter-parent version from 2.5.6 to 2.5.14, because 2.5.14 is a patch that uses reactor-netty-http version 1.0.19. 1.0.18 has an important fix related to how connections are handled.
Do not return the connection to the pool in case SSLEngine has been closed
This alone although didn't solve the issue.
Setting maxIdleTime did the trick. Here's what I did.
#Bean
public WebClient apiClient() {
/*
* Setting maxIdleTime as 10s, because servers usually have a keepAliveTimeout
* of 60s, after which the connection gets closed.
* If the connection pool has any connection which has been idle for over 10s, it
* will be evicted from the pool.
* Refer https://github.com/reactor/reactor-netty/issues/1318#issuecomment-702668918
*/
ConnectionProvider connectionProvider = ConnectionProvider.builder("connectionProvider")
.maxIdleTime(Duration.ofSeconds(10))
.build();
HttpClient httpClient = HttpClient.create(connectionProvider)
.wiretap("reactor.netty.http.client.HttpClient", LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL)
.responseTimeout(Duration.of(5, ChronoUnit.SECONDS));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}

Error when executing java -jar in spring boot app but not compiling

When I compile the application it works perfect, also test are passed but then if I execute java -jat in the compiled jar i had the following error when trying to load a jpg resource:
XXX#XXXX MINGW64 /d/Proyectos/PetApp/Back (master)
$ mvn clean install
###########################################################
__________ __ __ _____ ____________________
\______ \ _____/ |__/ |_ / _ \\______ \______ \
| ___// __ \ __\ __\/ /_\ \| ___/| ___/
| | \ ___/| | | | / | \ | | |
|____| \___ >__| |__| \____|__ /____| |____|
\/ \/
###########################################################
2019-10-16 15:29:59,977 INFO [main] org.springframework.boot.StartupInfoLogger: Starting BackEndTestApplicationTests on gggarrido10 with PID 4436 (started by gggarrido in D:\Proyectos\PetApp\Back)
2019-10-16 15:29:59,980 DEBUG [main] org.springframework.boot.StartupInfoLogger: Running with Spring Boot v2.1.6.RELEASE, Spring v5.1.8.RELEASE
2019-10-16 15:29:59,981 INFO [main] org.springframework.boot.SpringApplication: No active profile set, falling back to default profiles: default
2019-10-16 15:30:04,187 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBConfig: H2 DDBB selected
2019-10-16 15:30:08,767 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Initializacion of the DDBB
2019-10-16 15:30:09,002 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Role: ADMIN stored on DDBB
2019-10-16 15:30:09,006 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Role: USER stored on DDBB
2019-10-16 15:30:09,017 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Role: VISITOR stored on DDBB
2019-10-16 15:30:09,237 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Default AdminUser Created: AdminRoot/AdminPass246
2019-10-16 15:30:09,237 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Default Owner Created: Manolo Amelgas
2019-10-16 15:30:09,253 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Default Pet Created: Lucky
2019-10-16 15:30:14,019 INFO [main] org.springframework.boot.StartupInfoLogger: Started BackEndTestApplicationTests in 14.867 seconds (JVM running for 16.865)
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 16.279 s - in com.mashosoft.backEndTest.BackEndTestApplicationTests
[INFO] Running com.mashosoft.backEndTest.security.service.Impl.AuthServiceImplTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 s - in com.mashosoft.backEndTest.security.service.Impl.AuthServiceImplTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) # pettapp ---
[INFO] Building jar: D:\Proyectos\PetApp\Back\target\pettapp-V.RELEASE.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.1.8.RELEASE:repackage (repackage) # pettapp ---
[INFO] Replacing main artifact with repackaged archive
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) # pettapp ---
[INFO] Installing D:\Proyectos\PetApp\Back\target\pettapp-V.RELEASE.jar to D:\Tools\.m2\repository\com\mashosoft\pettapp\V.RELEASE\pettapp-V.RELEASE.jar
[INFO] Installing D:\Proyectos\PetApp\Back\pom.xml to D:\Tools\.m2\repository\com\mashosoft\pettapp\V.RELEASE\pettapp-V.RELEASE.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 34.801 s
[INFO] Finished at: 2019-10-16T15:30:18+02:00
[INFO] Final Memory: 49M/331M
[INFO] ------------------------------------------------------------------------
XXX#XXXX MINGW64 /d/Proyectos/PetApp/Back (master)
$ cd target/
XXX#XXX MINGW64 /d/Proyectos/PetApp/Back/target (master)
$ java -jar pettapp-V.RELEASE.jar
###########################################################
__________ __ __ _____ ____________________
\______ \ _____/ |__/ |_ / _ \\______ \______ \
| ___// __ \ __\ __\/ /_\ \| ___/| ___/
| | \ ___/| | | | / | \ | | |
|____| \___ >__| |__| \____|__ /____| |____|
\/ \/
###########################################################
2019-10-16 15:30:33,466 INFO [main] org.springframework.boot.StartupInfoLogger: Starting BackEndTestApplication vV.RELEASE on gggarrido10 with PID 11360 (D:\Proyectos\PetApp\Back\target\pettapp-V.RELEASE.jar started by gggarrido in D:\Proyectos\PetApp\Back\target)
2019-10-16 15:30:33,472 DEBUG [main] org.springframework.boot.StartupInfoLogger: Running with Spring Boot v2.1.6.RELEASE, Spring v5.1.8.RELEASE
2019-10-16 15:30:33,475 INFO [main] org.springframework.boot.SpringApplication: No active profile set, falling back to default profiles: default
2019-10-16 15:30:37,905 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBConfig: H2 DDBB selected
2019-10-16 15:30:41,331 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Initializacion of the DDBB
2019-10-16 15:30:41,792 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Role: ADMIN stored on DDBB
2019-10-16 15:30:41,795 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Role: USER stored on DDBB
2019-10-16 15:30:41,800 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Role: VISITOR stored on DDBB
2019-10-16 15:30:41,918 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Default AdminUser Created: AdminRoot/AdminPass246
2019-10-16 15:30:41,919 INFO [main] com.mashosoft.backEndTest.config.DDBB.DDBBInitializer: Default Owner Created: Manolo Amelgas
2019-10-16 15:30:41,963 ERROR [main] org.springframework.boot.SpringApplication: Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'DDBBInitializer': Invocation of init method failed; nested exception is com.mashosoft.backEndTest.exception.initialization.InitializationException
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:414)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1770)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1213)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1202)
at com.mashosoft.backEndTest.BackEndTestApplication.main(BackEndTestApplication.java:18)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:51)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)
Caused by: com.mashosoft.backEndTest.exception.initialization.InitializationException: null
at com.mashosoft.backEndTest.config.DDBB.DDBBInitializer.getTestPetImageAsMultipart(DDBBInitializer.java:123)
at com.mashosoft.backEndTest.config.DDBB.DDBBInitializer.init(DDBBInitializer.java:100)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:307)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
... 26 common frames omitted
This is the class:
package com.mashosoft.backEndTest.config.DDBB;
import com.mashosoft.backEndTest.component.ImageUploader;
import com.mashosoft.backEndTest.exception.errorcode.InitializationErrorCodes;
import com.mashosoft.backEndTest.exception.initialization.InitializationException;
import com.mashosoft.backEndTest.persistence.entity.Owner;
import com.mashosoft.backEndTest.persistence.entity.Pet;
import com.mashosoft.backEndTest.persistence.repository.OwnerRepository;
import com.mashosoft.backEndTest.persistence.repository.PetRepository;
import com.mashosoft.backEndTest.security.model.enums.Roles;
import com.mashosoft.backEndTest.security.persistence.entity.Role;
import com.mashosoft.backEndTest.security.persistence.entity.User;
import com.mashosoft.backEndTest.security.persistence.repository.RoleRepository;
import com.mashosoft.backEndTest.security.persistence.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
#Configuration
public class DDBBInitializer {
private static final Logger log = LoggerFactory.getLogger( DDBBInitializer.class );
#Autowired
private RoleRepository roleRepository;
#Autowired
private UserRepository userRepository;
#Autowired
private OwnerRepository ownerRepository;
#Autowired
private PetRepository petRepository;
#Autowired
private PasswordEncoder passwordEncoder;
#Value("${pettapp.config.default.username}")
private String defaultUsername;
#Value("${pettapp.config.default.email}")
private String defaultEmail;
#Value("${pettapp.config.default.password}")
private String defaultPassword;
#PostConstruct
private void init() {
log.info( "Initializacion of the DDBB" );
for (Roles role : Roles.values()) {
Role roleEntity = new Role( role );
roleRepository.save( roleEntity );
log.info( "Role: " + roleEntity.getRoleName() + " stored on DDBB" );
}
User defaultAdminUser = new User();
defaultAdminUser.setUserId( new BigDecimal( 1 ) );
defaultAdminUser.addOneRole( Roles.ADMIN );
defaultAdminUser.setUsername( defaultUsername );
defaultAdminUser.setPassword( passwordEncoder.encode( defaultPassword ) );
defaultAdminUser.setActive( true );
defaultAdminUser.setEmail( defaultEmail );
log.info( "Default AdminUser Created: " + defaultAdminUser.getUsername() + "/" + defaultPassword );
Owner adminOwnerProfile = new Owner();
adminOwnerProfile.setAddress( "Calle de jacinto Nº6 Bajo B" );
adminOwnerProfile.setName( "Manolo" );
adminOwnerProfile.setSurname( "Amelgas" );
adminOwnerProfile.setDefaulter( false );
adminOwnerProfile.setTelephoneNumber( "678987656 " );
adminOwnerProfile.setUser( defaultAdminUser );
defaultAdminUser.setOwner( adminOwnerProfile );
log.info( "Default Owner Created: " + adminOwnerProfile.getName() + " " + adminOwnerProfile.getSurname() );
Pet testPet = new Pet();
testPet.setAlive( true );
testPet.setBitrh( new Date() );
testPet.setBreed( "Carlino" );
testPet.setFur( "White" );
testPet.setName( "Lucky" );
String imageUrl = ImageUploader.uploadFile( getTestPetImageAsMultipart() );
testPet.setPictureUrl( imageUrl );
testPet.setOwner( adminOwnerProfile );
adminOwnerProfile.addPet( testPet );
log.info( "Default Pet Created: " + testPet.getName() );
userRepository.save( defaultAdminUser );
}
private MultipartFile getTestPetImageAsMultipart() {
try {
File file;
try {
file = new ClassPathResource( "/TestResources/DogImageForTest.jpg" ).getFile();
} catch (IOException e){
throw new InitializationException( InitializationErrorCodes.IMAGE_TEST_NOT_FOUND );
}
return new MockMultipartFile( "DogImageForTest.jpg", "DogImageForTest.jpg", "image/jpeg",
new FileInputStream( file ) );
} catch (Exception ignored) {
throw new InitializationException( InitializationErrorCodes.IMAGE_TEST_ERROR );
}
}
}
Why everything works fine but not when executing java -jar??
I dont know what to try because also in intellij when i press play or debug it works perfect.
The line that I know it is failing is the following:
file = new ClassPathResource( "/TestResources/DogImageForTest.jpg" ).getFile();
I have check inside the jar file and the image is inside:
Thanks in advance
I found the solution. Within a jar I cant use .getFile(); because it expect to have a file withint the system. Intead I used:
fileStream = new ClassPathResource( "/TestResources/DogImageForTest.jpg" ).getInputStream();
return new MockMultipartFile( "DogImageForTest.jpg", "DogImageForTest.jpg", "image/jpeg",fileStream );
With a stream it works perfect

Write Unit Test for API endpoint Controller

I have a spring controller which responds to API requests. I am trying to write Unit Tests for the controller class methods. I'll expose the controller code below:
AuditRestController.java
package com.audittrail.auditTrail.controller;
import com.audittrail.auditTrail.services.CreateAuditService;
import com.audittrail.auditTrail.services.GetAuditService;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.*;
import java.io.IOException;
#Controller("audit")
public class AuditRestController {
#Autowired
private GetAuditService getAuditService;
#Autowired
CreateAuditService createAuditService;
#JsonIgnoreProperties(ignoreUnknown = true)
#RequestMapping(value = "/audit/checkevent", method = RequestMethod.POST, consumes = {
MediaType.APPLICATION_JSON_VALUE })
#ResponseBody
public String create(#Validated #RequestBody String audi) throws IOException {
return createAuditService.createEvent(audi);
}
#JsonIgnoreProperties(ignoreUnknown = true)
#RequestMapping(value = "/audit/getevent", method = RequestMethod.POST, consumes = {
MediaType.APPLICATION_JSON_VALUE })
#ResponseBody
public String getObjectId(#Validated #RequestBody String audi) throws IOException {
return getAuditService.getEvent(audi);
}
}
One of the services that I am using is getAuditService.
GetAuditRestController.java
package com.audittrail.auditTrail.services;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.emc.leap.commons.client.web.LeapRestTemplate;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
#Service
public class GetAuditService {
#Autowired
private final RestTemplate clientTemplate;
public GetAuditService(#Qualifier(LeapRestTemplate.LEAP_CLIENT_REST_TEMPLATE) RestTemplate clientTemplate) {
this.clientTemplate = clientTemplate;
}
public String getEvent(String audi) throws JsonProcessingException, IOException {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = null;
jsonNode = objectMapper.readTree(audi);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<String>(headers);
String auditGetRequestURL = "some external url";
ResponseEntity<String> auditServiceGetRequest;
auditServiceGetRequest = this.clientTemplate.exchange(auditGetRequestURL, HttpMethod.GET, entity, String.class);
return auditServiceGetRequest.getBody().toString();
}
}
One thing to note is that this entire project does not have a main class. I am trying to build a non executable jar to be used in some other project. I have checked the jar without unit test cases and it is working fine. But I am also trying to write unit test cases.
This is bit of code that I am trying to execute.
AuditRestControllerTest.java
package com.audittrail.audittrail;
import com.google.gson.JsonObject;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import com.audittrail.auditTrail.controller.AuditObject;
import com.audittrail.auditTrail.controller.AuditRestController;
import com.audittrail.auditTrail.services.CreateAuditService;
import com.audittrail.auditTrail.services.GetAuditService;
#RunWith(SpringJUnit4ClassRunner.class)
#WebMvcTest(AuditRestController.class)
public class AuditRestControllerTest {
#Autowired
private MockMvc mockMvc;
#Autowired
AuditRestController auditRestController;
#MockBean
GetAuditService getAuditService;
#MockBean
CreateAuditService CreateAuditService;
#MockBean
AuditObject auditObject;
// #Before
// public void setUp() {
// mockMvc = MockMvcBuilders.standaloneSetup(new AuditRestController()).build();
// System.out.println("setup done");
// }
#Test
public void checkObjectId() throws Exception {
JsonObject demoInput = new JsonObject();
demoInput.addProperty("id", "1");
demoInput.addProperty("name", "Rajesh");
JsonObject demoResponse = new JsonObject();
demoResponse.addProperty("eventName", "Update");
demoResponse.addProperty("ObjectId", "12344");
Mockito.when(getAuditService.getEvent(demoInput.toString())).thenReturn(demoResponse.toString());
mockMvc.perform(MockMvcRequestBuilders.post("/audit/getevent").contentType(MediaType.APPLICATION_JSON)
.content(demoInput.toString()))
.andExpect(MockMvcResultMatchers.jsonPath("$.eventNmae", Matchers.is("Update")));
}
}
Shown Below is the pom.xml file that I have:
Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.auditTrail</groupId>
<artifactId>audit-trail-test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>audit-trail</name>
<description>Audit Service Integration</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.emc.leap</groupId>
<artifactId>leap-commons-client</artifactId>
<version>1.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.emc.leap</groupId>
<artifactId>leap-commons-core</artifactId>
<version>1.1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.1.1.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
</dependencies>
</project>
And finally here is the dependency tree for my maven:
[INFO] com.auditTrail:audit-trail-test:jar:0.0.1-SNAPSHOT
[INFO] +- com.google.code.gson:gson:jar:2.6.2:compile
[INFO] +- com.emc.leap:leap-commons-client:jar:1.1.0-SNAPSHOT:compile
[INFO] | +- org.springframework:spring-context:jar:4.3.17.RELEASE:compile
[INFO] | | +- org.springframework:spring-aop:jar:4.3.17.RELEASE:compile
[INFO] | | \- org.springframework:spring-expression:jar:4.3.17.RELEASE:compile
[INFO] | +- org.apache.httpcomponents:httpclient:jar:4.5.1:compile
[INFO] | | +- org.apache.httpcomponents:httpcore:jar:4.4.3:compile
[INFO] | | +- commons-logging:commons-logging:jar:1.2:compile
[INFO] | | \- commons-codec:commons-codec:jar:1.9:compile
[INFO] | +- org.springframework:spring-web:jar:4.3.17.RELEASE:compile
[INFO] | +- org.apache.commons:commons-lang3:jar:3.5:compile
[INFO] | +- org.slf4j:slf4j-api:jar:1.7.21:compile
[INFO] | \- com.eatthepath:fast-uuid:jar:0.1:compile
[INFO] +- com.emc.leap:leap-commons-core:jar:1.1.0-SNAPSHOT:compile
[INFO] | +- com.emc.dctm:security:jar:1.0.9:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-core:jar:2.7.5:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.7.5:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.7.5:compile
[INFO] | +- commons-io:commons-io:jar:2.4:compile
[INFO] | +- org.springframework.security:spring-security-jwt:jar:1.0.9.RELEASE:compile
[INFO] | | \- org.bouncycastle:bcpkix-jdk15on:jar:1.56:compile
[INFO] | | \- org.bouncycastle:bcprov-jdk15on:jar:1.56:compile
[INFO] | +- org.springframework.security:spring-security-core:jar:4.2.6.RELEASE:compile
[INFO] | | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] | +- com.google.guava:guava:jar:18.0:compile
[INFO] | \- net.jodah:expiringmap:jar:0.3.1:compile
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:provided
[INFO] +- org.mockito:mockito-all:jar:1.9.5:test
[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:2.1.1.RELEASE:test
[INFO] | +- org.springframework.boot:spring-boot-starter:jar:2.1.1.RELEASE:test
[INFO] | | +- org.springframework.boot:spring-boot:jar:2.1.1.RELEASE:test
[INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:2.1.1.RELEASE:test
[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:2.1.1.RELEASE:test
[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.2.3:test
[INFO] | | | | \- ch.qos.logback:logback-core:jar:1.2.3:test
[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.11.1:test
[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.11.1:test
[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:1.7.25:test
[INFO] | | +- javax.annotation:javax.annotation-api:jar:1.3.2:test
[INFO] | | \- org.yaml:snakeyaml:jar:1.23:test
[INFO] | +- org.springframework.boot:spring-boot-test:jar:2.1.1.RELEASE:test
[INFO] | +- org.springframework.boot:spring-boot-test-autoconfigure:jar:2.1.1.RELEASE:test
[INFO] | +- com.jayway.jsonpath:json-path:jar:2.4.0:test
[INFO] | | \- net.minidev:json-smart:jar:2.3:test
[INFO] | | \- net.minidev:accessors-smart:jar:1.2:test
[INFO] | | \- org.ow2.asm:asm:jar:5.0.4:test
[INFO] | +- junit:junit:jar:4.12:test
[INFO] | +- org.assertj:assertj-core:jar:3.11.1:test
[INFO] | +- org.mockito:mockito-core:jar:2.23.4:test
[INFO] | | +- net.bytebuddy:byte-buddy:jar:1.9.3:test
[INFO] | | +- net.bytebuddy:byte-buddy-agent:jar:1.9.3:test
[INFO] | | \- org.objenesis:objenesis:jar:2.6:test
[INFO] | +- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] | +- org.hamcrest:hamcrest-library:jar:1.3:test
[INFO] | +- org.skyscreamer:jsonassert:jar:1.5.0:test
[INFO] | | \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO] | +- org.springframework:spring-core:jar:5.1.3.RELEASE:compile
[INFO] | | \- org.springframework:spring-jcl:jar:5.1.3.RELEASE:compile
[INFO] | +- org.springframework:spring-test:jar:5.1.3.RELEASE:test
[INFO] | \- org.xmlunit:xmlunit-core:jar:2.6.2:test
[INFO] \- org.springframework:spring-tx:jar:5.1.5.RELEASE:compile
[INFO] \- org.springframework:spring-beans:jar:5.1.5.RELEASE:compile
And Now finally here is the error that I am getting after mvn:install
-<testcase time="0.017" name="initializationError" classname="com.audittrail.audittrail.AuditRestControllerTest">
<error type="java.lang.NoClassDefFoundError" message="org/springframework/web/servlet/config/annotation/WebMvcConfigurer">java.lang.NoClassDefFoundError: org/springframework/web/servlet/config/annotation/WebMvcConfigurerat org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTypeExcludeFilter.<clinit>(WebMvcTypeExcludeFilter.java:58)at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)at java.lang.reflect.Constructor.newInstance(Unknown Source)at org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer.instantiateTypeExcludeFilter(TypeExcludeFiltersContextCustomizer.java:66)at org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer.instantiateTypeExcludeFilters(TypeExcludeFiltersContextCustomizer.java:55)at org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer.<init>(TypeExcludeFiltersContextCustomizer.java:48)at org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizerFactory.createContextCustomizer(TypeExcludeFiltersContextCustomizerFactory.java:47)at org.springframework.test.context.support.AbstractTestContextBootstrapper.getContextCustomizers(AbstractTestContextBootstrapper.java:404)at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:376)at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:312)at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:265)at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildTestContext(AbstractTestContextBootstrapper.java:108)at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.buildTestContext(SpringBootTestContextBootstrapper.java:99)at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:139)at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:124)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:151)at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:142)at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)at java.lang.reflect.Constructor.newInstance(Unknown Source)at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:250)at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)at java.lang.reflect.Method.invoke(Unknown Source)at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75) Caused by: java.lang.ClassNotFoundException: org.springframework.web.servlet.config.annotation.WebMvcConfigurerat 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)... 41 more </error>
I am pretty new to this. I have tried to learn and write the tests and the above code. I am badly stuck at this. Any help is welcome.
Also I do not have any ApplicationContext defined for the Controller as I am using it as external jar in another project. Is it possible to create the tests in the same way.
We only need to test this one controller with two endpoints.
Thanks in advance.
Caused by: java.lang.ClassNotFoundException: org.springframework.web.servlet.config.annotation.WebMvcConfigurer: looks like your missing some dependencies.
This class should be contained in spring-webmvc
This error arose because I had not involved the spring-webmvc dependency in my pom.xml.
The reason I was not including it was beacuse I was getting error "AbstractMethodError".
But later I found out that the main problem was because I was mixing up spring-boot and spring together.
Spring-starter-test comes with spring-boot and hence the whole project was collapsing.
Thanks to people who responded.

Jetty Server's Session is Null

I am trying to implement a hello world Jetty project (using Jetty 9.3.6.v20151106) with a servlet that looks at the session. However, when my code runs, I am not able to see the session or store any cookies. I have looked at this stackoverflow question to help troubleshoot and implemented the simple BaseServlet recommended, but every time I run it the BaseServlet outputs "no session". Am I missing some configuration?
Here is my HelloWorld.java class:
package com.my.company;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SessionManager;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.session.HashSessionIdManager;
import org.eclipse.jetty.server.session.HashSessionManager;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
public class HelloWorld {
public static void main(String[] args) throws Exception {
//Create the server
Server server = new Server();
// Configure for Http
HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(8443);
http_config.setOutputBufferSize(32768);
ServerConnector http = new ServerConnector(server,
new HttpConnectionFactory(http_config));
int http_port = 12043;
http.setPort(http_port);
http.setIdleTimeout(30000);
server.addConnector(http);
//Add ServletContextHandler
ServletContextHandler servletContextHandler = new ServletContextHandler(
ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/");
SessionManager sessionManager = new HashSessionManager();
sessionManager.setMaxInactiveInterval(60 * 15); //session time out of 15 minutes
HashSessionIdManager idManager = new HashSessionIdManager();
sessionManager.getSessionCookieConfig().setName("JSESSIONID_" + Integer.toString(http_port));
sessionManager.setSessionIdManager(idManager);
server.setSessionIdManager(idManager);
SessionHandler sessionHandler = new SessionHandler(sessionManager);
servletContextHandler.setSessionHandler(sessionHandler);
server.setHandler(servletContextHandler);
//Add BaseServlet
ServletHolder holder = new ServletHolder(new BaseServlet());
servletContextHandler.addServlet(holder, "/*");
//Start the server
server.start();
System.out.println("SERVER DUMP AFTER START" + server.dump());
// The use of server.join() the will make the current thread join and
// wait until the server is done executing.
// See http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join()
server.join();
}
}
Here is my BaseServlet.java class:
package com.my.company;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class BaseServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
boolean create = "true".equals(req.getParameter("create"));
HttpSession session = req.getSession(create);
if (create) {
session.setAttribute("created", new Date());
}
PrintWriter pw = new PrintWriter(resp.getOutputStream());
pw.println("Create = " + create);
if (session == null) {
pw.println("no session");
} else {
pw.println("Session = " + session.getId());
pw.println("Created = " + session.getAttribute("created"));
}
pw.flush();
}
}
Here is my pom.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>EmbeddJettyHelloWorld</groupId>
<artifactId>EmbeddJettyHelloWorld</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>EmbeddJettyHelloWorld</name>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.4.0</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.my.company.HelloWorld</mainClass>
<classpathScope>test</classpathScope>
<systemProperties>
<property>
<key>basedir</key>
<value>${basedir}</value>
</property>
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty-version}</version>
<configuration>
<webAppConfig>
<contextPath>/</contextPath>
</webAppConfig>
<webAppSourceDirectory>target/${project.artifactId}-${project.version}</webAppSourceDirectory>
<webDefaultXml>${project.basedir}/conf/jetty/webdefault.xml</webDefaultXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${jetty-version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${jetty-version}</version>
</dependency>
</dependencies>
<properties>
<jetty-version>9.3.6.v20151106</jetty-version>
</properties>
Here is the output of the server dump:
SERVER DUMP AFTER STARTorg.eclipse.jetty.server.Server#71f2a7d5 - STARTED
+= qtp1149319664{STARTED,8<=8<=200,i=5,q=0} - STARTED
| +- 15 qtp1149319664-15 TIMED_WAITING # sun.misc.Unsafe.park(Native Method) IDLE
| +- 13 qtp1149319664-13-acceptor-0#4c170d5c-ServerConnector#326de728 {HTTP/1.1,[http/1.1]}{0.0.0.0:12043} RUNNABLE # sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method) prio=3
| +- 14 qtp1149319664-14 RUNNABLE # sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
| +- 12 qtp1149319664-12 TIMED_WAITING # sun.misc.Unsafe.park(Native Method) IDLE
| +- 18 qtp1149319664-18 TIMED_WAITING # sun.misc.Unsafe.park(Native Method) IDLE
| +- 16 qtp1149319664-16 TIMED_WAITING # sun.misc.Unsafe.park(Native Method) IDLE
| +- 11 qtp1149319664-11 RUNNABLE # sun.nio.ch.WindowsSelectorImpl$SubSelector.poll0(Native Method)
| +- 17 qtp1149319664-17 TIMED_WAITING # sun.misc.Unsafe.park(Native Method) IDLE
+= ServerConnector#326de728{HTTP/1.1,[http/1.1]}{0.0.0.0:12043} - STARTED
| +~ org.eclipse.jetty.server.Server#71f2a7d5 - STARTED
| +~ qtp1149319664{STARTED,8<=8<=200,i=5,q=0} - STARTED
| += org.eclipse.jetty.util.thread.ScheduledExecutorScheduler#1a6c5a9e - STARTED
| +- org.eclipse.jetty.io.ArrayByteBufferPool#2cfb4a64
| += HttpConnectionFactory#20ad9418[HTTP/1.1] - STARTED
| | +- HttpConfiguration#5474c6c{32768/8192,8192/8192,https://:8443,[]}
| += org.eclipse.jetty.server.ServerConnector$ServerConnectorManager#4b6995df - STARTED
| | +- org.eclipse.jetty.io.ManagedSelector#34033bd0 id=0 keys=0 selected=0 id=0
| | | +- sun.nio.ch.WindowsSelectorImpl#5200a403 keys=0
| | +- org.eclipse.jetty.io.ManagedSelector#3aa9e816 id=1 keys=0 selected=0 id=1
| | +- sun.nio.ch.WindowsSelectorImpl#33c7bf keys=0
| +- sun.nio.ch.ServerSocketChannelImpl[/0:0:0:0:0:0:0:0:12043]
| +- qtp1149319664-13-acceptor-0#4c170d5c-ServerConnector#326de728{HTTP/1.1,[http/1.1]}{0.0.0.0:12043}
+= org.eclipse.jetty.server.session.HashSessionIdManager#17d99928 - STARTED
+= o.e.j.s.ServletContextHandler#2e5c649{/,null,AVAILABLE} - STARTED
| += org.eclipse.jetty.server.session.SessionHandler#6fffcba5 - STARTED
| | += org.eclipse.jetty.server.session.HashSessionManager#9e89d68 - STARTED
| | | +~ org.eclipse.jetty.server.session.HashSessionIdManager#17d99928 - STARTED
| | | += org.eclipse.jetty.util.thread.ScheduledExecutorScheduler#34340fab - STARTED
| | | +- sun.misc.Unsafe.park(Native Method)
| | | +- java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
| | | +- java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
| | | +- java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
| | | +- java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
| | | +- java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
| | | +- java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
| | | +- java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
| | | +- java.lang.Thread.run(Thread.java:745)
| | += org.eclipse.jetty.servlet.ServletHandler#2aafb23c - STARTED
| | += com.rtn.iaf.BaseServlet-484b61fc#3334c9b2==com.rtn.iaf.BaseServlet,-1,true - STARTED
| | +- [/*]=>com.rtn.iaf.BaseServlet-484b61fc
| | += org.eclipse.jetty.servlet.ServletHandler$Default404Servlet-7a7b0070#1d1bf782==org.eclipse.jetty.servlet.ServletHandler$Default404Servlet,-1,false - STARTED
| | +- [/]=>org.eclipse.jetty.servlet.ServletHandler$Default404Servlet-7a7b0070
| |
| +> No ClassLoader
| +> Handler attributes o.e.j.s.ServletContextHandler#2e5c649{/,null,AVAILABLE}
| | +- org.eclipse.jetty.server.Executor=qtp1149319664{STARTED,8<=8<=200,i=5,q=0}
| +> Context attributes o.e.j.s.ServletContextHandler#2e5c649{/,null,AVAILABLE}
| | +- org.eclipse.jetty.util.DecoratedObjectFactory=org.eclipse.jetty.util.DecoratedObjectFactory[decorators=0]
| +> Initparams o.e.j.s.ServletContextHandler#2e5c649{/,null,AVAILABLE}
|
+> sun.misc.Launcher$AppClassLoader#73d16e93
+- file:/C:/Users/myUser/tutorialAndDemo_workspace/EmbeddJettyHelloWorld/target/classes/
+- file:/C:/Users/myUser/tutorialAndDemo_workspace/.m2/repository1/org/eclipse/jetty/jetty-server/9.3.6.v20151106/jetty-server-9.3.6.v20151106.jar
+- file:/C:/Users/myUser/tutorialAndDemo_workspace/.m2/repository1/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar
+- file:/C:/Users/myUser/tutorialAndDemo_workspace/.m2/repository1/org/eclipse/jetty/jetty-http/9.3.6.v20151106/jetty-http-9.3.6.v20151106.jar
+- file:/C:/Users/myUser/tutorialAndDemo_workspace/.m2/repository1/org/eclipse/jetty/jetty-util/9.3.6.v20151106/jetty-util-9.3.6.v20151106.jar
+- file:/C:/Users/myUser/tutorialAndDemo_workspace/.m2/repository1/org/eclipse/jetty/jetty-io/9.3.6.v20151106/jetty-io-9.3.6.v20151106.jar
+- file:/C:/Users/myUser/tutorialAndDemo_workspace/.m2/repository1/org/eclipse/jetty/jetty-servlet/9.3.6.v20151106/jetty-servlet-9.3.6.v20151106.jar
+- file:/C:/Users/myUser/tutorialAndDemo_workspace/.m2/repository1/org/eclipse/jetty/jetty-security/9.3.6.v20151106/jetty-security-9.3.6.v20151106.jar
+- sun.misc.Launcher$ExtClassLoader#2b80d80f
After talking with the folks on the Jetty Users Mailing List, I modified my code to become:
public static void main(String[] args) throws Exception {
// Create the server
Server server = new Server(12043);
// Add ServletContextHandler
ServletContextHandler servletContextHandler = new ServletContextHandler(
ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/");
server.setHandler(servletContextHandler);
// Add BaseServlet
ServletHolder holder = new ServletHolder(new BaseServlet());
servletContextHandler.addServlet(holder, "/*");
// Start the server
server.start();
System.out.println("SERVER DUMP AFTER START" + server.dump());
server.join();
}
Where the output is: Request = Request(GET //localhost:12043/)#968bbe8
Response = HTTP/1.1 200
Date: Thurs, 2 Jun 2016 13:00:04 GMT
Create = false
no session
Which is expected since, the call request.getSession(false) does not create the session. It only returns it if it has been previously created.

Injecting SoyTemplateRenderer in custom Atlassian JIRA plugin

I'm currently trying to develop a custom Jira plugin, which also uses a servlet to render a Soy template.
This is the code of my servlet:
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package at.fraiss.plugins.custommenuitem.servlets;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import com.atlassian.soy.renderer.SoyTemplateRenderer;
import java.util.HashMap;
import java.util.Map;
/**
*
* #author Mario
*/
public class SoyTemplateServlet extends HttpServlet {
private SoyTemplateRenderer soyTemplateRenderer;
public SoyTemplateServlet(SoyTemplateRenderer soyTemplateRenderer)
{
this.soyTemplateRenderer = soyTemplateRenderer;
}
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
response.setContentType("text/html");
response.getWriter().write(getHtml());
}
public String getHtml()
{
Map<String, Object> data = new HashMap<String,Object>();
data.put("isLocal", true);
data.put("url", "http://www.example.com");
data.put("title", "example");
return this.soyTemplateRenderer.render("jira.webresources:soy-templates", "JIRA.Templates.Links.helpLink", data);
}
}
This is how I defined the soy template files inside the atlassian-plugin.xml descriptor:
<web-resource key="soy-templates">
<dependency>com.atlassian.soy.soy-template-plugin:soy-deps</dependency>
<!-- Available to the server-side only -->
<resource type="soy" name="links" location="links.soy"/>
 
<!-- Make available to the client-side in JS as well... -->
<transformation extension="soy">
<transformer key="soyTransformer"/>
</transformation>
<resource type="download" name="Links.soy.js" location="links.soy"/>
</web-resource>
I have added the following section to my pom.xml:
<dependency>
<groupId>com.atlassian.soy</groupId>
<artifactId>soy-template-renderer-api</artifactId>
<version>4.0.4</version>
<scope>provided</scope>
</dependency>
and always get this error when try to acces the servlet
[INFO] [talledLocalContainer] Caused by: org.springframework.beans.factory.Unsat isfiedDependencyException: Error creating bean with name 'at.fraiss.plugins.cust ommenuitem.servlets.SoyTemplateServlet': Unsatisfied dependency expressed throug h constructor argument with index 0 of type [com.atlassian.soy.renderer.SoyTempl ateRenderer]: : No qualifying bean of type [com.atlassian.soy.renderer.SoyTempla teRenderer] found for dependency: expected at least 1 bean which qualifies as au towire candidate for this dependency. Dependency annotations: {}; nested excepti on is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualif ying bean of type [com.atlassian.soy.renderer.SoyTemplateRenderer] found for dep endency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {} [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Con structorResolver.createArgumentArray(ConstructorResolver.java:749) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Con structorResolver.autowireConstructor(ConstructorResolver.java:185) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanF actory.java:1139) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFa ctory.java:1042) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory. java:504) [INFO] [talledLocalContainer] at org.springframework.beans.factory.support.Abs tractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.ja va:342) [INFO] [talledLocalContainer] ... 2 filtered [INFO] [talledLocalContainer] at java.lang.reflect.Method.invoke(Method.java:4 97) [INFO] [talledLocalContainer] at com.atlassian.plugin.osgi.spring.DefaultSprin gContainerAccessor.createBean(DefaultSpringContainerAccessor.java:112) [INFO] [talledLocalContainer] at com.atlassian.plugin.module.ClassPrefixModule Factory.createModule(ClassPrefixModuleFactory.java:39) [INFO] [talledLocalContainer] at com.atlassian.plugin.module.PrefixDelegatingM oduleFactory.createModule(PrefixDelegatingModuleFactory.java:100) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.descriptors.Serv letModuleDescriptor.getModule(ServletModuleDescriptor.java:48) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DelegatingPlugin Servlet.<init>(DelegatingPluginServlet.java:33) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DefaultServletMo duleManager$LazyLoadedServletReference.create(DefaultServletModuleManager.java:5 41) [INFO] [talledLocalContainer] at com.atlassian.plugin.servlet.DefaultServletMo duleManager$LazyLoadedServletReference.create(DefaultServletModuleManager.java:5 21) [INFO] [talledLocalContainer] at com.atlassian.util.concurrent.LazyReference$S ync.run(LazyReference.java:325) [INFO] [talledLocalContainer] at com.atlassian.util.concurrent.LazyReference.g ...
I also had this problem (and lost hours on it).
The Spring scanner apparently only processes classes marked with #Named.
This worked for me:
#Named("MyServlet")
public class MyServlet extends HttpServlet{
#ComponentImport
private final SoyTemplateRenderer soyTemplateRenderer;
#Inject
public MyServlet(#ComponentImport final SoyTemplateRenderer soyTemplateRenderer) {
this.soyTemplateRenderer = soyTemplateRenderer;
}
}
Apparently this has nothing to do with jiira, but in your frustration you seem to be blaming it and its documentation. It's actually a problem with your use of spring, and your apparent inability to read stack traces.
The first entry in the stack trace mentions, in may different ways, No qualif
ying bean of type [com.atlassian.soy.renderer.SoyTemplateRenderer] found. So, you seem to have not provided a bean definition for the SoyTemplateRenderer for spring to find. Rectify this and this particular problem will disappear.

Resources