[ 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 00:26
Message generated for change (Comment added) made by bmjiang
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=474136&aid=831469&group_id=54559

Category: client
Group: v0.7.6-rc1
Status: Open
Resolution: None
Priority: 5
Submitted By: Bo Min Jiang (jiangb)
Assigned to: Jim Alateras (jalateras)
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: 2003-12-09 19: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 02: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-18 20: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 00: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


-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
Does SourceForge.net help you be more productive?  Does it
help you create better code?  SHARE THE LOVE, and help us help
YOU!  Click Here: http://sourceforge.net/donate/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.