HornetQ allows only one session per connection - jboss6.x

I am using HornetQ in distributed transaction environment with MDBs. I read from the JMS documentation that we should not create Connection instance frequently, rather we should reuse the connection and create JMS sessions as and when required. So I wrote a code which creates JMS connection and then reuse it. But I have encountered the following exception while reusing the JMS connection object.
Could not create a session: Only allowed one session per connection.
See the J2EE spec, e.g. J2EE1.4 Section 6.6
I read few blogs on this but they all are specific to seam framework.
Here is my code
public class DefaultService implements IMessageService {
private static final long serialVersionUID = 1L;
private static final Logger logger = LogManager.getLogger(DefaultService.class);
private static final String connectionFactoryJndiName = "java:/JmsXA";
private static volatile Connection connection = null;
private Session session = null;
#Override
public void sendMessage(String destinationStr, Serializable object) {
try {
Destination destination = jmsServiceLocator.getDestination(destinationStr);
ObjectMessage message = session.createObjectMessage();
message.setObject(object);
MessageProducer messageProducer = session.createProducer(destination);
messageProducer.send(destination, message);
messageProducer.close();
logger.trace("Sent JMS Messagae for: " + object.getClass().getName());
}
catch (NamingException e) {
throw new RuntimeException("Couldn't send jms message", e);
}
catch (JMSException e) {
throw new RuntimeException("Couldn't send jms message", e);
}
}
#Override
public void close() {
try {
if (session != null) {
session.close();
}
}
catch (Exception e) {
logger.error("Couldn't close session", e);
}
}
}
I am using JBoss EAP 6.
Did I miss any settings here?

On JCA connection (i.e. connection where you used the PooledConnectionFactory) you are supposed to create one Session only per connection. That is part of the EE specification. (It has always been).
This is because these connections are pooled and it would be impossible to put them back on the pool if you were using more than one session per connection.
If you switch for non pooled connection factories (the ones that are meant for remote clients) you would have it working the way you wanted but then you would miss pooling from the application server. EE components are usually short lived and opening / closing JMS Connections (any connection to be more precise) it's an expensive operation.

Related

Netty ChannelInboundHandlerAdapter async/multithreading

