• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Need help in MDB

 
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I have configured a MDB which listens to a topic :
import javax.jms.*;
import javax.ejb.*;
public class MessageBean implements MessageDrivenBean,MessageListener{
MessageDrivenContext ctx=null;
String s=null;
public void ejbCreate(){};
public void ejbRemove(){};
public void onMessage(Message msg){
System.out.println("MessageBean1");
s.charAt(1);//null string
}


public void setMessageDrivenContext(MessageDrivenContext ctx){
this.ctx=ctx;
}

}

where I am accessing a null String at //line .

And during deployment if I have bean managed transaction,the message "MessageBean1" appears only once on the server console,but if I change it CMT,the message appears multiple times.According to headfirst EJB(page 460) if there is any system exception,both BMT and CMT should put the message again in topic,but in this case,it's happening only for CMT and not for BMT.
Ans I was wondering if this is will hold good for Q also.
 
Author & Gold Digger
Posts: 7617
6
IntelliJ IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
First of all, MDB should never thrown anything else than application exceptions, i.e. no RemoteException and no RuntimeException. In your case, a NullPointerException (which is a RuntimeException) is thrown while the specification forbids it. See section 15.4.13 of the spec and try to throw a valid exception type instead.
 
Amit Sharma#
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Valentin.

But I still have confusion.

Through this code I just wanted to check whether the message is again being put in the topic in case of any Runtime Exception.But this seems to hold good for CMT only as the message is continuously appearing on server console for CMT only and not for BMT.Can you please let me know ,if through my code I have replicated a scenario where the message can be redelievered again if there is some System/Runtime exception.If the answer is 'YES',then why is it behaving differently for BMT and CMT.

I am not sure if this a silly question to ask.
 
Ranch Hand
Posts: 372
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Amit,
In CMT - message acknowlegement is tied to the transaction status. If the transaction is rolled back, the message appears back on the queue.

In BMT - message acknowledgement is tied to the method completion status. If the method does not complete successfully, the message should come back in the queue. This is how it is supposed to behave

If a system exception is thrown, the transaction gets rolled back. The message should come back on the queue in CMT. That is happening in your case for CMT

In BMT, if a system exception is thrown, the method does not complete successfully and hence the message should come back on the queue. My suspicion here is that the line that causes the null pointer exception is the last line. Hence I doubt whether it is assuming that the method is completing succesfully as the last line gets executed. Can you try pushing back that line before the System.out. In that way there will be one more line to be executed before the method completes. can you try that and post the results back? I am eager to know it
 
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Amit,
If you have not solved the problem yet, please provide the following ingo.
1) Which application server are you using ?
2) Provide the DD entries ( What value have you set for acknowledge-mode ?)
 
Amit Sharma#
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I tried moving the code up and I replaced

System.out.println("MessageBean1");
s.charAt(1);

with
System.out.println("MessageBean1");
s.charAt(1);//1
System.out.println("Hi");

