1

I am using jboss5.1, EJB3.0 and standalone java application as a 'subscriber'

I have mechanism which publish messages via jms Topic to subscribers. when subscriber get the message it need to do few operations until it will start listening again for a future messages.

the problem is that if a subscriber get a message from the Topic it will need to get back fast enough to listen for further messages(else it will miss it in a case another message will be published)

So my solution is to putThread.sleep() for couple of seconds inside the ejb publisher.

This way ill make sure that all subscribers went back to listen before a new message will be published.

I know that using Thread inside EJB'S is not recommended.

any solution for that scenario?

thanks, ray.

rayman
  • 20,786
  • 45
  • 148
  • 246
  • 1
    What do you mean by "It will miss it?" It looks like you have a design problem when you say: "it will need to get back fast enough to ..." You can almost never rely on the fact that the execution of some code will be fast enough. It should work wheter it takes 1ms or 1hour – Guillaume Polet Apr 20 '12 at 07:55
  • I guess you right. how would you redesign it in such a way that the subscriber will be able to receive messages all the time? – rayman Apr 20 '12 at 09:13
  • 1
    Sorry, I am not a JMS expert so I don't really know how it works and what hypothesis you can make. I don't really understand why you would miss any message. If you are busy doing something else, the message should be queued but not discarded. Do you mean that your subscriber stop listening for new messages when they process an incoming message and they start again to listen when they are done? – Guillaume Polet Apr 20 '12 at 09:30
  • Exactly! the reason for that is that I dont want it to get new message until it finish to process the current one. but in other hand I need it to be able to get all messages which being published (one by one) – rayman Apr 20 '12 at 13:52

3 Answers3

2

IMHO, you shouldn't need to put the publisher's thread at sleep at all. Per definition, when working with JMS and message driven beans, you have the guarantee that messages will be delivered. The only thing that is not guaranteed is the order : the Message Driven Beans may get the messages in an order that is different from the order they've been sent.

Moreover, the whole point of working with JMS is to allow you to send messages asynchronously (even though you could actually configure your queue/topic to work synchronously)

kyiu
  • 1,926
  • 1
  • 24
  • 30
1

OK, so your problem is actually that you stop listening to the JMS queue when you process a message and then you register yourself back. Of course, you could then miss messages while your processing a previous one.

I would suggest to never unregister yourself from the JMS queue and in order to ensure that you process a single message at a time, you could use a single thread pool where you push your processing.

For example, if previously you had something like this:

public void onNewJMSMessage(JMSMessage message) {
    unregisterMySelf();
    processMessage(message);
    registerMySelf();
}

Use this instead:

Initiate a class member like this:

private ExecutorsService processingPool = Executors.newSingleThreadExecutor();

and

public void onNewJMSMessage(final JMSMessage message) {
    processingPool.submit(new Runnable() {

         @Override
         public void run() {
              processMessage(message);
         }
    });
}

This will guarantee that only a single message at a time is processed (if the enclosing class is unique, otherwise you will have to setup a singleton to ensure the uniqueness of the Single-thread pool).

Having done that, this will mainly allow you to remove that Thread.sleep in your EJB which is evil and sources of all kind of headaches.

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • This may cause a large growing memory-consumtion. All messages may be lost, if a OutOfMemoryerror occours. I would suggest a persistent queu/topic instead. (-1) – Christian Kuetbach Apr 20 '12 at 14:12
  • @ckuetbach I don't have enough context to know how important messages are or not, nor do I know how big messages are and how many he is getting. It says that he has a standalone application, so for me outside JEE applications, you may have stateless software which are only clients that can loose or miss some messages when they are shutdown (willingly or not). If he had some way previously to properly store the messages he could of course restore that. – Guillaume Polet Apr 20 '12 at 14:20
  • @ckuetbach I thought again about your comment and I consider it more an improvement rather than saying the solution I suggest is wrong. With regards to the problem asked, it actually solves his issue and removes the main design error made in the first place. The fact that the messages are made persistent or not is more another problem in his software that could be solved by what you suggest. – Guillaume Polet Apr 20 '12 at 14:41
  • I don't mean your answer is wrong at all it will fix the described problem. I just wantet to show a possible error-situation. The problem with your answer is, that the question is about a jboss environment. And it is strongly discouraged to use Threads within an application server. As far as I remember it is forbidden in an EJB-application server. http://stackoverflow.com/questions/533783/why-spawning-threads-in-j2ee-container-is-discouraged – Christian Kuetbach Apr 20 '12 at 14:58
  • @ckuetbach Sorry to bother again, but I think you read too fast. I would be the first to discourage the use of Thread.sleep in EJB's. My solution is not for the publisher part but for the subscriber part. By applying that solution, it will of course allow the removal of the Thread.sleep(). Maybe this was not clear (but it was so obvious to me that I forgot to mention that) – Guillaume Polet Apr 20 '12 at 15:07
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/10328/discussion-between-ckuetbach-and-guillaume-polet) – Christian Kuetbach Apr 20 '12 at 15:09
0

I know this thread is old but I feel compelled to add my two cents. I agree with what Kyiu has said above.

As per EJB2 specifications, an enterprise bean should not manage threads. I am not sure what do the latest specifications have to say about this but I will be shocked if this has been changed.

The thing is that JMS is designed to be such that messages are not lost. So, the MDB is going to consume the messages, no matter what. Also, one should remember that MDBs (like other EJBs) are container managed. Why do you think that there will only be one instance of your MDB working to consume your messages (unless of course, you design it to be that way, which I am sure is not the case).

Aditya K
  • 487
  • 3
  • 11