WebSocket issue : Multiple Endpoints may not be deployed to the same path - spring-boot

i am building project in spring boot and i want to implement chat application logic into my project i am using websockets and here is my code
#SpringBootApplication
public class SamepinchApplication extends SpringBootServletInitializer{
#Bean
public EchoEndpoint echoEndpoint() {
return new EchoEndpoint();
}
#Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
#Bean
public ServletContextAware endpointExporterInitializer(final ApplicationContext applicationContext) {
return new ServletContextAware() {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SamepinchApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SamepinchApplication.class, args);
}
}
and EchoEndpoint
#ServerEndpoint(value = "/api/v1/chat/{username}")
public class EchoEndpoint {
private static final Logger log = LoggerFactory.getLogger(EchoEndpoint.class);
private static final Set<Session> sessionsSet = Collections.synchronizedSet(new HashSet<Session>());
private static final ConcurrentHashMap<String, Object> sessions = new ConcurrentHashMap<String, Object>();
#OnOpen
public void onWebSocketConnect(Session session, #PathParam("username") String uname) throws IOException {
session.getBasicRemote().sendText("Connection established with session id "+session.getId());
sessionsSet.add(session);
sessions.put(uname, session);
System.out.println("Connected with: " + session.getId());
log.info("Connected with: " + session.getId());
}
#OnMessage
public void onWebSocketMessage(Session session, String message) throws IOException {
System.out.println("getting message......");
System.out.println(message.substring(message.indexOf(":",0)+1));
String[] mesgArray = message.split(":");
System.out.println(mesgArray[0]);
Session sess = (Session) sessions.get(mesgArray[0]);
if(sess != null)
sess.getBasicRemote().sendText(message.substring(message.indexOf(":",0)+1));
// sendMessageToAll(message);
}
#OnClose
public void onWebSocketClose(Session session) {
System.out.println("Closed: " + session.getId());
log.info("Closed: " + session.getId());
}
#OnError
public void onWebSocketError(Session session, Throwable error) {
System.out.println("Error (from " + session.getId() + "): " + error.getMessage());
log.info("Error (from " + session.getId() + "): " + error.getMessage());
}
private void sendMessageToAll(String message){
for(Session s : sessionsSet){
try {
log.info("send from qasim siddiqui");
log.info(s.getId());
s.getBasicRemote().sendText(message);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
this code is working fine when i am running code in ecllipse but when i deployed it to tomcat it gives me this exception
SEVERE: ContainerBase.addChild: start:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/samepinch-0.0.1-SNAPSHOT]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1095)
at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1930)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: Failed to register #ServerEndpoint class: class com.samepinch.socket.EchoEndpoint
at org.springframework.web.socket.server.standard.ServerEndpointExporter.registerEndpoint(ServerEndpointExporter.java:148)
at org.springframework.web.socket.server.standard.ServerEndpointExporter.registerEndpoints(ServerEndpointExporter.java:129)
at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterSingletonsInstantiated(ServerEndpointExporter.java:107)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:775)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.context.web.SpringBootServletInitializer.run(SpringBootServletInitializer.java:117)
at org.springframework.boot.context.web.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:108)
at org.springframework.boot.context.web.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:68)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:175)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5517)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 10 more
Caused by: javax.websocket.DeploymentException: Multiple Endpoints may not be deployed to the same path [/api/v1/chat/{username}]
at org.apache.tomcat.websocket.server.WsServerContainer.addEndpoint(WsServerContainer.java:199)
at org.apache.tomcat.websocket.server.WsServerContainer.addEndpoint(WsServerContainer.java:271)
at org.springframework.web.socket.server.standard.ServerEndpointExporter.registerEndpoint(ServerEndpointExporter.java:145)
... 24 more
on tomcat it tries to create multiple endpoints and i am not getting any solution . Can anybody help me!
i am using this dependency for websocket
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

you remove
#Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
Tomcat not need this

You are creating multiple end points in production,you should need echo end point in development not in production..so configure according to the environment
if (Environment.current == Environment.DEVELOPMENT) {
// then create echo point
}

Related

Cannot connect to rabbitmq STOMP from Spring boot

