Jetty Server's Session is Null - maven

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.

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();
}

Redis cluster client creation in spring with spark

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.

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.

Pax Exam execute command against Karaf

I am trying to run a PAX Exam test which starts a Karaf instance version 4.0.2 and then deploys some features. Everything works so far.
However, I also want to run some commands to check that the bundles have been installed i.e. run "bundle:list" command.
I have added the executeCommand and getOsgiService methods found here:
https://github.com/christian-posta/rider-auto-osgi/blob/master/itests/src/test/java/org/jboss/fuse/example/support/FuseTestSupport.java#L80
but I am getting RuntimeException:
java.lang.RuntimeException: Gave up waiting for service (objectClass=org.apache.felix.service.command.CommandProcessor)
at com.axiell.tenantidlookup.integrationtest.TenantIdLookupTest.getOsgiService(TenantIdLookupTest.java:205)
at com.axiell.tenantidlookup.integrationtest.TenantIdLookupTest.getOsgiService(TenantIdLookupTest.java:171)
at com.axiell.tenantidlookup.integrationtest.TenantIdLookupTest.testProvisioning(TenantIdLookupTest.java:110)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:68)
at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:37)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.invokeViaJUnit(JUnitProbeInvoker.java:124)
at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.findAndInvoke(JUnitProbeInvoker.java:97)
at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.call(JUnitProbeInvoker.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.ops4j.pax.exam.rbc.internal.RemoteBundleContextImpl.remoteCall(RemoteBundleContextImpl.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:323)
at sun.rmi.transport.Transport$1.run(Transport.java:200)
at sun.rmi.transport.Transport$1.run(Transport.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:568)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:826)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$256(TCPTransport.java:683)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:682)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
This is the code causing the exception.
CommandProcessor cp = getOsgiService(CommandProcessor.class);
CommandSession cs = cp.createSession(System.in, System.out, System.err);
//cs.execute("bundle:list");
//cs.execute("wrapper:install --help");
//System.out.println(executeCommand("bundle:list"));
cs.close();
Something with the CommandProcessor is not working. Any hints or help would be appreciated. Thakns
With Karaf 4.x the commands did change so you need to change it accordingly.
A full sample can be found here
As quick sum-up you need the SessionFactory in your test, see below:
#Inject
protected SessionFactory sessionFactory;
and from there on create a session object:
#Before
public void setUpITestBase() throws Exception {
session = sessionFactory.create(System.in, printStream, errStream);
}
I did this in the before part of the test, to make sure the session is always created new.
The following is the crucial part for executing commands:
String response;
FutureTask<String> commandFuture = new FutureTask<String>(new Callable<String>() {
public String call() {
try {
System.err.println(command);
session.execute(command);
} catch (Exception e) {
e.printStackTrace(System.err);
}
printStream.flush();
errStream.flush();
return byteArrayOutputStream.toString();
}
});
try {
executor.submit(commandFuture);
response = commandFuture.get(10000L, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace(System.err);
response = "SHELL COMMAND TIMED OUT: ";
}
Achim Nierbeck solved this headache for me so for reference look at his answer. If anyone just wants a peak on the code that worked for me.
import static org.junit.Assert.*;
import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.*;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.camel.model.language.ConstantExpression;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.apache.karaf.features.FeaturesService;
import org.apache.karaf.features.BootFinished;
import org.apache.karaf.shell.api.console.Session;
import org.apache.karaf.shell.api.console.SessionFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.ProbeBuilder;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.karaf.options.LogLevelOption;
import org.ops4j.pax.exam.options.WrappedUrlProvisionOption;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.framework.Constants;
import javax.inject.Inject;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
#RunWith(PaxExam.class)
public class TenantIdLookupTest {
#Inject
protected BundleContext bc;
#Inject
protected FeaturesService featuresService;
#Inject
protected BootFinished bootFinished;
#Inject
protected SessionFactory sessionFactory;
private ExecutorService executor = Executors.newCachedThreadPool();
private ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
private PrintStream printStream = new PrintStream(byteArrayOutputStream);
private PrintStream errStream = new PrintStream(byteArrayOutputStream);
private Session session;
#ProbeBuilder
public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE,
"*,org.apache.felix.service.*;status=provisional");
return probe;
}
#Configuration
public static Option[] configure() throws Exception {
return new Option[] {
karafDistributionConfiguration()
.frameworkUrl(
maven().groupId("org.apache.karaf")
.artifactId("apache-karaf").type("zip")
.version("4.0.2"))
.karafVersion("4.0.2").useDeployFolder(false)
.unpackDirectory(new File("target/paxexam/unpack")),
configureConsole().ignoreLocalConsole(),
features(
maven().groupId("org.apache.camel.karaf")
.artifactId("apache-camel").type("xml")
.classifier("features").version("2.15.1"),
"camel"),
features(
maven().groupId("org.apache.camel.karaf")
.artifactId("apache-camel").type("xml")
.classifier("features").version("2.15.1"),
"camel-blueprint"),
features(
maven().groupId("org.apache.camel.karaf")
.artifactId("apache-camel").type("xml")
.classifier("features").version("2.15.1"),
"camel-netty4"),
features(
maven().groupId("org.apache.camel.karaf")
.artifactId("apache-camel").type("xml")
.classifier("features").version("2.15.1"),
"camel-rabbitmq"),
CoreOptions.mavenBundle(CoreOptions.maven(
"com.google.code.gson", "gson").version("2.3")),
logLevel(LogLevelOption.LogLevel.INFO),
// features(maven().groupId("org.apache.camel.karaf").artifactId("apache-camel").type("xml").classifier("features").version("2.12.1"),
// "camel-blueprint", "camel-test"),
// features(maven().groupId("net.nanthrax.blog").artifactId("camel-blueprint").type("xml").classifier("features").version("1.0-SNAPSHOT"),
// "blog-camel-blueprint-route"),
keepRuntimeFolder(),
};
}
#Before
public void setUpITestBase() throws Exception {
session = sessionFactory.create(System.in, printStream, errStream);
}
#Test
public void testProvisioning() throws Exception {
assertTrue(featuresService.isInstalled(featuresService.getFeature("camel-blueprint")));
System.out.println(executeCommand("bundle:list"));
}
protected String executeCommand(final String command) throws IOException {
byteArrayOutputStream.flush();
byteArrayOutputStream.reset();
String response;
FutureTask<String> commandFuture = new FutureTask<String>(
new Callable<String>() {
public String call() {
try {
System.err.println(command);
session.execute(command);
} catch (Exception e) {
e.printStackTrace(System.err);
}
printStream.flush();
errStream.flush();
return byteArrayOutputStream.toString();
}
});
try {
executor.submit(commandFuture);
response = commandFuture.get(10000L, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace(System.err);
response = "SHELL COMMAND TIMED OUT: ";
}
System.err.println(response);
return response;
}
#SuppressWarnings({ "rawtypes", "unchecked" })
protected <T> T getOsgiService(Class<T> type, String filter, long timeout) {
ServiceTracker tracker = null;
try {
String flt;
if (filter != null) {
if (filter.startsWith("(")) {
flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")";
} else {
flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))";
}
} else {
flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
}
Filter osgiFilter = FrameworkUtil.createFilter(flt);
tracker = new ServiceTracker(bc, osgiFilter, null);
tracker.open(true);
// Note that the tracker is not closed to keep the reference
// This is buggy, as the service reference may change i think
Object svc = type.cast(tracker.waitForService(timeout));
if (svc == null) {
Dictionary dic = bc.getBundle().getHeaders();
System.err.println("Test bundle headers: " + explode(dic));
for (ServiceReference ref : asCollection(bc.getAllServiceReferences(null, null))) {
System.err.println("ServiceReference: " + ref);
}
for (ServiceReference ref : asCollection(bc.getAllServiceReferences(null, flt))) {
System.err.println("Filtered ServiceReference: " + ref);
}
//logger.error("Gave up waiting for service " + flt);
return null;
}
return type.cast(svc);
} catch (InvalidSyntaxException e) {
throw new IllegalArgumentException("Invalid filter", e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/*
* Explode the dictionary into a ,-delimited list of key=value pairs
*/
#SuppressWarnings("rawtypes")
private static String explode(Dictionary dictionary) {
Enumeration keys = dictionary.keys();
StringBuffer result = new StringBuffer();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
result.append(String.format("%s=%s", key, dictionary.get(key)));
if (keys.hasMoreElements()) {
result.append(", ");
}
}
return result.toString();
}
/**
* Provides an iterable collection of references, even if the original array
* is null
*/
#SuppressWarnings("rawtypes")
private static Collection<ServiceReference> asCollection(ServiceReference[] references) {
return references != null ? Arrays.asList(references) : Collections.<ServiceReference> emptyList();
}
}
Finally the output I was waiting for:
START LEVEL 100 , List Threshold: 50
ID | State | Lvl | Version | Name
--------------------------------------------------------------------------------------
9 | Active | 80 | 2.3 | Gson
10 | Active | 80 | 3.3.4 | RabbitMQ Java AMQP client library
11 | Active | 80 | 4.0.26.Final | Netty/Buffer
12 | Active | 80 | 4.0.26.Final | Netty/Codec
13 | Active | 80 | 4.0.26.Final | Netty/Common
14 | Active | 80 | 4.0.26.Final | Netty/Handler
15 | Active | 80 | 4.0.26.Final | Netty/Transport
29 | Active | 80 | 2.15.1 | camel-blueprint
30 | Active | 80 | 2.15.1 | camel-catalog
31 | Active | 80 | 2.15.1 | camel-commands-core
32 | Active | 80 | 2.15.1 | camel-core
33 | Active | 80 | 2.15.1 | camel-netty4
34 | Active | 80 | 2.15.1 | camel-rabbitmq
35 | Active | 80 | 2.15.1 | camel-spring
36 | Active | 80 | 2.15.1 | camel-karaf-commands
37 | Active | 80 | 1.6.0 | Commons Pool
38 | Active | 80 | 1.0 | Apache Geronimo JSR-330 Spec API
39 | Active | 80 | 1.1.1 | geronimo-jta_1.1_spec
69 | Active | 80 | 2.2.6.1 | Apache ServiceMix :: Bundles :: jaxb-impl
81 | Active | 80 | 1.5.0 | OPS4J Base - IO
82 | Active | 80 | 1.5.0 | OPS4J Base - Lang
83 | Active | 80 | 1.5.0 | OPS4J Base - Monitors
84 | Active | 80 | 1.5.0 | OPS4J Base - Net
85 | Active | 80 | 1.5.0 | OPS4J Base - Service Provider Access
86 | Active | 80 | 1.5.0 | OPS4J Base - Store
87 | Active | 80 | 1.5.0 | OPS4J Base - Util - Property
88 | Active | 80 | 4.6.0 | OPS4J Pax Exam API
89 | Active | 80 | 4.6.0 | OPS4J Pax Exam Extender Service
90 | Active | 80 | 4.6.0 | OPS4J Pax Exam Injection
91 | Active | 80 | 4.6.0 | OPS4J Pax Exam JUnit Probe Invoker
92 | Active | 80 | 4.6.0 | OPS4J Pax Exam Remote Bundle Context
93 | Active | 80 | 1.8.1 | OPS4J Pax Swissbox :: OSGi Core
94 | Active | 80 | 1.8.1 | OPS4J Pax Swissbox :: Extender
95 | Active | 80 | 1.8.1 | OPS4J Pax Swissbox :: Framework Helpers
96 | Active | 80 | 1.8.1 | OPS4J Pax Swissbox :: Lifecycle
97 | Active | 80 | 1.8.1 | OPS4J Pax Swissbox :: Tracker
98 | Active | 80 | 1.3.0.1 | OPS4J Pax Tipi - hamcrest-core
99 | Active | 80 | 4.12.0.1 | OPS4J Pax Tipi - junit
112 | Active | 80 | 3.1.4 | Stax2 API
113 | Active | 80 | 4.4.1 | Woodstox XML-processor
114 | Active | 80 | | PAXEXAM-PROBE-bb084675-f072-481b-8f3e-6e3657762bc3

