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
Related
Assume the config, applied both on sending and receiving sides:
#Configuration
#EnableRabbit
public class EventsConfig {
#Bean
public Jackson2JsonMessageConverter messageConverter(ObjectMapper objectMapper) {
return new Jackson2JsonMessageConverter(objectMapper);
}
#Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, Jackson2JsonMessageConverter jackson2JsonMessageConverter) {
final var rabbitTemplate = new RabbitTemplate(connectionFactory);
rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter);
return rabbitTemplate;
}
}
Assume also, that there is a simple Spring Boot RabbitMQ listener on receiving side, declared like:
#RabbitListener(queues = "${amqp.inbox}")
public void listen(org.springframework.amqp.core.Message message) {
...
}
Attempt to receive a collection of List<TaskAssignment> (where TaskAssignment is a simple POJO having two UUIDs), sent by rabbit template, is ended on receiver side with exception:
accounting-service_1 | 01:26:39.610 WARN [org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler$DefaultExceptionStrategy] - Fatal message conversion error; message rejected; it will be dropped or routed to a dead letter exchange, if so configured: (Body:'[{"assigneeId":"1033c1ab-f277-4162-a711-722966bf69ec","taskId":"ae408e2d-39e0-4094-bf52-8c171d965be7"}]' MessageProperties [headers={__ContentTypeId__=java.lang.Object, __TypeId__=io.vavr.collection.List$Cons}, messageId=83f6bb30-a2b8-434a-867e-08684241e9b0, type=TASKS_REASSIGNED, contentType=application/json, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=outbox, receivedRoutingKey=, deliveryTag=3, consumerTag=amq.ctag-PodhhDJx6JtYsjIg6Cof1Q, consumerQueue=accounting-service])
accounting-service_1 | 01:26:39.610 ERROR [org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer] - Execution of Rabbit message listener failed, and the error handler threw an exception
accounting-service_1 | org.springframework.amqp.AmqpRejectAndDontRequeueException: Error Handler converted exception to fatal
accounting-service_1 | at org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler.handleError(ConditionalRejectingErrorHandler.java:146)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeErrorHandler(AbstractMessageListenerContainer.java:1460)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.handleListenerException(AbstractMessageListenerContainer.java:1744)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1519)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:968)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:914)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:83)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1289)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1195)
accounting-service_1 | at java.base/java.lang.Thread.run(Unknown Source)
accounting-service_1 | Caused by: org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Failed to convert message
accounting-service_1 | at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:146)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1656)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1575)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1563)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1554)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1498)
accounting-service_1 | ... 6 common frames omitted
accounting-service_1 | Caused by: org.springframework.amqp.support.converter.MessageConversionException: Failed to convert Message content
accounting-service_1 | at org.springframework.amqp.support.converter.AbstractJackson2MessageConverter.doFromMessage(AbstractJackson2MessageConverter.java:294)
accounting-service_1 | at org.springframework.amqp.support.converter.AbstractJackson2MessageConverter.fromMessage(AbstractJackson2MessageConverter.java:271)
accounting-service_1 | at org.springframework.amqp.support.converter.AbstractJackson2MessageConverter.fromMessage(AbstractJackson2MessageConverter.java:251)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.adapter.AbstractAdaptableMessageListener.extractMessage(AbstractAdaptableMessageListener.java:344)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter$MessagingMessageConverterAdapter.extractPayload(MessagingMessageListenerAdapter.java:347)
accounting-service_1 | at org.springframework.amqp.support.converter.MessagingMessageConverter.fromMessage(MessagingMessageConverter.java:132)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.toMessagingMessage(MessagingMessageListenerAdapter.java:229)
accounting-service_1 | at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:136)
accounting-service_1 | ... 11 common frames omitted
accounting-service_1 | Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `byte` from Object value (token `JsonToken.START_OBJECT`)
accounting-service_1 | at [Source: (String)"[{"assigneeId":"1033c1ab-f277-4162-a711-722966bf69ec","taskId":"ae408e2d-39e0-4094-bf52-8c171d965be7"}]"; line: 1, column: 2] (through reference chain: byte[][0])
accounting-service_1 | at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
Vavr module for Jackson is installed in ObjectMapper, so the root cause is not the fact that the collection is wrong and unserializable.
Notable thing about the stack trace is the headers part:
headers={__ContentTypeId__=java.lang.Object, __TypeId__=io.vavr.collection.List$Cons}
My theory is: since listener has received a JSON array, and Jackson requires explicit TypeReference to be provided in order to deduce a POJO, to which to deserialize array's items, that was the reason failure occurred in Jackson2MessageConverter. Nobody have given it the contents type.
The question is - how to provide Jackson2MessageConverter with such info? RabbitTemplate doesn't seem to give any means. Explicit setup of __ContentTypeId__ on sender side doesn't help either.
Or how to at least overcome Jackson deserialization on receiving side and listen to just raw messages in #RabbitListener with byte[] payload?
UPD: made a project reproducing the issue here: https://www.dropbox.com/s/rde9u02mxob189w/proba_amqp.zip?dl=0
You are attempting to receive the raw, unconverted Message.
Try listen(List<Foo> foos) instead so we can pass the inferred type to the converter.
EDIT
The issue is that your collection object is not compatible with Jackson.
This works
#PostConstruct
public void init() {
List<POJO> payload = new ArrayList<>();
payload.add(new POJO(1,2));
payload.add(new POJO(3,4));
//POJO payload = new POJO(1,2);
template.convertAndSend(
outbox,
"",
payload,
message -> {
var props = message.getMessageProperties();
props.setMessageId(UUID.randomUUID().toString());
return message;
}
);
}
#RabbitListener(queues = "${amqp.inbox}")
public void listen(List<POJO> pojos) {
System.out.println("Message reached:" + pojos);
}
Message reached:[com.skapral.POJO#7af8fa38, com.skapral.POJO#5569d76c]
FROM AUTHOR:
This answer gave me a hint towards the root cause. It turns out there is the bug in vavr-jackson - Jackson module for supporting Vavr collections.
https://github.com/vavr-io/vavr-jackson/issues/189
See if this sample helps you somehow:
https://github.com/spring-projects/spring-amqp-samples/tree/main/spring-rabbit-json
The docs is here: https://docs.spring.io/spring-amqp/docs/current/reference/html/#json-message-converter
UPDATE
See what would be a difference if you use this option on the converter:
/**
* When false (default), fall back to type id headers if the type (or contents of a container
* type) is abstract. Set to true if conversion should always be attempted - perhaps because
* a custom deserializer has been configured on the {#link ObjectMapper}. If the attempt fails,
* fall back to headers.
* #param alwaysAttemptConversion true to attempt.
* #since 2.2.8
*/
public void setAlwaysConvertToInferredType(boolean alwaysAttemptConversion) {
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.
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
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.
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.