I'm having trouble grasping the concepts behind multithreading in netty, EventLoopGroup (MultithreadEventLoopGroup), MultithreadEventExecutorGroup, DefaultEventExecutorGroup
I am trying to understand how the server handles multiple clients simultaneously sending requests that will execute some business logic and CRUD operations that add to RTT. Below is my netty server code which works, but I am trying to understand exactly how it will work with concurrent users and multiple open channels.
I have a simple ServerBootstrap
#Component
#RequiredArgsConstructor
public class SocketServer {
private final ContextAwareLogger logger;
private final ServerInitializer serverInitializer;
private final NioEventLoopGroup bossGroup;
private final NioEventLoopGroup workerGroup;
private Channel mainChannel;
#PostConstruct
public void start() {
try {
ServerBootstrap bootstrap = init();
mainChannel = bootstrap.bind(8484).sync().channel(); // save the main channel so we can cleanly close it when app is shutdown
logger.info("Netty server started...");
} catch (Exception e) {
e.printStackTrace();
}
}
#PreDestroy
public void stop() throws InterruptedException {
logger.info("Shutting down Netty server");
bossGroup.shutdownGracefully().sync();
workerGroup.shutdownGracefully().sync();
mainChannel.closeFuture().sync();
logger.info("Netty Server shutdown complete.");
}
private ServerBootstrap init() {
return new ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 5000)
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.SO_KEEPALIVE, true)
.childHandler(serverInitializer);
}
}
ChannelInitializer:
#Component
#RequiredArgsConstructor
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
private final PacketDecoder packetDecoder;
private final ServerHandler serverHandler;
private final PacketEncoder packetEncoder;
#Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline()
.addLast("decoder", packetDecoder) // ByteArrayDecoder
.addLast("encoder", packetEncoder) // ByteArrayEncoder
.addLast("inbound", serverHandler); // ChannelInboundHandlerAdapter
}
}
ChannelInboundHandlerAdapter:
#Component
#Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter {
#Autowired
private SomeService someService;
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// contains db access
byte[] accept = someService.validateClient(ctx.channel());
ctx.channel().writeAndFlush(accept);
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// may contain db access
byte[] response = someService.processPacket(ctx.channel(), msg));
ctx.channel().writeAndFlush(response);
}
}
Now when a client connects, I understand that a new Channel will opened and the handlers will be reused. Requirement is each client request/response needs to process immediately without waiting for some other client's CRUD operations to finish.
Are my channelRead and channelActive, etc, async because I am using NioEventLoopGroup (ie will each client's channel operations be run independent of each other)?
If a single client sends multiple requests in series, are they guaranteed to be handled in the same order?
Do I need to specific DefaultEventExecutorGroup for my inbound handler? (https://stackoverflow.com/a/28305019/1738539)
You either would need to use a DefaultEventExecutorGroup for your ServerHandler or dispatch the validateClient(...) / processPacket(...) to your own ThreadPool. Failing todo so will cause the EventLoop thread to block and so no other IO can be processed for this EventLoop until the blocking operation completes.

How to multi-thread parsing of JMS messages

In my Spring Boot project, I have two JMS listeners listening to one queue. All messages received from the queue have to be processed in the same way and persisted / updated in the database (Oracle). Currently, I have a synchronized method in a class that is doing the parsing of the messages. As expected, all thread read messages simultaneously, but parsing is done one by one as the method (parseMessage()) is synchronized. What I want is to parse the messages simultaneously and do database operations as well.
How can I solve this?
I don't want to create two different classes with the same code and use #Qualifier to call different classes in each listener, as the code for parsing the message is the same.
The ideal solution, I think, is to do database operations using a new synchronized method in a new class, but parsing the message in a multi-threaded way. So, at a time only one thread can say persist / update. When a thread is not waiting to persist / update, it continues the parsing on its own thread.
Please correct me if I am wrong or if you find the optimal solution. Let me know if any other info is needed.
JMS Controller Class
#RestController
#EnableJms
public class JMSController {
#Autowired
private IParseMapXml iParseMapXml;
#JmsListener(destination = "${app.jms_destinaltion}")
public void receiveMessage1(String recvMsg) {
try {
InputSource is = new InputSource(new StringReader(recvMsg.replaceAll("&", "&amp")));
Document doc = new SAXReader().read(is);
iParseMapXml.parseMessage(doc);
} catch (Exception e) {
}
}
#JmsListener(destination = "${app.jms_destinaltion}")
public void receiveMessage2(String recvMsg) {
try {
InputSource is = new InputSource(new StringReader(recvMsg.replaceAll("&", "&amp")));
Document doc = new SAXReader().read(is);
iParseMapXml.parseMessage(doc);
} catch (Exception e) {
}
}
}
Parse XML Interface
public interface IParseMapXml {
public void parseMessage(Document doc);
}
Parsing Implementation
public class ParsingMessageClass implements IParseMapXml{
#Override
#Transactional
synchronized public void parseMessage(Document doc) {
// TODO Auto-generated method stub
....
PROCESS DATA/MESSAGE
....
DO DB OPERATIONS
}
}

Hazelcast listeners don't work after client reconnects

My hazelcast client got disconnected because of possible memory outbreak. After the client reconnects, it is not getting getting messages from listeners on maps and topics. Is there a way to make the client active to the listeners again ?
This is how I am initiating a listener in my client/service:
IMap liveMap = hazelcastCacheClientService.getMap("MYMAP");
MyListener myMapListener = new MyListener();
liveMap.addEntryListener(myMapListener,true);
This is how my listener looks like:
public class MyListener implements EntryListener {
#Override
public void entryAdded(EntryEvent entryEvent) {
//do something
}
#Override
public void entryEvicted(EntryEvent entryEvent) {
}
#Override
public void entryRemoved(EntryEvent entryEvent) {
}
#Override
public void entryUpdated(EntryEvent entryEvent) {
//do something
}
#Override
public void mapCleared(MapEvent mapEvent) {
}
#Override
public void mapEvicted(MapEvent mapEvent) {
}
}
I have multiple other services, who put entries into the map.
If your version is 3.9 or older it could be a bug. We improved the client reconnect logic in 3.10 and further improved it in 3.11. Here are the 3.11 documentation for client reconnect configuration: https://docs.hazelcast.org/docs/3.11/manual/html-single/index.html#configuring-client-connection-retry
Now having said that I always recommend an additional circuit breaker pattern such as the one from netflix: https://github.com/Netflix/Hystrix/wiki/How-it-Works
In order to restore the client listeners it is best to destroy the hazelcastinstance and create a new one. This forces all the sockets to perform an init during startup. Hazelcast is a socket application so if you suffer from 1/2 open sockets then there is not much Hazelcast can do about restoring the connections.
Hope this helps,

Spring Redis template with Jedis connection factory , Redis standalone configuration and multi-threading

I am using Spring Redis template in a multi-threaded environment. One thread saves the data into Redis and other one (the scheduler) fetches the data from it. JedisConnectionFactory is used in redis template. Following is the code snippet for obtaining redis connection:
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = null;
try {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(hostName,
port);
jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration);
} catch (RedisConnectionFailureException e) {
LOGGER.error("Connection break with redis " + e.getMessage());
}
return jedisConnectionFactory;
}
/**
* Redis template.
*
* #return the redis template
*/
#Bean
public RedisTemplate<String, Object> redisTemplate() {
final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(jedisConnectionFactory());
template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));
template.setEnableTransactionSupport(true);
return template;
}
The instance of redis template is obtained using constructor auto-wiring as follows:
#Autowired
public A(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
I am getting an exception while fetching data from Redis using "findAll()" method of redis template:
org.springframework.data.redis.RedisConnectionFailureException: java.net.SocketException: Connection reset by peer: socket write error; nested exception is redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketException: Connection reset by peer: socket write error
Below are my findings:
connection reset by peer exception occurs when TCP socket is to be "closing" and your code to not have yet been notified. (the thread for findAll has not been notified for the closed connection).
Redis template is thread safe (only if connection pool is used) and handles connection management on its own. It may happen that when thread saved data into redis and closed the connection and during that only, the fetch operation occured and demanded data. In that case, the server might have issued RST command but fetch operation might have not obtained it.
Jedis pool config can be used; but there are depreciated methods in this that can later cause upgradation issues.
Please suggest best method to handle multi-threading with "JedisConnectionFactory", "RedisStandAloneConfiguration" and "RedisTemplate".
The cause of this problem was :
Redis Template is thread safe but only when it uses connection pooling; If connection pool is not used then the simultaneous connection calls result in RST signal from either (server / client) side and thus 'connection reset by peer' exception is thrown. SO, if we need to use Redis template then create a connection pool and set 'maxIdle' and 'maxTotal' for the pool config. Also, make sure that the system should not goes down (sleep) in any case.
Code that worked correctly:
#Bean
JedisConnectionFactory jedisConnectionFactory() {
JedisConnectionFactory jedisConnectionFactory = null;
try {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(hostName,
port);
jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration);
jedisConnectionFactory.getPoolConfig().setMaxTotal(50);
jedisConnectionFactory.getPoolConfig().setMaxIdle(50);
} catch (RedisConnectionFailureException e) {
e.getMessage();
}
return jedisConnectionFactory;
}
#Bean
public RedisTemplate<String, Object> redisTemplate() {
final RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(jedisConnectionFactory());
template.setValueSerializer(new GenericToStringSerializer<Object>(Object.class));
template.setEnableTransactionSupport(true);
return template;
}

