5 Replies Latest reply on Oct 6, 2009 10:26 AM by belcar

    Nullpointer while creating a remote JMS Session

    belcar

      Hi all

      My JMS client application running on JBoss 4.2.3 fails to create a remote JMS Session on startup due to a NullpointerException. The JMS server is JBM 1.4.4 on JBoss AS 4.2.3. Threads mentioned below already discuss the issue, but even when trying to change the scoping/loader the issue remains.

      13:37:18,980 INFO [StartupListener] ~~ Creating JMS Session ...
      13:37:18,989 FATAL [StartupListener]
      java.lang.NullPointerException
       at org.jboss.jms.client.container.FailoverValveInterceptor.invoke(FailoverValveInterceptor.j
      ava:87)
       at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:105)
       at org.jboss.jms.client.delegate.ClientConnectionDelegate$createSessionDelegate_605233526772
      4906805.invokeNext(ClientConnectionDelegate$createSessionDelegate_6052335267724906805.java)
       at org.jboss.jms.client.container.ClosedInterceptor.invoke(ClosedInterceptor.java:170)
       at org.jboss.aop.advice.PerInstanceInterceptor.invoke(PerInstanceInterceptor.java:105)
       at org.jboss.jms.client.delegate.ClientConnectionDelegate$createSessionDelegate_605233526772
      4906805.invokeNext(ClientConnectionDelegate$createSessionDelegate_6052335267724906805.java)
       at org.jboss.jms.client.delegate.ClientConnectionDelegate.createSessionDelegate(ClientConnec
      tionDelegate.java)
       at org.jboss.jms.client.JBossConnection.createSessionInternal(JBossConnection.java:269)
       at org.jboss.jms.client.JBossConnection.createSession(JBossConnection.java:91)


      This standalone WAR file connects to the JBM server from the ServletContextListener.contextInitialized() callback method to poll for messages. The code was tested on windows platform(on 1 machine) but now fails during linux deployments where both servers are remote.

      http://www.jboss.org/index.html?module=bb&op=viewtopic&t=110051&postdays=0&postorder=asc&start=0
      https://jira.jboss.org/jira/browse/JBMESSAGING-980
      http://www.jboss.org/community/wiki/ClassLoadingconfiguration

      On the client server I removed the server/default/deploy/jms folder to remove JBossMQ. In the WEB-INF/lib of my WAR I've provided jboss-remoting.jar (v2.2.3) and jboss-messaging-client.jar (v1.4.4).

      Here is my Spring configuration:
      <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
       <property name="environment">
       <props>
       <prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
       <prop key="java.naming.provider.url">jnp://someIP:1099</prop>
       <prop key="java.naming.factory.url.pkgs">org.jboss.naming:org.jnp.interfaces</prop>
       </props>
       </property>
       </bean>
      
       <bean id="threadPoolSize" class="java.lang.Integer">
       <constructor-arg value="${threadPoolSize}"/>
       </bean>
      
       <bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
       <property name="jndiTemplate"><ref bean="jndiTemplate" /></property>
       <property name="jndiName" value="/ConnectionFactory"/>
       </bean>
      
       <bean id="requestQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
       <property name="jndiTemplate"><ref bean="jndiTemplate" /></property>
       <property name="jndiName" value="${queue}"/>
       </bean>


      and here is the code that initializes the connection:

      public class StartupListener implements ServletContextListener {
       private static final Log log = LogFactory.getLog(StartupListener.class);
       private static Connection connection;
       private static Session session;
       private static MessageConsumer consumer;
       private static Boolean run = Boolean.TRUE;
       private static ExecutorService pool;
       private static Thread daemonThread;
       private static final String PREFIX = " ~~ ";
       private static MeteoService metService;
      
       /**
       * Startup trigger of the application.
       */
       public void contextInitialized(ServletContextEvent ctx) {
       log.info("==== Initializing ServiceBroker");
      
       logInfo("Creating polling thread ...");
       daemonThread = new Thread(new MessageDispatcher());
      
       try {
       ApplicationContext _ctx = WebApplicationContextUtils.getWebApplicationContext(ctx.getServletConte
      xt());
       initializeWorkerThreadPool(_ctx);
       initializeJMSEnvironment(_ctx);
      
       metService = (MeteoService) _ctx.getBean("metService");
      
       logInfo("Starting the Session ...");
       connection.start();
      
       logInfo("Starting a Daemon Thread responsible for message dispatching ...");
       daemonThread.start();
      
       log.info("==== ServiceBroker initialized successfully");
       } catch (Throwable e) {
       log.fatal(e.getMessage(), e);
       }
       }
      
       /**
       * This is a context lifecycle (callback) method.
       * The Servlet Context is being destroyed by the Container due to a shutdown.
       * As a result we need to clean up our privately managed resources.
       */
       public void contextDestroyed(ServletContextEvent ctx) {
       synchronized (run) {
       log.info("==== Shutting down PilotBriefing ServiceBroker ...");
       run = Boolean.FALSE;
      
       logInfo("Interrupting polling thread ...");
       daemonThread.interrupt();
      
       if (session != null) {
       try {
       logInfo("Closing JMS Session ...");
       session.close();
       } catch (JMSException e) {
       log.error(e.getMessage(), e);
       }
       }
      
       if (connection != null) {
       try {
       logInfo("Closing JMS Connection ...");
       connection.close();
       } catch (JMSException e) {
       log.error(e.getMessage(), e);
       }
       }
      
       if (pool != null) {
       logInfo("Shutting down ThreadPool");
       pool.shutdownNow();
       }
      
       log.info("==== ServiceBroker shutdown complete");
       }
       }
      
       private void logInfo(String msg) {
       log.info(PREFIX + msg);
       }
      
       /**
       * Initialization of JMS environment.
       * @param _ctx external configuration parameters
       * @throws NamingException
       * @throws JMSException
       */
       private void initializeJMSEnvironment(ApplicationContext _ctx) throws NamingException, JMSException
       {
       Queue queue = (Queue) _ctx.getBean("requestQueue");
      
       logInfo("Lookup of ConnectionFactory ...");
       ConnectionFactory cf = (ConnectionFactory) _ctx.getBean("jmsConnectionFactory");
      
       logInfo("Creating JMS Connection ...");
       connection = cf.createConnection();
      
       logInfo("Creating JMS Session ...");
       session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      
       logInfo("Creating MessagConsumer ...");
       consumer = session.createConsumer(queue);
       }
      
       /**
       * Setup a pool of worker threads for message handling.
       * @param _ctx external configuration parameters
       */
       private void initializeWorkerThreadPool(ApplicationContext _ctx) {
       int poolSize = (Integer) _ctx.getBean("threadPoolSize");
       logInfo("Initializing Thread Pool [#" + poolSize + "] ...");
       pool = Executors.newFixedThreadPool(poolSize);
       }
      
       /**
       * Daemon thread for the dispatching of incoming messages to a pooled Worker Thread that will handl
      e the request.
       * This class is implemented as a Thread because otherwise the Servlet Container Thread that execut
      es this listener class,
       * fails to complete as a result of the polling-loop.
       */
       class MessageDispatcher implements Runnable {
       public void run() {
       try {
       while (run) {
       TextMessage message = (TextMessage) consumer.receive();
       if (message != null) {
       JMSUtils.printMessage("Received request", message);
       pool.execute(createMessageHandler(message));
       }
       }
       } catch (Throwable t) {
       log.error(t.getMessage(), t);
       }
       }
      
       /**
       * Factory method.
       * @param message
       * @return
       * @throws JMSException
       */
       private Runnable createMessageHandler(TextMessage message) throws JMSException {
       return new MessageHandler(metService, session, message.getJMSReplyTo(), message.getJMSMessageID()
      , message.getText());
       }
       }


      I've searched and tried every possible thing but I cannot get past this issue. Any help is much appreciated.

        • 1. Re: Nullpointer while creating a remote JMS Session
          belcar

          I've managed to reproduce this error on a windows environment, but only when the 2 JBoss processes are remote.
          Since you need to patch JBoss Remoting to get JBM working I guess my issue might be related to just that!
          As a result, I wonder how and where I need to provide this patch. Currently I've added the jboss-remoting (2.2.3) to the WEB-INF/lib but that doesn't seem to work.

          Can somebody please provide more details about this?

          • 2. Re: Nullpointer while creating a remote JMS Session
            belcar

            FYI: The update to JBM 1.4.5 had no effect.

            • 3. Re: Nullpointer while creating a remote JMS Session
              belcar

              I finally found the solution for my problem. I had to put the javassist.jar and jboss-aop-jdk50.jar in my WEB-INF/lib folder to make it work.

              This was a lot of trial and error going on here, so I would be delighted if somebody could explain why this happened to be the (a) solution. Also why is this not documented, because I use the refdocs on a clean JBoss AS.
              Just to understand what's going on.

              Thanks in advance.

              • 4. Re: Nullpointer while creating a remote JMS Session
                timfox

                IIRC, the user manual chapter 4 explains exactly what jars you need on the classpath, and in what order.

                • 5. Re: Nullpointer while creating a remote JMS Session
                  belcar

                  Indeed, but it only mentions non-JBoss clients.

                  It reads:
                  "In order to access JBoss Messaging from a client outside the JBoss app server, you will need to ensure the following jar files are on the client classpath"

                  Since I was deploying on JBoss I expected everything was already on the classpath. As result, I guess my issue was caused by classloading scoping?

                  Thank you