Ralph Schaer - 2003-05-05

I try to embed the ubermq server into a java program.
I use the latest CVS version. Here my experiences:

1. The documentation mention a start() method of the Message Server.
   But there is no start() method.
  
2. Next try was to start the server with run().
      MessageServer server = new MessageServer(props);     
      server.run();
      server.stop();
  
   But with that a NullPointerException occurs:
   java.lang.NullPointerException
     at com.ubermq.jms.server.MessageServer.exec(MessageServer.java:205)
    
3. I figured out that the program has to call the addStandardProtocols() method.
      MessageServer server = new MessageServer(props); 
      server.addStandardProtocols();   
      server.run();
      server.stop();    

   Now the stop() method throws a NullPointerException
   java.lang.NullPointerException
      at com.ubermq.jms.server.ssl.SSLProtocol.stop(SSLProtocol.java:130)
     
     The problem is that in my server.properties ssl support is disabled (server.ssl.enable=false)
     and the stop() method in SSLProtocol.java does not check if the acceptThread is
     not null. Here my fix:
    
    public void stop()
    {  
        if (acceptThread != null) {
          acceptThread.interrupt();
        }
    }    
   
4. Now the server starts and stops without any problem. But after stop() the VM is still running.
   The reason is that there are some threads that are not stopped and still alive.
  
   Acceptor
   DuableSubscription Periodic Tasks
   RMI Threads from the AdminProtocoll.
  
  
   To fix that I made some changes to various classes:
  
   Add shutdown() method to AcceptThread.java  
   public void shutdown() throws IOException {
        interrupt();
      connectSelector.close();
    }
   
   
   Change the "DuableSubscription Periodic Task" thread to daemon (DurableSubscriptionProxy.java)
      Thread t = new Thread(p0, "DurableSubscription Periodic Tasks");
      t.setDaemon(true);
      return t;  
  
  
   MessageServer.java
  
   Implement the stop() method from DefaultProtocol class
        public void stop()
        {
            try {
              acceptThread.shutdown();
            } catch (IOException ioe) {
              ioe.printStackTrace();
            }
        }  
  
   Implement the stop() method from AdminProtocol class
  
        public void stop()
        { try {
            registry.unbind(ADMIN_SERVICE_NAME);
            admin.close();
                     
          } catch (java.rmi.RemoteException re) {
            re.printStackTrace();
          }    catch (java.rmi.NotBoundException nb) {
            nb.printStackTrace();
          }
        }

  
  
   The VM is now exiting after the MessageServer.stop() method. (It takes about 30 - 60 seconds on my machine.
   I guess this has something todo with RMI)
  
  
5. The MessageServer.addStandardProtocols() registers three protocols (DefaultProtocol, AdminProtocol, SSLProtocol)
   It would be nice if there is a mechanism to turn off Protocols that are not needed. (saves resources)      

   My quick and dirty fix is to change the visiblity of getDatagramFactory() to protected.
   protected IDatagramFactory getDatagramFactory()
  
   Now this code is possible
  
      MessageServer server = new MessageServer(props){
        public void addStandardProtocols()
        {
          add(new DefaultProtocol(getDatagramFactory(),
                                  DefaultProtocol.getProtocolPort()));
          //add(new AdminProtocol());
          //add(new SSLProtocol(getDatagramFactory(),
          //                    this,
          //                    SSLProtocol.getProtocolPort()));
           
        }
      };
      server.addStandardProtocols();

      server.run();   
      server.stop();  
  
  
  
   The VM is now stopping immediatly .