On servlet 3.0 webserver, is it good to make all servlets and filters async?

I am confused with Async feature introduced in Servlet 3.0 spec
From Oracle site (http://docs.oracle.com/javaee/7/tutorial/doc/servlets012.htm):
To create scalable web applications, you must ensure that no threads
associated with a request are sitting idle, so the container can use
them to process new requests.
There are two common scenarios in which a thread associated with a
request can be sitting idle.
1- The thread needs to wait for a resource to become available or process data before building the response. For example, an application
may need to query a database or access data from a remote web service
before generating the response.
2- The thread needs to wait for an event before generating the response. For example, an application may have to wait for a JMS
message, new information from another client, or new data available in
a queue before generating the response.
The first item happens a lot (nearly always, we always query db or call a remote webservice to get some data). And calling an external resource will always consume some time.
Does it mean that we should ALWAYS use servelt async feature for ALL our servelts and filter ?!
I can ask this way too, if I write all my servelts and filters async, will I lose anything (performance)?!
If above is correct the skeleton of ALL our servlets will be:
public class Work implements ServletContextListener {
private static final BlockingQueue queue = new LinkedBlockingQueue();
private volatile Thread thread;
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
thread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
ServiceFecade.doBusiness();
AsyncContext context;
while ((context = queue.poll()) != null) {
try {
ServletResponse response = context.getResponse();
PrintWriter out = response.getWriter();
out.printf("Bussiness done");
out.flush();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
context.complete();
}
}
} catch (InterruptedException e) {
return;
}
}
}
});
thread.start();
}
public static void add(AsyncContext c) {
queue.add(c);
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
thread.interrupt();
}
}

Resources