Jersey Singleton Using Spring: Method cannot be cast to Constructor

I am trying to use Spring to autowire Jersey but I'm getting the weirdest exception as soon as one of the methods gets called.
Here is my resource:
package fungle.funfinder.rest.resource;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import fungle.common.hdao.model.ByteId;
import fungle.common.hdao.model.OnError;
import fungle.common.hdao.util.CascadeUtils;
import fungle.common.hdao.util.FetchUtils;
import fungle.funfinder.data.dao.ActivityTypeDAO;
import fungle.funfinder.data.entity.ActivityType;
#Path("activityType")
#Singleton
#Service
public class ActivityTypeResource {
private ActivityTypeDAO activityTypeDAO;
public ActivityTypeResource() {
}
public ActivityTypeResource(ActivityTypeDAO activityTypeDAO) {
this.activityTypeDAO=activityTypeDAO;
}
public ActivityTypeDAO getActivityTypeDAO() {
return activityTypeDAO;
}
#Autowired
public void setActivityTypeDAO(ActivityTypeDAO activityTypeDAO) {
this.activityTypeDAO = activityTypeDAO;
}
#GET
#Path("/all")
#Produces(value={MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public List<ActivityType> getAll() {
Map<ByteId, ActivityType> types = activityTypeDAO.getAll(FetchUtils.always(),OnError.CONTINUE,null,null);
return new ArrayList<>(types.values());
}
#POST
public Response post(ActivityType activityType,#Context UriInfo uriInfo) {
ActivityType existing = activityTypeDAO.getByName(activityType.getName());
if (existing==null) {
activityTypeDAO.save(activityType, CascadeUtils.always(), OnError.ATTEMPT_UNDO);
existing = activityTypeDAO.getByName(activityType.getName());
if (existing !=null) {
// success
URI uri = uriInfo.getAbsolutePathBuilder().path(existing.getName()).build();
return Response.created(uri).build();
} else {
// failed to save.
return Response.serverError().build();
}
} else {
// already exists.
return Response.notModified("An activity type with that name already exists.").entity(existing).build();
}
}
#GET
#Path("/{name}")
public ActivityType getByName(#PathParam("name") String name) {
ActivityType existing = activityTypeDAO.getByName(name);
return existing;
}
}
Here is my maven dependency:tree:
[INFO] fungle:fungle.funfinder.data:jar:0.0.1-SNAPSHOT
[INFO] +- fungle:fungle.common.core:jar:0.0.1-SNAPSHOT:compile
[INFO] +- fungle:fungle.common.hdao:jar:0.0.1-SNAPSHOT:compile
[INFO] +- org.apache.avro:avro:jar:1.7.6:compile
[INFO] | +- org.codehaus.jackson:jackson-core-asl:jar:1.8.8:compile
[INFO] | +- org.codehaus.jackson:jackson-mapper-asl:jar:1.8.8:compile
[INFO] | +- com.thoughtworks.paranamer:paranamer:jar:2.3:compile
[INFO] | +- org.xerial.snappy:snappy-java:jar:1.0.5:compile
[INFO] | \- org.apache.commons:commons-compress:jar:1.4.1:compile
[INFO] | \- org.tukaani:xz:jar:1.0:compile
[INFO] +- org.apache.commons:commons-math3:jar:3.2:compile
[INFO] +- org.geotools:gt-referencing:jar:11.1:compile
[INFO] | +- java3d:vecmath:jar:1.3.2:compile
[INFO] | +- commons-pool:commons-pool:jar:1.5.4:compile
[INFO] | +- org.geotools:gt-metadata:jar:11.1:compile
[INFO] | | \- org.geotools:gt-opengis:jar:11.1:compile
[INFO] | +- jgridshift:jgridshift:jar:1.0:compile
[INFO] | \- javax.media:jai_core:jar:1.1.3:compile
[INFO] +- org.geotools:gt-geometry:jar:11.1:compile
[INFO] | +- net.java.dev.jsr-275:jsr-275:jar:1.0-beta-2:compile
[INFO] | \- org.geotools:gt-main:jar:11.1:compile
[INFO] | +- org.geotools:gt-api:jar:11.1:compile
[INFO] | +- com.vividsolutions:jts:jar:1.13:compile
[INFO] | \- org.jdom:jdom:jar:1.1.3:compile
[INFO] +- org.geotools:gt-epsg-hsql:jar:11.1:compile
[INFO] | \- org.hsqldb:hsqldb:jar:2.2.8:compile
[INFO] +- org.springframework:spring-aspects:jar:4.0.2.RELEASE:compile
[INFO] | \- org.aspectj:aspectjweaver:jar:1.7.4:compile
[INFO] +- org.springframework:spring-context:jar:4.0.2.RELEASE:compile
[INFO] +- org.springframework:spring-test:jar:4.0.2.RELEASE:test
[INFO] +- org.springframework:spring-aop:jar:4.0.2.RELEASE:compile
[INFO] | \- aopalliance:aopalliance:jar:1.0:compile
[INFO] +- org.springframework:spring-tx:jar:4.0.2.RELEASE:compile
[INFO] +- org.springframework:spring-core:jar:4.0.2.RELEASE:compile
[INFO] | \- commons-logging:commons-logging:jar:1.1.3:compile
[INFO] +- org.springframework:spring-beans:jar:4.0.2.RELEASE:compile
[INFO] +- org.springframework:spring-expression:jar:4.0.2.RELEASE:compile
[INFO] +- org.springframework:spring-orm:jar:4.0.2.RELEASE:compile
[INFO] | \- org.springframework:spring-jdbc:jar:4.0.2.RELEASE:compile
[INFO] +- ch.qos.logback:logback-classic:jar:1.1.2:compile
[INFO] | \- ch.qos.logback:logback-core:jar:1.1.2:compile
[INFO] +- org.slf4j:slf4j-api:jar:1.7.7:compile
[INFO] +- commons-cli:commons-cli:jar:20040117.000000:compile
[INFO] +- com.google.guava:guava:jar:17.0:compile
[INFO] +- org.apache.commons:commons-collections4:jar:4.0:compile
[INFO] +- commons-io:commons-io:jar:1.3.2:compile
[INFO] +- org.apache.commons:commons-lang3:jar:3.1:compile
[INFO] +- junit:junit:jar:4.11:test
[INFO] | \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.apache.hadoop:hadoop-client:jar:2.0.0-cdh4.5.0:compile
[INFO] | +- org.apache.hadoop:hadoop-common:jar:2.0.0-cdh4.5.0:compile
[INFO] | | +- org.apache.commons:commons-math:jar:2.1:compile
[INFO] | | +- xmlenc:xmlenc:jar:0.52:compile
[INFO] | | +- commons-net:commons-net:jar:3.1:compile
[INFO] | | +- commons-el:commons-el:jar:1.0:runtime
[INFO] | | +- org.apache.hadoop:cloudera-jets3t:jar:2.0.0-cdh4.5.0:compile
[INFO] | | +- org.mockito:mockito-all:jar:1.8.5:compile
[INFO] | | +- org.apache.hadoop:hadoop-auth:jar:2.0.0-cdh4.5.0:compile
[INFO] | | \- com.jcraft:jsch:jar:0.1.42:compile
[INFO] | +- org.apache.hadoop:hadoop-hdfs:jar:2.0.0-cdh4.5.0:compile
[INFO] | +- org.apache.hadoop:hadoop-mapreduce-client-app:jar:2.0.0-cdh4.5.0:compile
[INFO] | | +- org.apache.hadoop:hadoop-mapreduce-client-common:jar:2.0.0-cdh4.5.0:compile
[INFO] | | | +- org.apache.hadoop:hadoop-yarn-client:jar:2.0.0-cdh4.5.0:compile
[INFO] | | | \- org.apache.hadoop:hadoop-yarn-server-common:jar:2.0.0-cdh4.5.0:compile
[INFO] | | +- org.apache.hadoop:hadoop-mapreduce-client-shuffle:jar:2.0.0-cdh4.5.0:compile
[INFO] | | \- org.jboss.netty:netty:jar:3.2.4.Final:compile
[INFO] | +- org.apache.hadoop:hadoop-yarn-api:jar:2.0.0-cdh4.5.0:compile
[INFO] | +- org.apache.hadoop:hadoop-mapreduce-client-core:jar:2.0.0-cdh4.5.0:compile
[INFO] | | \- org.apache.hadoop:hadoop-yarn-common:jar:2.0.0-cdh4.5.0:compile
[INFO] | +- org.apache.hadoop:hadoop-mapreduce-client-jobclient:jar:2.0.0-cdh4.5.0:compile
[INFO] | \- org.apache.hadoop:hadoop-annotations:jar:2.0.0-cdh4.5.0:compile
[INFO] \- org.apache.hbase:hbase:jar:0.94.6-cdh4.5.0:compile
[INFO] +- com.yammer.metrics:metrics-core:jar:2.1.2:compile
[INFO] +- commons-configuration:commons-configuration:jar:1.6:compile
[INFO] | +- commons-collections:commons-collections:jar:3.2.1:compile
[INFO] | +- commons-digester:commons-digester:jar:1.8:compile
[INFO] | | \- commons-beanutils:commons-beanutils:jar:1.7.0:compile
[INFO] | \- commons-beanutils:commons-beanutils-core:jar:1.8.0:compile
[INFO] +- com.github.stephenc.high-scale-lib:high-scale-lib:jar:1.1.1:compile
[INFO] +- commons-codec:commons-codec:jar:20041127.091804:compile (version managed from 1.4)
[INFO] +- commons-httpclient:commons-httpclient:jar:3.1:compile
[INFO] +- commons-lang:commons-lang:jar:2.5:compile
[INFO] +- log4j:log4j:jar:1.2.17:compile
[INFO] +- org.apache.zookeeper:zookeeper:jar:3.4.5-cdh4.5.0:compile
[INFO] +- org.apache.thrift:libthrift:jar:0.9.0:compile
[INFO] | +- org.apache.httpcomponents:httpclient:jar:4.3.1:compile (version managed from 4.1.3)
[INFO] | \- org.apache.httpcomponents:httpcore:jar:4.1.3:compile
[INFO] +- org.jruby:jruby-complete:jar:1.6.5:compile
[INFO] +- org.mortbay.jetty:jetty:jar:6.1.26.cloudera.2:compile
[INFO] +- org.mortbay.jetty:jetty-util:jar:6.1.26.cloudera.2:compile
[INFO] +- org.mortbay.jetty:jsp-2.1:jar:6.1.14:compile
[INFO] | \- org.eclipse.jdt:core:jar:3.1.1:compile
[INFO] +- org.mortbay.jetty:jsp-api-2.1:jar:6.1.14:compile
[INFO] +- org.codehaus.jackson:jackson-jaxrs:jar:1.8.8:compile
[INFO] +- org.codehaus.jackson:jackson-xc:jar:1.8.8:compile
[INFO] +- tomcat:jasper-compiler:jar:5.5.23:runtime
[INFO] +- tomcat:jasper-runtime:jar:5.5.23:runtime
[INFO] +- org.jamon:jamon-runtime:jar:2.3.1:compile
[INFO] +- com.google.protobuf:protobuf-java:jar:2.4.0a:compile
[INFO] +- javax.xml.bind:jaxb-api:jar:2.1:compile
[INFO] | \- javax.activation:activation:jar:1.1:compile
[INFO] \- stax:stax-api:jar:1.0.1:compile
I am not sure if this is relevant or not, but I was having some jersey jar conflicts a while back, my hadoop jars were pulling in some jersey artifacts so I threw some exclusions in my pom as follows:
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<artifactId>
jersey-test-framework-grizzly2
</artifactId>
<groupId>
com.sun.jersey.jersey-test-framework
</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-guice</artifactId>
<groupId>com.sun.jersey.contribs</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-server</artifactId>
<groupId>com.sun.jersey</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-core</artifactId>
<groupId>com.sun.jersey</groupId>
</exclusion>
<exclusion>
<artifactId>jersey-json</artifactId>
<groupId>com.sun.jersey</groupId>
</exclusion>
</exclusions>
</dependency>
So when I run my web app, everything seems to be fine until that resource is called when my jsp page loads. Here is the stack trace:
SEVERE: Servlet.service() for servlet [jersey] in context with path [/fungle.funfinder.web] threw exception [A MultiException has 3 exceptions. They are:
1. java.lang.ClassCastException: java.lang.reflect.Method cannot be cast to java.lang.reflect.Constructor
2. java.lang.IllegalArgumentException: While attempting to resolve the dependencies of fungle.funfinder.rest.resource.ActivityTypeResource errors were found
3. java.lang.IllegalStateException: Unable to perform operation: resolve on fungle.funfinder.rest.resource.ActivityTypeResource
] with root cause
java.lang.ClassCastException: java.lang.reflect.Method cannot be cast to java.lang.reflect.Constructor
at org.glassfish.jersey.server.spring.AutowiredInjectResolver.createSpringDependencyDescriptor(AutowiredInjectResolver.java:114)
at org.glassfish.jersey.server.spring.AutowiredInjectResolver.getBeanFromSpringContext(AutowiredInjectResolver.java:97)
at org.glassfish.jersey.server.spring.AutowiredInjectResolver.resolve(AutowiredInjectResolver.java:92)
at org.jvnet.hk2.internal.ClazzCreator.resolve(ClazzCreator.java:214)
at org.jvnet.hk2.internal.ClazzCreator.resolveAllDependencies(ClazzCreator.java:244)
at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:360)
at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:456)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:114)
at org.jvnet.hk2.internal.SingletonContext$1.compute(SingletonContext.java:102)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture$1.call(Cache.java:97)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.glassfish.hk2.utilities.cache.Cache$OriginThreadAwareFuture.run(Cache.java:154)
at org.glassfish.hk2.utilities.cache.Cache.compute(Cache.java:199)
at org.jvnet.hk2.internal.SingletonContext.findOrCreate(SingletonContext.java:153)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2151)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:641)
at org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:626)
at org.glassfish.jersey.internal.inject.Injections.getOrCreate(Injections.java:172)
at org.glassfish.jersey.server.model.MethodHandler$ClassBasedMethodHandler.getInstance(MethodHandler.java:185)
at org.glassfish.jersey.server.internal.routing.PushMethodHandlerRouter.apply(PushMethodHandlerRouter.java:74)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:112)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:115)
at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:94)
at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:63)
at org.glassfish.jersey.process.internal.Stages.process(Stages.java:197)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:261)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:252)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1025)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:382)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:345)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:220)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:744)
I can also post any of my app contexts and/or web xml file, it's just that this post is already pretty long and I think this might be a classpath issue. Let me know if you want to see those.
Please tell me what I'm doing wrong.
==================================
Edit: I just moved the autowired to the constructor and now it is working without exception. Still, I might need to use a setter method in the future for various reasons. Would somebody please tell me why it fails when I autowire the setter? Is this a bug?
This was due to a bug in Jersey (JERSEY-2681). This bug was fixed in Jersey 2.16, which was released in 2015. It was fixed in Jersey GitHub pull request #115.
The best fix therefore would be to update to Jersey 2.16 or later.
The issue was that the Jersey code re-implements some of the Spring autowiring logic, but was missing the setter method case. The exception thrown in the AutowiredInjectResolver class was because method autowiring case wasn't being taken into account; if the autowired element wasn't a field, the code was assuming it's a constructor. So in the case of an autowired method, a ClassCastException was thrown.
private DependencyDescriptor createSpringDependencyDescriptor(final Injectee injectee) {
AnnotatedElement annotatedElement = injectee.getParent();
if (annotatedElement.getClass().isAssignableFrom(Field.class)) {
return new DependencyDescriptor((Field) annotatedElement,
!injectee.isOptional());
} else {
return new DependencyDescriptor(
new MethodParameter((Constructor) annotatedElement, injectee.getPosition()), !injectee.isOptional());
}
}
If your code is stuck on an older version of Jersey and you don't want to use constructor injection, field injection does still work. So you could annotate the field with #Autowired and everything should work. You could still keep the setter around if you still want or need it.
#Autowired
private ActivityTypeDAO activityTypeDAO;
public void setActivityTypeDAO(ActivityTypeDAO activityTypeDAO) {
this.activityTypeDAO = activityTypeDAO;
}

Resources