I have used the RabbitMQ docker image which has STOMP enabled. With the following configuration, when I try to run my Spring Boot Application, I am getting an exception.
StackTrace:
2020-11-21 16:03:07.620 INFO 28504 --- [ient-loop-nio-1] o.s.m.s.s.StompBrokerRelayMessageHandler : TCP connection failure in session system: Failed to connect: Connection refused: /127.0.0.1:61613
io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: /127.0.0.1:61613
Caused by: java.net.ConnectException: Connection refused
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~[na:1.8.0_242]
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:714) ~[na:1.8.0_242]
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:330) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final]
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:702) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) ~[netty-transport-4.1.51.Final.jar:4.1.51.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.51.Final.jar:4.1.51.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.51.Final.jar:4.1.51.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.51.Final.jar:4.1.51.Final]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_242]
Dockerfile
FROM rabbitmq:3-management
RUN rabbitmq-plugins enable --offline rabbitmq_stomp
EXPOSE 61613
The logs from Rabbitmq container looks fine to me.
WebSocketConfig.java looks like:
#EnableWebSocketMessageBroker
#Configuration
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws-connection")
.setAllowedOrigins("*")
.withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableStompBrokerRelay("/topic", "/queue")
.setRelayPort(61613)
.setRelayHost("127.0.0.1")
.setClientPasscode("guest")
.setClientLogin("guest");
registry.setApplicationDestinationPrefixes("/ws");
}
}
pom.xml
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
What's wrong with the configuration? Can anyone help me?
I think you made a mistake while exposing the rabbitmq stomp port 61613 for the client. By the way, I tested with a similar configuration it works for me.
For implementation please check my demo application on GitHub or read the following details.
Dockerfile
FROM rabbitmq:3-management
RUN rabbitmq-plugins enable --offline rabbitmq_stomp
EXPOSE 15671 15672 61613
Server Implementation
Message Contract
public class ZbytesMessage {
private String from;
private String text;
...getters and setters...
}
WebSocket Configuration
#Configuration
#EnableWebSocketMessageBroker
public class StompConfig implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/zsockets")
.setAllowedOrigins("*").withSockJS();
}
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableStompBrokerRelay("/topic", "/queue")
.setRelayHost("localhost")
.setRelayPort(61613)
.setClientLogin("guest")
.setClientPasscode("guest");
config.setApplicationDestinationPrefixes("/zbytes");
}
}
Web Controller
#Controller
public class ZbytesController {
private static final Logger LOG = LoggerFactory.getLogger(ZbytesController.class);
#MessageMapping("/hello")
#SendTo("/topic/greetings")
public ZbytesMessage greeting(ZbytesMessage msg) throws Exception {
Thread.sleep(1000); // simulated delay
LOG.info("Received : {} from: {} ", msg.getText(), msg.getFrom());
return msg;
}
}
Server Runner
#SpringBootApplication
public class ServerRunner {
public static void main(String[] args) {
SpringApplication.run(ServerRunner.class, args);
}
}
Client Implementation
public class HelloClient {
private static final WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
private static final Logger LOG = LoggerFactory.getLogger(HelloClient.class);
public static void main(String[] args) throws Exception {
HelloClient helloClient = new HelloClient();
ListenableFuture<StompSession> f = helloClient.connect();
StompSession stompSession = f.get();
LOG.info("Subscribing to greeting topic using session {}", stompSession);
helloClient.subscribeGreetings(stompSession);
LOG.info("Sending hello message {}", stompSession);
helloClient.sendHello(stompSession);
Thread.sleep(60000);
}
public ListenableFuture<StompSession> connect() {
Transport webSocketTransport = new WebSocketTransport(new StandardWebSocketClient());
List<Transport> transports = Collections.singletonList(webSocketTransport);
SockJsClient sockJsClient = new SockJsClient(transports);
sockJsClient.setMessageCodec(new Jackson2SockJsMessageCodec());
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
String url = "ws://{host}:{port}/zsockets";
return stompClient.connect(url, headers, new MyHandler(), "localhost", 8080);
}
public void subscribeGreetings(StompSession stompSession) {
stompSession.subscribe("/topic/greetings", new StompFrameHandler() {
public Type getPayloadType(StompHeaders stompHeaders) {
return byte[].class;
}
public void handleFrame(StompHeaders stompHeaders, Object o) {
LOG.info("Received greeting {}", new String((byte[]) o));
}
});
}
public void sendHello(StompSession stompSession) {
String jsonHello = "{ \"from\" : \"suraj\", \"text\" : \"Hi zbytes!\" }";
stompSession.send("/zbytes/hello", jsonHello.getBytes());
}
private static class MyHandler extends StompSessionHandlerAdapter {
#Override
public void afterConnected(StompSession stompSession, StompHeaders stompHeaders) {
LOG.info("Now connected");
}
}
}
To Run
Build the docker image and run it (don't forget to expose port 61613). (Note: I would prefer docker-compose.yaml)
docker build -t zbytes/rabbitmq .
docker run -p61613:61613 zbytes/rabbitmq
Run ServerRunner java main class.
Run HelloClient java main class.
Server Output
i.g.zbytes.demo.server.ZbytesController : Received : Hi zbytes! from: suraj
Client Output
Received greeting {"from":"suraj","text":"Hi zbytes!"}

SpringBoot + Rabbitmq - DLQ queue not working

I have setup dlq and dlx, but failed message is not redirecting to dlq.
I am trying to send message from java app as well as from rabbitmq server to MESSAGES.EXCHANGE, in both case i am getting message but after throwing the exception message should redirect to DLX.MESSAGES.EXCHANGE but it is happening.
Below is java code and screen shot of rabbitmq serer. everything looks right to me. could not find any problem in code or in rabbitmq server.
Queue setup code -
public class DLQAmqpConfiguration {
public static final String DLX_MESSAGES_EXCHANGE = "DLX.MESSAGES.EXCHANGE";
public static final String DLQ_MESSAGES_QUEUE = "DLQ.MESSAGES.QUEUE";
public static final String MESSAGES_QUEUE = "MESSAGES.QUEUE";
public static final String MESSAGES_EXCHANGE = "MESSAGES.EXCHANGE";
public static final String ROUTING_KEY_MESSAGES_QUEUE = "ROUTING_KEY_MESSAGES_QUEUE";
#Bean
Queue messagesQueue() {
return QueueBuilder.durable(MESSAGES_QUEUE)
.withArgument("x-dead-letter-exchange", DLX_MESSAGES_EXCHANGE)
.build();
}
#Bean
DirectExchange messagesExchange() {
return new DirectExchange(MESSAGES_EXCHANGE);
}
#Bean
Binding bindingMessages() {
return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(ROUTING_KEY_MESSAGES_QUEUE);
}
#Bean
FanoutExchange deadLetterExchange() {
return new FanoutExchange(DLX_MESSAGES_EXCHANGE);
}
#Bean
Queue deadLetterQueue() {
return QueueBuilder.durable(DLQ_MESSAGES_QUEUE).build();
}
#Bean
Binding deadLetterBinding() {
return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange());
}
}
Producer -
this.template.convertAndSend(DLQAmqpConfiguration.MESSAGES_EXCHANGE,
DLQAmqpConfiguration.ROUTING_KEY_MESSAGES_QUEUE, message);
Cunsumer -
#RabbitListener(queues = DLQAmqpConfiguration.MESSAGES_QUEUE)
public void receiveMessage(Message message) throws BusinessException {
System.out.println("Received failed message, re-queueing: " + message.toString());
System.out.println("Received failed message, re-queueing: " + message.getMessageProperties().getReceivedRoutingKey());
throw new BusinessException();
}
// this code never running
#RabbitListener(queues = DLQAmqpConfiguration.DLQ_MESSAGES_QUEUE)
public void processFailedMessages(Message message) {
System.out.println("Received failed message: " + message.toString());
}
Exchange -
QUEUE -
Logs -
Received failed message, re-queueing: (Body:'[B#55c36bc9(byte[26])' MessageProperties [headers={}, contentLength=0, receivedDeliveryMode=PERSISTENT, redelivered=true, receivedExchange=MESSAGES.EXCHANGE, receivedRoutingKey=ROUTING_KEY_MESSAGES_QUEUE, deliveryTag=5444, consumerTag=amq.ctag-KrxkDPlc_uoqHOx_bbnvnA, consumerQueue=MESSAGES.QUEUE])
Received failed message, re-queueing: ROUTING_KEY_MESSAGES_QUEUE
2020-08-27 21:36:33.460 WARN 13192 --- [ntContainer#0-1] s.a.r.l.ConditionalRejectingErrorHandler : Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener method 'public void com.example.rabbitmq.RabbitmqApplication.receiveMessage(org.springframework.amqp.core.Message) throws com.example.rabbitmq.errorhandler.BusinessException' threw exception
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:228) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:148) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:133) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1591) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1510) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1498) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1489) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1433) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:970) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:916) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:83) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1291) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1197) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
Caused by: com.example.rabbitmq.errorhandler.BusinessException: null
You have to set spring.rabbitmq.listener.simple.default-requeue-rejected=false (or ...direct... if using the direct container instead of the simple container) or throw AmqpRejectAndDontRequeueException.
Otherwise, the failed message will be requeued and redelivered.
#SpringBootApplication
public class So63620066Application {
public static void main(String[] args) {
SpringApplication.run(So63620066Application.class, args);
}
public static final String DLX_MESSAGES_EXCHANGE = "DLX.MESSAGES.EXCHANGE";
public static final String DLQ_MESSAGES_QUEUE = "DLQ.MESSAGES.QUEUE";
public static final String MESSAGES_QUEUE = "MESSAGES.QUEUE";
public static final String MESSAGES_EXCHANGE = "MESSAGES.EXCHANGE";
public static final String ROUTING_KEY_MESSAGES_QUEUE = "ROUTING_KEY_MESSAGES_QUEUE";
#Bean
Queue messagesQueue() {
return QueueBuilder.durable(MESSAGES_QUEUE)
.withArgument("x-dead-letter-exchange", DLX_MESSAGES_EXCHANGE)
.build();
}
#Bean
DirectExchange messagesExchange() {
return new DirectExchange(MESSAGES_EXCHANGE);
}
#Bean
Binding bindingMessages() {
return BindingBuilder.bind(messagesQueue()).to(messagesExchange()).with(ROUTING_KEY_MESSAGES_QUEUE);
}
#Bean
FanoutExchange deadLetterExchange() {
return new FanoutExchange(DLX_MESSAGES_EXCHANGE);
}
#Bean
Queue deadLetterQueue() {
return QueueBuilder.durable(DLQ_MESSAGES_QUEUE).build();
}
#Bean
Binding deadLetterBinding() {
return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange());
}
#RabbitListener(queues = MESSAGES_QUEUE)
public void receiveMessage(Message message) {
System.out.println("Received failed message, re-queueing: " + message.toString());
System.out.println(
"Received failed message, re-queueing: " + message.getMessageProperties().getReceivedRoutingKey());
throw new RuntimeException("fail");
}
#RabbitListener(queues = DLQ_MESSAGES_QUEUE)
public void processFailedMessages(Message message) {
System.out.println("Received failed message: " + message.toString());
}
#Bean
public ApplicationRunner runner(RabbitTemplate template) {
return args -> {
template.convertAndSend(MESSAGES_EXCHANGE,
ROUTING_KEY_MESSAGES_QUEUE, "foo");
};
}
}
spring.rabbitmq.listener.simple.default-requeue-rejected=false
Received failed message, re-queueing: ROUTING_KEY_MESSAGES_QUEUE
2020-08-27 12:49:41.056 WARN 11489 --- [ntContainer#0-1] s.a.r.l.ConditionalRejectingErrorHandler : Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.support.ListenerExecutionFailedException: Listener method 'public void com.example.demo.So63620066Application.receiveMessage(org.springframework.amqp.core.Message)' threw exception
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:228) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandlerAndProcessResult(MessagingMessageListenerAdapter.java:148) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:133) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1591) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1510) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1498) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1489) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1433) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:970) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:916) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:83) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1291) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1197) [spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_212]
Caused by: java.lang.RuntimeException: fail
at com.example.demo.So63620066Application.receiveMessage(So63620066Application.java:71) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_212]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_212]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_212]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_212]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171) ~[spring-messaging-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) ~[spring-messaging-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:53) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:220) ~[spring-rabbit-2.2.10.RELEASE.jar:2.2.10.RELEASE]
... 13 common frames omitted
Received failed message: (Body:'foo' MessageProperties [headers={x-first-death-exchange=MESSAGES.EXCHANGE, x-death=[{reason=rejected, count=1, exchange=MESSAGES.EXCHANGE, time=Thu Aug 27 12:49:41 EDT 2020, routing-keys=[ROUTING_KEY_MESSAGES_QUEUE], queue=MESSAGES.QUEUE}], x-first-death-reason=rejected, x-first-death-queue=MESSAGES.QUEUE}, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, redelivered=false, receivedExchange=DLX.MESSAGES.EXCHANGE, receivedRoutingKey=ROUTING_KEY_MESSAGES_QUEUE, deliveryTag=3, consumerTag=amq.ctag--VIXT0V3hhBrlfTFqI5uxg, consumerQueue=DLQ.MESSAGES.QUEUE])

