1 2 Previous Next 19 Replies Latest reply on May 17, 2006 7:23 PM by daviddryparry Go to original post
      • 15. Re: JMS JDBC Persistence and server restart.
        mormota

         

        "adrian@jboss.org" wrote:
        FAQ: http://www.jboss.org/wiki/Wiki.jsp?page=WhatIsTheCorrectWayToMakeADurableSubscription

        Preconfigured clients ids (for the testsuite) from deploy/jms/hsqldb-jdbc-state-service.xml:
         POPULATE.TABLES.03 = INSERT INTO JMS_USERS (USERID, PASSWD, CLIENTID) VALUES ('john', 'needle', 'DurableSubscriberExample')
        





        I seems to me that we could solve the problem. We have modified our code and hacked the jms-ra.rar as well.

        Regarding our code, we added the following to the message producer:
        connection.setClientID("10001");


        So, we do the following in the producer:
        connection = connectionFactory.createTopicConnection("guest","guest"); // previously we used createTopicConnection(void)
        connection.start();
        connection.setClientID("10001"); // new line
        session = connection.createTopicSession(true, 0);
         session.createDurableSubscriber((Topic)topic,"MySubscriptionName"); // new line
        publisher = session.createProducer(topic);
        publisher.setDeliveryMode(DeliveryMode.PERSISTENT);
        


        However, when we tried to set the client identifier, JBoss thrown IllegalStateException claiming that "This method is not applicatable in JMS resource adapter".

        Thereafter, we looked into the source code of method JmsSessionFactoryImpl.setClientID(String), which actually throws the exception. Here it is:
        public void setClientID(String cID)
         throws JMSException
         {
         if(mcf.isStrict())
         throw new IllegalStateException("This method is not applicatable in JMS resource adapter");
         checkClosed();
         if(clientID != null)
         {
         throw new IllegalStateException("Cannot change client id");
         } else
         {
         clientID = cID;
         return;
         }
         }
        


        Okay, we realized that the corresponding ManagedConnectionFactory (mcf) has to be strict. Unfortunately, according to the JMX console the mcf is obviously strict.

        After some research on the web, we learnt that we can configure this attribute in ra.xml located in jms-ra.rar.

        Well, this finding was followed by some minimal hacking, which resulted in the following modified ra.xml:
        <?xml version="1.0" encoding="UTF-8"?>
        
        <!-- $Id: ra.xml,v 1.12 2004/08/11 21:05:49 ejort Exp $ -->
        
        <connector xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
         http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd"
         version="1.5">
        
         <description>JBoss JMS Resource Adapter</description>
         <display-name>JMS Adapter</display-name>
        
         <vendor-name>JBoss, Inc</vendor-name>
         <eis-type>JMS 1.1 Server</eis-type>
         <resourceadapter-version>4.0</resourceadapter-version>
        
         <license>
         <description>
         COPYRIGHT AND PERMISSION NOTICE
         Copyright (c) 2004 JBoss, Inc
         This is released under the terms of the LGPL.
         See gnu.org for details.
         </description>
         <license-required>true</license-required>
         </license>
        
         <resourceadapter>
         <resourceadapter-class>org.jboss.resource.adapter.jms.JmsResourceAdapter</resourceadapter-class>
        
         <outbound-resourceadapter>
         <connection-definition>
         <managedconnectionfactory-class>org.jboss.resource.adapter.jms.JmsManagedConnectionFactory</managedconnectionfactory-class>
         <config-property>
         <description>The jndi name of the provider of connection factories</description>
         <config-property-name>JmsProviderAdapterJNDI</config-property-name>
         <config-property-type>java.lang.String</config-property-type>
         <config-property-value>java:DefaultJMSProvider</config-property-value>
         </config-property>
         <config-property>
         <description>The default session type</description>
         <config-property-name>SessionDefaultType</config-property-name>
         <config-property-type>java.lang.String</config-property-type>
         <config-property-value>javax.jms.Topic</config-property-value>
         </config-property>
         <config-property>
         <description>The user name used to login to the jms server</description>
         <config-property-name>UserName</config-property-name>
         <config-property-type>java.lang.String</config-property-type>
         <config-property-value></config-property-value>
         </config-property>
         <config-property>
         <description>The password used to login to the jms server</description>
         <config-property-name>Password</config-property-name>
         <config-property-type>java.lang.String</config-property-type>
         <config-property-value></config-property-value>
         </config-property>
         <config-property>
         <description>The client id for this connection factory</description>
         <config-property-name>ClientID</config-property-name>
         <config-property-type>java.lang.String</config-property-type>
         <config-property-value></config-property-value>
         </config-property>
         <config-property>
         <config-property-name>Strict</config-property-name>
         <config-property-type>java.lang.Boolean</config-property-type>
         <config-property-value>false</config-property-value> <!-- by default was true -->
         </config-property>
         <connectionfactory-interface>org.jboss.resource.adapter.jms.JmsConnectionFactory</connectionfactory-interface>
         <connectionfactory-impl-class>org.jboss.resource.adapter.jms.JmsConnectionFactoryImpl</connectionfactory-impl-class>
         <connection-interface>javax.jms.Session</connection-interface>
         <connection-impl-class>org.jboss.resource.adapter.jms.JmsSession</connection-impl-class>
         </connection-definition>
         <transaction-support>XATransaction</transaction-support>
         <authentication-mechanism>
         <authentication-mechanism-type>BasicPassword</authentication-mechanism-type>
         <credential-interface>javax.resource.spi.security.PasswordCredential</credential-interface>
         </authentication-mechanism>
         <reauthentication-support>false</reauthentication-support>
         </outbound-resourceadapter>
        
         <inbound-resourceadapter>
         <messageadapter>
         <messagelistener>
         <messagelistener-type>javax.jms.MessageListener</messagelistener-type>
         <activationspec>
         <activationspec-class>org.jboss.resource.adapter.jms.inflow.JmsActivationSpec</activationspec-class>
         <required-config-property>
         <config-property-name>destination</config-property-name>
         </required-config-property>
         <required-config-property>
         <config-property-name>destinationType</config-property-name>
         </required-config-property>
         </activationspec>
         </messagelistener>
         </messageadapter>
         </inbound-resourceadapter>
        
         </resourceadapter>
        </connector>
        [\code]
        
        This modification added an extra durable subscriber to the topic, and made the topic durable (txop values are 'A'). So, now we have two subscribers, the new one is durable, and our MDB is (against all of our efforts) is non-durable.
        
        The problem is, that this is obviously a hacked workaround and not a real solution, and we do not release a "patched" jms-ra.rar (JBoss 4.0.1) along with our product(s).
        
        What is your opinion about this "solution"?
        
        Do you have an idea how can we make our MDB durable?
        


        • 16. Re: JMS JDBC Persistence and server restart.

          You don't need to modify the ra.xml

          You modify jms-ds.xml (or whatever you are using)

           <config-property name="ClientID" type="java.lang.String">10001</config-property>
          


          Setting strict to false means you have unportable code (won't work in other appservers).
          Strict == false is for use outside a J2EE application server.

          • 17. Re: JMS JDBC Persistence and server restart.

            Thanks for your test case, the answer is trivial.

            I cannot spell.

            The problem is in JMSContainerInvoker

            - activationConfig = getActivationConfigProperty("subscriptionDurablity");
            + activationConfig = getActivationConfigProperty("subscriptionDurability");
            


            You can workaround the problem using the old fashioned configuration in ejb-jar.xml
             <subscription-durability>Durable</subscription-durability>
            




            • 18. Re: JMS JDBC Persistence and server restart.
              frank-15

              Dear Forum Readers and Adrian!

              If you followed this thread thoughtfully perhaps you have conclusions similar to mine - as follows:

              The Professional Open Source Company (henceforth referenced as JBOSS) did not provide any official and detailed descriptions or how-to's about durable descriptions and topics or making messages persistent. There are lot of sources available on the web however most of them are outdated and/or contradicting each other - especially for newbies, like us. We continously failed to persist or messages under 4.0.1 AS so as a last resort we tried to get some help from the official JBOSS forum.

              Although my posts did not have any allusions that this was a Jboss bug (which it actually turned out to be) I was rewarded with a uniquely hostile behaviour from Adrian:

              The stuff you have posted does not show anything. It is just some xml out of context.
              ...
              All I have seen so far in this post in lots of assertions with the usual
              "IT DOES NOT WORK". So show me what it IS doing.
              . So this was the point where my project leader (henceforth referenced as mormota) came into the picture. He tried to shepherd to flow of this conversation into a constructive tunnel. (It's very funny how this good-cop, bad-coop scenario works and what a scientific degree could mean...)

              As time passed our developer team succesfully provided an unambigous evidence that there is a bug in the JMS handling of JBOSS and a bug report has been posted (http://jira.jboss.com/jira/browse/JBAS-1351?page=comments#action_12315048) , which was rejected firstly, however Adrian in his last post admitted that right now the 4.0.1 version is incapable of providing topic management corresponding to the EJB 2.1 recommendation. Actually that part of code could have never worked.

              We are working for a large telecommunication company. We, like most informatical projects have limited time and developer resources. Still it was our task to provide a detailed test-case so that JBOSS finally could accept that it is not our defect or laziness that causes the problem. Adrian, please help me! Help me to explain my costumer that JBOSS AS is the definite open source target platform that could be recommended because the thorough testing and open support! Help me to make them understand that JBOSS is not a bad and risky choice!

              I'will be here, waiting for your answer.

              Regards: Frank-15

              • 19. Re: JMS JDBC Persistence and server restart.

                Interesting so are you saying if you have a Topic in jboss i.e. topic/testTopic that a MessageDrivenBean implements MessageDrivenBean, MessageListener. Will not be activated. Big question is will it work in jboss 4.0.1?

                I have been banging my head why my MessageDrivenBean onMessage() method is never called. I publish to the topic/testTopic but the Bean is never called.

                First i publish with this:
                Topic topic = (Topic)initialContext.lookup(MessageSubscriberBean.TOPIC_JNDI_NAME);
                TopicConnection connection = null;
                TopicSession session = null;
                TopicPublisher publisher = null;
                try {
                connection = openTopicConnection();
                session = connection.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
                publisher = session.createPublisher(topic);
                MessageCreator creator = new ObjectMessageCreator(message);
                publisher.publish(creator.getMessage(session), Message.DEFAULT_DELIVERY_MODE,priority,Message.DEFAULT_TIME_TO_LIVE);

                } catch(JMSException e) {
                throw new KVException(e);
                } finally {
                closeTopicPublisher(publisher);
                closeSession(session);
                closeConnection(connection);
                }

                Then the MDB config is here with a basic bean:

                <message-driven >
                [CDATA[]]
                <display-name>Test Topic Bean</display-name>

                <ejb-name>TestTopic</ejb-name>

                <ejb-class>com.message.MessageSubscriberBean</ejb-class>

                <transaction-type>Container</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>

                </message-driven>


                1 2 Previous Next