JMS send and recv synchronization - java

I have a question about best pattern for JMS message send and recv synchronization...
I have an C++ client talking to J2EE server using JAX-RS (REST) over HTTP. On the server side I have two EJBs - one for resource manipulation and other for session state tracking (#Singleton). And I need to notify client when something is changed, created or deleted on server. So I made this approach:
1 - When client connects and logs in, session bean creates temporary jms queue (non transactional) with code like:
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection.start();
producer = session.createProducer(queue);
consumer = session.createConsumer(queue);
2 - Client call "listener" REST resource which calls:
public void listen() {
...
consumer.recv(timeout);
...
}
and blocks until it got an message or timeout expires.
3 - When I make some changes in resource bean it calls
public void update(...) {
em.update(...);
producer.send(session.createMessage(CHANGE_NOTIFY_MESSAGE));
}
4 - "listener" resource get the message from JMS and returns it to client with changed (created) object information and than client calls "get" method to get created or changed object.
My problem is that "listener" gets message before changes are written to database (I'm using JPA), so when client asks for created or changed object, this one doesn't exist yet or has old information.
How I can modify my alghoritm to be notified only after changes are saved to database?
Thank you for ideas in advance)))

As Steve C says, I think you need to make the session transactional. An example:
// do the operation
em.getTransaction().begin();
em.update(p);
em.getTransaction().commit();
// now you can send
producer.send(session.createMessage(CHANGE_NOTIFY_MESSAGE));

Related

Does akka actors will able to use websocket session ? does websocket connection closes before actors start using?

I am having three actors,able to send data to client from the first actor but some how session is closing for second,third actors.I want what is causing the closing of session,I have tried onClose(..) method but debug pointer is not coming to onClose(..) method.Can any one tell how to intercept the session closing ?
public class ScheduleMgmtWebSocket extends BaseWebSocket {
#OnMessage
public void onMessage(String message, Session session) {
actor1.tell(session);
actor2.tell(session);
}
here when control comes out of onMessage does session closes i.e whole web socket instance closes ?when instance closes actors no more can send data to clients ? Can any expert clarify me please

Producers not getting cleaned while using CachingConnectionFactory

It seems the JMSProducer is not getting garbage collected and keeps alive after delivering messages to queue, I'm using Spring 3.2.2 and CachingConnectionFactory with Keep-alive setting for sending message.
Producers count keeps increasing every time I send message.
Is it related to spring version I am using?
or am I doing something wrong in my configuration?
You need to call close() method on your MessageProducer. As per the Java docs:-
void close()
throws JMSException
Closes the message producer.
Since a provider may allocate some resources on behalf of a MessageProducer outside the Java virtual machine, clients should close them when they are not needed. Relying on garbage collection to eventually reclaim these resources may not be timely enough.
As per the spring CachingConnectionFactory docs :-
NOTE: This ConnectionFactory requires explicit closing of all Sessions
obtained from its shared Connection. This is the usual recommendation
for native JMS access code anyway. However, with this
ConnectionFactory, its use is mandatory in order to actually allow for
Session reuse.
So you need to call getCachedSessionProxy instead of getSession and once done with sending message call the close() (in finally block) . As per the source code, the close call to this Session proxy is handled such that the session and messageproducer is reused. Gary's comments states the same.

Get client-ID through Message in JMS

i'm trying to get the client-id (or connection-id) of a message consumer through a message in JMS.
Is there a way to get it, when i'm only have access to a received message (like in the onMessage method of the MessageListener interface)?
Short: i have a jms message and i want to know the client-id of the consumer who received the message
A Connection object is a client's active connection to its JMS provider. It typically
allocates provider resources outside the Java virtual machine (JVM).
Method of Connection Interface provides following method.
String getClientID() throws JMSException
This value is specific to the JMS provider. It is either preconfigured by an administrator in a ConnectionFactory object or assigned dynamically by the application by calling the setClientID method.

ActiveMQ, how can i create only one consumer?

I'm working with Java EE and ActiveMQ. I want to realize a JMS Queue where I can send messages to my QUEUE and a Consumer + MessageListener should read this messages.
The Code for my Consumer ist the following:
private void initializeActiveMq() throws JMSException {
// Create a ConnectionFactory
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
// Create a Connection
connection = connectionFactory.createConnection();
connection.start();
// Create a Session
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
// Create the destination (Queue)
Queue queue = session.createQueue(queueName);
// Create a MessageConsumer from the Session to the Queue
consumer = session.createConsumer(queue);
consumer.setMessageListener(this);
}
But the problem is, every time i will run this code it ads a new consumer to my queue, and then i have some strange behavior the consumers did then not deliver the messages correctly. If i have only one consumer it works perfect.
So how can I make sure that I have only one consumer in my queue?
I've experienced the exact same issue. You need to make sure that your war has a concept of a graceful shutdown procedure when undeployed.
You can achieve this by having a HTTP Servlet that implements init (do all your initialisation here) and destroy (do all you clearing down here). Destory() will get get called by the JVM when the war is undeployed.
I use Spring to define all my beans, ActiveMQ connections, message consumers and producers. My init() loads the Spring application context from a master xml file, caches a reference to it locally, then the destory() calls close() on the application context.

RMI - create thread on server to serve client

I'm developing a application using rmi which allow client to login, perform some task and logout. I know that each client is considered as one thread when it call a method on server, however, all clients' threads call to the same object created on server. So now, I want to for each client login successfully, a new thread is created (and a new object, which is used by only one client, is binded, too), a thread terminates when client logout. Hence, each client has its own server's object to work with.
Thank you very much.
Cheers
I know that each client is considered
as one thread when it call a method on
server
That's not correct. The relationship between clients and server threads is undefined in RMI.
In any case you don't need a thread per client. You need a remote object per client. This is a job for the Session pattern:
public interface Login extends Remote
{
Session login(String credentials) throws RemoteException;
}
public interface Session extends Remote
{
// Your API here
}
Have your Login implementation object return a new Session implementation object for every client.

Categories

Resources