kafkaendpointlistenerregistry.start() throws null pointer exception

I have a requirement where I want to start Kakfa consumer manually.
Code :
class Dummy implements
ConsumerSeekAware
{
#Autowired
KafkaListenerEndpointRegistry registry;
CountDownLatch latch;
#Autowired
ConcurrentKafkaListenerContainerFactory factory;
onIdleEvent(){
latch.countdown()
}
#KafkaListener(id="myContainer",
topics="mytopic",
autoStartup="false")
public void listen() {}
#Scheduled(cron=" some time ")
void do_some_consumption(){
latch = new CountDownLatch(1);
this.registry.getListenerContainer("myContainer").start();
latch.await();
do processing
this.registry.getListenerContainer("myContainer").stop()
}
}
I have made the bean of
ConcurrentKafkaListenerContainerFactory with all props in my other Config class which I am Autowiring here.
However, I get a null pointer exception when I start my container
using this.registry.getListenerContainer("myContainer").start()
java.lang.NullPointerException: null
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.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:93)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
I just copied your code into a Spring Boot app (which auto configures the factories); and everything works perfectly as expected...
#SpringBootApplication
#EnableScheduling
public class So62412316Application {
public static void main(String[] args) {
SpringApplication.run(So62412316Application.class, args);
}
#Bean
public ApplicationRunner runner(KafkaTemplate<String, String> template) {
return args -> {
template.send("mytopic", "foo");
};
}
#Bean
public NewTopic topic() {
return TopicBuilder.name("mytopic").partitions(1).replicas(1).build();
}
}
#Component
class Dummy implements ConsumerSeekAware {
#Autowired
KafkaListenerEndpointRegistry registry;
CountDownLatch latch;
#Autowired
ConcurrentKafkaListenerContainerFactory factory;
#EventListener
public void onIdleEvent(ListenerContainerIdleEvent event) {
System.out.println(event);
latch.countDown();
}
#KafkaListener(id = "myContainer", topics = "mytopic", autoStartup = "false")
public void listen(String in) {
System.out.println(in);
}
#Scheduled(initialDelay = 5_000, fixedDelay = 60_000)
void do_some_consumption() throws InterruptedException {
latch = new CountDownLatch(1);
this.registry.getListenerContainer("myContainer").start();
latch.await();
this.registry.getListenerContainer("myContainer").stop();
}
}
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.listener.idle-event-interval=5000

