[ openjms-Bugs-831469 ] ClassCastException when using MDBs in Sun ONE AS7
"SourceForge.net" <[email protected]>
| Newsgroups | gmane.comp.java.openjms.devel |
|---|---|
| Message-ID | <[email protected]> |
Bugs item #831469, was opened at 2003-10-28 11:26 Message generated for change (Settings changed) made by tanderson You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=474136&aid=831469&group_id=54559 Category: client Group: v0.7.6-rc3 >Status: Closed Resolution: Fixed Priority: 5 Submitted By: Bo Min Jiang (jiangb) Assigned to: Tim Anderson (tanderson) Summary: ClassCastException when using MDBs in Sun ONE AS7 Initial Comment: I am running Sun ONE Application Server 7 with OpenJMS as the JMS provider, and have run into a problem with Message Driven Beans. In the onMessage method of class org.exolab.jms.client.JmsConnectionConsumer, a ServerSession object is being retrieved from a server session pool, and is then cast into a JmsServerSession object. However, the server session pool is an application server specific object (for Sun ONE AS7, it's implemented by class com.iplanet.ias.ejb.containers.IASServerSessionImpl), and cannot necessarily be cast into an a JmsServerSession object - a ClassCastException occurs as a result. Unfortunately, Sun ONE does not allow me to specify a different implementation of the ServerSession interface. Is there a workaround for the problem described? I need to use Sun ONE AS7, and am curious if a similar problem exists when using other application servers. ---------------------------------------------------------------------- Comment By: Bo Min Jiang (bmjiang) Date: 2004-01-13 14:09 Message: Logged In: YES user_id=645251 I've tested the changes - the ClassCastException no longer appears, and the MDBs that I used for testing work as expected. I did, however, have to make a couple of classes serializable in order for Sun ONE AS7 to perform JNDI lookups of OpenJMS resources - please see item #875841. ---------------------------------------------------------------------- Comment By: Tim Anderson (tanderson) Date: 2004-01-11 13:40 Message: Logged In: YES user_id=557161 Fixes checked in to CVS. Please test it as this is the only thing holding up the final 0.7.6 release. Note that the fix isn't 100% compliant with the JMS specification, as messages are being acked by the ConnectionConsumer - they should be acked by the session responsible for processing the message, in its run() method. ---------------------------------------------------------------------- Comment By: Tim Anderson (tanderson) Date: 2003-12-23 00:33 Message: Logged In: YES user_id=557161 I don't believe the changes are in the spirit of the JMS spec. Section 8.2.6 states that the application server is responsible for creating the thread associated with the Session, so the thread creation in JmsSession.run() should be redundant. This also means that the session could be accessed by multiple threads of control, which is not supported by the spec. There is no need to cast to a JmsServerSession - in fact this class should be removed. Also, the message shouldn't be acknowledged in JmsConnectionConsumer.onMessage() - the ServerSessionPool could create CLIENT_ACKNOWLEDGE or transacted sessions. ---------------------------------------------------------------------- Comment By: Tim Anderson (tanderson) Date: 2003-12-17 23:38 Message: Logged In: YES user_id=557161 Will have a look at the changes this weekend (20/12). Note that patches can be applied faster if you attach diffs, as per http://openjms.sourceforge.net/volunteers.html#Submitting changes ---------------------------------------------------------------------- Comment By: Neil Kolban (kolban) Date: 2003-12-10 10:39 Message: Logged In: YES user_id=625504 I realize that this is completely against the spirit of OpenSource ... but I would love to test your changes ... however ... I am not skilled on building Java apps/classes. Would it be possible to email me a copy of your changes as replacement JAR files and I will test on WAS V5.1 on your behalf? Neil (kolban-r/[email protected]) ---------------------------------------------------------------------- Comment By: Bo Min Jiang (bmjiang) Date: 2003-12-10 06:56 Message: Logged In: YES user_id=645251 I downloaded the source for version v0.7.6-rc1 and made some changes that will allow OpenJMS to work with Sun ONE when it comes to MDBs. I've done some testing, and would like to get feedback on whether my logic is correct and applies with other app servers. The changes I made are as follows: JmsSession: -------------------------------- /** * The message cache holds all messages for the session. The messages are * sent to the listener during start. */ private Vector _messageCache = new Vector(); /** * Add a message to the message cache. This message will be processed * when the start method is called. * * @param message message to add. */ void addMessage(Message message) { _messageCache.addElement(message); } // implementation of Session.run public void run() { // application server functionality (new Thread(new Runnable() { /** * This method will iterate through the list of messages * in the cache and send them to the registered listener */ public void run() { try { Enumeration messages = _messageCache.elements(); while (messages.hasMoreElements()) { _listener.onMessage((Message) messages.nextElement()); } } catch (Exception exception) { _log.error( "Error in the Session.run method", exception); } finally { // Clear message cache _messageCache.clear(); } } })).start(); } JmsConnectionConsumer: -------------------------------- public void onMessage(Message message) { try { // not very sophisticated at this point. Simply get a server // session put the message in it and start it. getSession().acknowledgeMessage(message); ServerSession serverSession = (ServerSession) _pool.getServerSession(); //-------------------------- // BMJ - changes to work with JMSServerSession // and other app servers //-------------------------- // If ServerSession is instance of JmsServerSession, then add message // to server session, else add message to session in app server specific server session if (serverSession instanceof JmsServerSession) { JmsServerSession localSession = (JmsServerSession) _pool.getServerSession(); localSession.addMessage(message); localSession.start(); } else { // ServerSession is application server specific. Therefore add // message to session and process JmsSession session = (JmsSession) serverSession.getSession(); session.addMessage(message); // Cause the Session's run method to be called to process messages that were just assigned to it. serverSession.start(); } } catch (Exception exception) { _log.error(exception, exception); } } ---------------------------------------------------------------------- Comment By: Neil Kolban (kolban) Date: 2003-12-09 13:31 Message: Logged In: YES user_id=625504 Folks, For what its worth ... I stumbled into EXACTLY this problem trying to integrate OpenJMS with IBM's WebSphere Application Server V5. Exactly the same problem, exactly the same symptoms. Unfortunately, I have no skills or time to go further into the guts of OpenJMS and *contribute* any solutions but I would be DELIGHTED to hear from anyone who attempts to get this working and am willing to run tests ... Neil (kolban-r/[email protected]) ---------------------------------------------------------------------- Comment By: Mike Spille (scubabear68) Date: 2003-11-19 07:06 Message: Logged In: YES user_id=583085 I don't have time for a fully integrated diff, but the essence of the fix for this is: JmsSession.run(): public void run() { if (connConsumer == null) { return; } Message msg; while ((msg = connConsumer.nextMessage()) != null) { execute (msg); } connConsumer = null; } JmsConnectionConsumer: abstract class JmsConnectionConsumer implements ConnectionConsumer, MessageListener { private Message activeMessage; private static int objCount = 0; /** * This constructor simply manaages the server session pool and the * the maximum number of messages that can be loaded on any one server * session. * * @param pool the server session pool * @param maxMessages max number of messages it can send to down * a server session object at any one time. */ JmsConnectionConsumer(ServerSessionPool pool, int maxMessages) { pool_ = pool; maxMessages_ = (maxMessages > 0) ? maxMessages : 1; objCount++; } /** * Return a reference ot the server session pool instance use by this * object * <p> * If the object is not set or there is any other issue throw the * JMSException exception. * * @return ServerSessionPool * @exception JMSException */ public ServerSessionPool getServerSessionPool() throws JMSException { return pool_; } /** * Since a provider may allocate some resources on behalf of a * ConnectionConsumer outside the JVM, clients should close them when * they are not needed. Relying on garbage collection to eventually * reclaim these resources may not be timely enough. * * @exception JMSException if a JMS fails to release resources on * behalf of ConnectionConsumer or it fails * to close the connection consumer. */ public void close() throws JMSException { pool_ = null; } /** * Impmentation of MessageListener.onMessage, which will receive * messages from the server. In this most simply case it actually * loads each individual message into a server session and calls * the start method. * <p> * If this methods gets an error then it will send an error message * to the logger and return successful * * @param message message send back by the server. */ public void onMessage(Message message) { try { // not very sophisticated at this point. Simply get a server // session put the message in it and start it. /* MWS - This looks incorrect. The App Server implements the ServerSession pool object, therefore it's wrong for us to assume it's one of ours getSession().acknowledgeMessage(message); JmsServerSession local_session = (JmsServerSession) pool_.getServerSession(); local_session.addMessage(message); local_session.start(); */ activeMessage = message; ServerSession servSession = pool_.getServerSession (); JmsSession session = (JmsSession) servSession.getSession(); session.setConnectionConsumer (this); servSession.start(); } catch (Exception exception) { } } Message nextMessage () { Message msg = activeMessage; activeMessage = null; return (msg); } /** * Abstract mathod that returns the proxy to the server side session attached * to this object * * @return Session */ abstract JmsSession getSession(); /** * Return the maximum number of messages that can be loaded down any one * server session * * @return int */ int getMaxMessages() { return maxMessages_; } /** * This is a reference to the server session pool, which is used to deliver * messages to the actual processing client. */ private ServerSessionPool pool_ = null; /** * This attribute describes the maximum number of messages that can be * loaded on a server session at any one time. */ private int maxMessages_ = 1; } ---------------------------------------------------------------------- Comment By: Tim Anderson (tanderson) Date: 2003-10-28 11:51 Message: Logged In: YES user_id=557161 OpenJMS's support for MDB's is untested - if you have the time, any contribution with respect to this would be much appreciated. ---------------------------------------------------------------------- You can respond by visiting: https://sourceforge.net/tracker/?func=detail&atid=474136&aid=831469&group_id=54559 ------------------------------------------------------- The SF.Net email is sponsored by EclipseCon 2004 Premiere Conference on Open Tools Development and Integration See the breadth of Eclipse activity. February 3-5 in Anaheim, CA. http://www.eclipsecon.org/osdn