So now the null pointer code(//1) has moved up and we have another one line of code to execute after that ,but still the results are same.

Also my DD is

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN' 'http://java.sun.com/dtd/ejb-jar_2_0.dtd'>

<ejb-jar>
<display-name>Ejb2</display-name>
<enterprise-beans>
<message-driven>
<display-name>MessageBean</display-name>
<ejb-name>MessageBean</ejb-name>
<ejb-class>headfirst.MessageBean</ejb-class>
<transaction-type>Bean</transaction-type>
<acknowledge-mode>Auto-acknowledge</acknowledge-mode>
<message-driven-destination>
<destination-type>javax.jms.Topic</destination-type>
<subscription-durability>NonDurable</subscription-durability>
</message-driven-destination>
<security-identity>
<description></description>
<run-as>
<description></description>
<role-name>guest</role-name>
</run-as>
</security-identity>
<resource-env-ref>
<resource-env-ref-name>jms/Topic</resource-env-ref-name>
<resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
</resource-env-ref>
</message-driven>
</enterprise-beans>

and I am using the server available with J2ee SDK(being used in HFEJB)

Also Valentin has pointed that one cannot throw any Runtime/System exception from MDB.But since you don't have any client to MDB,you cannot even throw any Application exception.
Please correct me if I am wrong.
 
Sankar Subbiramaniam
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
From an onMessage() you cannot throw Application exception. But you may throw System exception.
See section 15.4.10 of EJB specs.

regarding your problem: I will get back to you shortly.
 
Sankar Subbiramaniam
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
OK. I refrred to specs & Mastering EJB. I understand that incase of BMT, the receival of message is always acknowledged immaterial of whether an exception occurs in onMessage() method. (i.e) an acknowledgement will be sent when onMessage completes.

I verified this behaviour while receiving messages from both Topic and Queue.

I do not have HFEJB book at the moment to verify your statement:

According to headfirst EJB(page 460) if there is any system exception,both BMT and CMT should put the message again in topic,but in this case,it's happening only for CMT and not for BMT.
Ans I was wondering if this is will hold good for Q also.

 
B.Sathish
Ranch Hand
Posts: 372
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
This might be container specific : the container would let you configure how many times a message should come back to the queue before it is sent to a poison queue. It might also allow you to tweak this number for both BMT and CMT. You might have to check this option out with the container you are using and check what is configured there.
 
Ranch Hand
Posts: 1683
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

First of all, MDB should never thrown anything else than application exceptions, i.e. no RemoteException and no RuntimeException.


According to the EJB 2.0 spec:

The onMessage method of a message-driven bean must not throw application exceptions or the java.rmi.RemoteException.

Message-driven beans, like other well-behaved JMS MessageListeners, should not, in general, throw RuntimeExceptions.



Furthermore, the EJB spec has this to say:

If the bean method encounters a RuntimeException or error, it should simply propagate the error from the bean method to the Container (i.e., the bean method does not have to catch the exception).


So, a NullPointerException should be propagated to the Container. However, whether it actually makes sense to do so is debatable as the message should be put back onto the queue.
 
Amit Sharma#
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Though I have come to know that we cannot throw any application or System exception from MDB as per specs,but still the debatable issue is if we have have any exception,will that message be re-delievered again in case of BMT?

Can we conlude from Sankar's reply that even if there is some exception
thrown from MDB in case of BMT,the message will always be acknowledged and won't be re-delievered again?And this will not be true for CMT.
 
B.Sathish
Ranch Hand
Posts: 372
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No, you cannot come to this conclusion from the EJB specification. As I already said, this behavior may be container-specific. The EJB spec only says that in case of CMT, message acknowledgement is tied to transaction status and in the case of BMT, message acknowledgement is tied to the method completion status. This means - if a system exception is thrown from a BMT onMessage() to the container, the method will not complete successfully and as per the spec, the acknowledgement stands cancelled and the container should instruct the messaging service to put the message back on the queue.

However, it's possible to configure your container such that the message does not come back on the queue if there is a system exception and send it straight to a dead message queue or a poison queue. I advise you to try out this example in a different container like JBoss or weblogic. You might get different results
 
Sankar Subbiramaniam
Ranch Hand
Posts: 116
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Sathish, i couldn't find the information you have specified regarding handling of message acknowledgment. Please provide page.no/section name in the specs form which you are referring. ( I hope you are not quoting from HFEJB. EJB specs is the BIBLE).

This is all i can find in the EJB2.0 specs:
Section 15.4.8, page 317

Message-driven beans should not attempt to use the JMS API for message acknowledgment. Message acknowledgment is automatically handled by the container. If the message-driven bean uses container managed transaction demarcation, message acknowledgment is handled automatically as a part of the transaction commit. If bean managed transaction demarcation is used, the message receipt cannot be part of the bean-managed transaction, and, in this case, the receipt is acknowledged by the container. If bean managed transaction demarcation is used, the Bean Provider can indicate in the acknowedge-mode deployment descriptor element whether JMS AUTO_ACKNOWLEDGE semantics or DUPS_OK_ACKNOWLEDGE semantics should apply. If the acknowledge-mode deployment descriptor element is not specified, JMS AUTO_ACKNOWLEDGE semantics are assumed.




Also refer to exception handling responsibilities of container provider:
Section 18.3.2, Table 17 & 18, page 377 and 378.
[ December 28, 2005: Message edited by: Sankar Subbiramaniam ]
 
B.Sathish
Ranch Hand
Posts: 372
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was referring to HFEJB. MDB chapter last but one page.
 
Roger Chung-Wee
Ranch Hand
Posts: 1683
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Message acknowledgment for BMT beans is tricky as it is poorly understood. Let's look and see what the EJB 2.0 spec has to say.


Message-driven beans should not attempt to use the JMS API for message acknowledgment. Message acknowledgment is automatically handled by the container. If the message-driven bean uses container managed transaction demarcation, message acknowledgment is handled automatically as a part of the transaction commit. If bean managed transaction demarcation is used, the message receipt cannot be part of the bean-managed transaction, and, in this case, the receipt is acknowledged by the container. If bean managed transaction demarcation is used, the Bean Provider can indicate in the acknowedge-mode deployment descriptor element whether JMS AUTO_ACKNOWLEDGE semantics or DUPS_OK_ACKNOWLEDGE semantics should apply. If the acknowledge-mode deployment descriptor element is not specified, JMS AUTO_ACKNOWLEDGE semantics are assumed.


So, message acknowledgment is handled by the container. With CMT, a commit or rollback will cause an acknowledgment or non-acknowledgment of the message, but with BMT the message will always be acknowledged (with no redelivery) even if the onMessage() doesn't return successfully! Note that the setting of the acknowedge-mode deployment descriptor element is irrelevant in that it influences the way that the container does acknowledgement but cannot prevent the container from acknowledging the message.
 
B.Sathish
Ranch Hand
Posts: 372
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Is this a mistake in the Head First EJB?

If that's the case, I would like the authors to give an explanation for this. The book says clearly that in BMT, message acknowledgement is tied to method completion status and that if the method does not complete fully due to some reason, the container asks the messaging service to put the message back on the queue / topic.

Looks like the spec does not say so !!

 
Roger Chung-Wee
Ranch Hand
Posts: 1683
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
It may be helpful to contrast CMT and BMT transactions.

CMT
===
The JTA transaction starts when the JMS provider removes the message from the destination and delivers it to the MDB's onMessage() method. The transaction commits upon successful return from the onMessage() method. But should the EJB container rollback a transaction, the message is automatically redelivered. This is possible because the transaction starts outside the MDB and includes message delivery.

BMT
===
A BMT bean obtains a transaction by calling MessageDrivenContext's getUserTransaction() method. Invoking the UserTransaction interface's begin(), commit() and rollback() methods controls the user transaction. Because the transaction starts inside the MDB, it does not span the JMS provider's message retrieval from the original destination. The transaction has no impact on message acknowledgement and in turn has no impact on message redelivery. Rolling back the transaction does not cause the messages to be redelivered.
 
B.Sathish
Ranch Hand
Posts: 372
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That explanation makes sense. Message delivery is part of the transaction in CMT and roll back of the transaction also causes the message delivery to be rolled back, thus putting the message back on the queue. In BMT, message delivery is not part of the bean started transaction and roll back of the transaction does not cause message delivery to be rolled back which means the acknowledement holds and message does not appear back on the queue.

But my question now is that : Is there something that will cause message redelivery in BMT? If so, what is that? I was thinking it to be the onMessage() method completion status
 
Ranch Hand
Posts: 393
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Is this a bug??
 
Consider Paul's rocket mass heater.
reply
    Bookmark Topic Watch Topic
  • New Topic