AQ and Spring Integration - java.lang.IllegalStateException: No 'defaultDestination' or 'defaultDestinationName' specified

When trying to run an Spring Integration application on Weblogic and connect to AQ I am getting the following error:
2016-11-08 18:07:53.677 ERROR 12864 --- [ask-scheduler-7] o.s.integration.handler.LoggingHandler : java.lang.IllegalStateException: No 'defaultDestination' or 'defaultDestinationName' specified. Check configuration of JmsTe
mplate.
at org.springframework.jms.core.JmsTemplate.getRequiredDefaultDestinationName(JmsTemplate.java:216)
at org.springframework.jms.core.JmsTemplate.receiveSelected(JmsTemplate.java:738)
at org.springframework.integration.jms.JmsDestinationPollingSource.doReceiveJmsMessage(JmsDestinationPollingSource.java:141)
at org.springframework.integration.jms.JmsDestinationPollingSource.receive(JmsDestinationPollingSource.java:111)
at org.springframework.integration.endpoint.SourcePollingChannelAdapter.receiveMessage(SourcePollingChannelAdapter.java:209)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.doPoll(AbstractPollingEndpoint.java:245)
at org.springframework.integration.endpoint.AbstractPollingEndpoint.access$000(AbstractPollingEndpoint.java:58)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:190)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:186)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:353)
at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:55)
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50)
at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:51)
at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:344)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
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 my code:
#SpringBootApplication
#EnableIntegration
#IntegrationComponentScan
public class AQMessageProcessorApplication extends SpringBootServletInitializer implements WebApplicationInitializer {
private static final String DATAFLOW_ACDR = "urn:xeu:ec:fisheries:flux-bl:FLUX_ACDR_OtherReport:1:1";
private static final Logger logger = LoggerFactory.getLogger(AQMessageProcessorApplication.class);
#Autowired
private ConnectionFactory aqConnectionFactory;
#Autowired
private Destination aqAcdrQueue;
public static void main(String[] args) {
SpringApplication.run(AQMessageProcessorApplication.class, args);
}
#Bean
public IntegrationFlow aqAcdrInboundFlow() {
return IntegrationFlows
.from(
Jms.inboundAdapter(this.aqConnectionFactory)
.destination(aqQueue),
e -> e.poller( Pollers.fixedRate(100, TimeUnit.MILLISECONDS).maxMessagesPerPoll(100))
)
.enrich(e -> e
.requestPayload(Message::getPayload)
.shouldClonePayload(false)
)
.transform( message-> message )
.channel("entrypoint")
.get();
}
#Bean
public ConnectionFactory aqConnectionFactory() {
ConnectionFactory factory = null;
JndiTemplate jndi = new JndiTemplate();
try {
factory = (ConnectionFactory) jndi.lookup("jms/QCF");
} catch (NamingException e) {
logger.error("NamingException for jms/QCF", e);
}
return factory;
}
#Bean
public Destination aqWeblogicQueue() {
Destination destination = null;
JndiTemplate jndi = new JndiTemplate();
try {
destination = (Destination) jndi.lookup("jms/Q_TEST");
} catch (NamingException e) {
logger.error("NamingException for jms/Q_TEST ", e);
}
return destination;
}
}
I have tried this code with WebLogic queues and it worked no problem.
What silly thing am I missing here?
Regards!

Spring 4 + hibernate 4 + c3p0 : Could not obtain transaction-synchronized Session for current thread

I an trying to run simple application that uses Spring 4, Hibernate 4, and c3p0 pooling, and I keep getting this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao': Invocation of init method failed; nested exception is org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:408)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1560)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:540)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:762)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4937)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)
Caused by: org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:134)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
at ggdb.components.database.dao.GenericDao.getCurrentSession(GenericDao.java:61)
at ggdb.components.database.dao.UserDao.getUser(UserDao.java:36)
at ggdb.components.database.dao.UserDao.postConstruct(UserDao.java:24)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:349)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:300)
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:133)
... 23 more
Here is my configuration:
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
public class DatabaseConfigutarion implements TransactionManagementConfigurer {
#Autowired
private Environment env;
public class PropertiesKeys {
public static final String DATABASE_HOST = "database.host";
public static final String DATABASE_PORT = "database.port";
public static final String DATABASE_USERNAME = "database.username";
public static final String DATABASE_PASSWORD = "database.password";
public static final String DATABASE_NAME = "database.database_name";
public static final String DATABASE_ADDITIONAL_CONNECTION_PROPERTIES = "database.additional.connection.properties";
public static final String HIBERNATE_DEFAULT_SCHEMA = "hibernate.default_schema";
public static final String HIBERNATE_HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";
}
#Bean
public SessionFactory sessionFactory() {
String databaseUrl = String.format("jdbc:mysql://%s:%s/%s", env.getProperty(PropertiesKeys.DATABASE_HOST), env.getProperty(PropertiesKeys.DATABASE_PORT), env.getProperty(PropertiesKeys.DATABASE_NAME));
String additionnalProperties = env.getProperty(PropertiesKeys.DATABASE_ADDITIONAL_CONNECTION_PROPERTIES);
databaseUrl = ( additionnalProperties.isEmpty() ? databaseUrl : String.format("%s?%s", databaseUrl, additionnalProperties) );
org.hibernate.cfg.Configuration configuration = new org.hibernate.cfg.Configuration();
configuration.setProperty("hibernate.connection.driver_class", com.mysql.jdbc.Driver.class.getName());
configuration.setProperty("hibernate.connection.url", databaseUrl);
configuration.setProperty("hibernate.connection.username", env.getProperty(PropertiesKeys.DATABASE_USERNAME));
configuration.setProperty("hibernate.connection.password", env.getProperty(PropertiesKeys.DATABASE_PASSWORD));
configuration.setProperty("hibernate.c3p0.min_size", "5");
configuration.setProperty("hibernate.c3p0.max_size", "20");
configuration.setProperty("hibernate.c3p0.timeout", "1800");
configuration.setProperty("hibernate.c3p0.max_statements", "50");
configuration.setProperty("hibernate.current_session_context_class", org.springframework.orm.hibernate4.SpringSessionContext.class.getName());
configuration.setProperty("hibernate.dialect", org.hibernate.dialect.MySQL5InnoDBDialect.class.getName());
configuration.setProperty("hibernate.show_sql", "false");
configuration.setProperty("hibernate.format_sql", "false");
configuration.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");
configuration.setProperty("hibernate.default_schema", env.getProperty(PropertiesKeys.HIBERNATE_DEFAULT_SCHEMA));
configuration.setProperty("hibernate.hbm2ddl.auto", env.getProperty(PropertiesKeys.HIBERNATE_HBM2DDL_AUTO));
configuration.addAnnotatedClass(ggdb.components.database.entities.User.class);
configuration.addAnnotatedClass(ggdb.components.database.entities.Role.class);
ServiceRegistry serviceRegistry = (new StandardServiceRegistryBuilder())
.applySettings(configuration.getProperties())
.build();
SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
}
#Bean
public HibernateTransactionManager transactionManager(){
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory());
return transactionManager;
}
#Override
public HibernateTransactionManager annotationDrivenTransactionManager() {
return transactionManager();
}
public Environment getEnv() {
return env;
}
public void setEnv(Environment env) {
this.env = env;
}
}
And code that throws error:
#Repository
public class UserDao extends GenericDao<User> {
public UserDao() {
super(User.class);
}
// TODO: this method is temporary,
// should be removed later,
#PostConstruct
#Transactional
public void postConstruct() {
User user = getUser("user");
if (user == null) {
user = new User();
user.setUsername("user");
user.setPassword("pass");
save(user);
}
}
#Transactional
public User getUser(String username) {
#SuppressWarnings("unchecked")
List<User> users = (List<User>) getCurrentSession().getNamedQuery(User.FIND_BY_USERNAME).setParameter("username", username).list();
return (users.isEmpty() ? null : users.get(0));
}
}
Extended class code:
public class GenericDao<T> {
private final Class<T> parameterClass;
#Autowired
protected SessionFactory sessionFactory;
public GenericDao(Class<T> parameterClass) {
this.parameterClass = parameterClass;
}
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
public Long save(T t) {
return (Long) getSession().save(t);
}
public void delete(Long id) {
getSession().delete(id);
}
#SuppressWarnings("unchecked")
public T get(Long id) {
return (T) getSession().get(parameterClass, id);
}
public void refresh(T t) {
getSession().refresh(t);
}
#SuppressWarnings("unchecked")
public T merge(T t) {
return (T) getSession().merge(t);
}
public void update(T t) {
getSession().update(t);
}
public void saveOrUpdate(T t) {
getSession().saveOrUpdate(t);
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
Can you help me? Where is the problem?
Invocation of init method failed. You could try to add this:
#Autowired
public void init(SessionFactory factory) {
setSessionFactory(factory);
}
to your GenericDAO.

Resources