InvalidMarshallingResource: Can not find a valid marshaller for data type: jms

Hi,

ich habe folgendes Problem :

Eine Applikation wird so umgebaut, dass sie im OSGi Kontext läuft. In der Applikation wird versucht eine JMS Connection aufzubauen.

Code:
ConnectionFactory factory = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
Connection connection = factory.createConnection(username, password);

Während der lookup funktioniert, wird beim createConnection eine Exception geworfen. Bis zur JBossConnectionFactory (org.jboss.jms.client) habe ich es debuggt. Für die Klassen org.jboss.jms.delegate.ConnectionFactoryDelegate, org.jboss.remoting.Client und org.jboss.remoting.MicroRemoteClientInvoker fehlen mir die Sourcen. Server- und Clientseitig verwenden wir die gleichen jars. Einen Versionskonflikt kann man damit ausschließen. Als Applikation funktioniert der connect.

Kann jemand mit der Exception etwas anfangen ? Mir würde es auch weiterhelfen, wenn jemand weiss wo ich die fehlenden Sourcen (org.jboss.remoting) downloaden kann.

Danke für jeden Tipp.


Code:
   protected JBossConnection createConnectionInternal(String username, String password, boolean isXA, int type)
      throws JMSException
   {
      try
      {
         ClientAOPStackLoader.getInstance().load(delegate);
      }
      catch(Exception e)
      {
         // Need to log message since no guarantee that client will log it
         final String msg = "Failed to download and/or install client side AOP stack";
         log.error(msg, e);
         throw new RuntimeException(msg, e);
      }

      // The version used by the connection is the minimum of the server version for the
      // connection factory and the client code version

      CreateConnectionResult res = delegate.createConnectionDelegate(username, password, -1);

      return new JBossConnection(res.getDelegate(), type);
   }

Beim delegate.createConnectionDelegate(username, password, -1); wird die Exception geworfen.

Code:
Caused by: org.jboss.jms.exception.MessagingJMSException: Failed to invoke
        at org.jboss.jms.client.delegate.DelegateSupport.handleThrowable(DelegateSupport.java:271)
        at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.org$jboss$jms$client$delegate$ClientConnectionFactoryDelegate$createConnectionDelegate$aop(ClientConnectionFactoryDelegate.java:187)
        at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.invokeNext(ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.java)
        at org.jboss.jms.client.container.StateCreationAspect.handleCreateConnectionDelegate(StateCreationAspect.java:83)
        at org.jboss.aop.advice.org.jboss.jms.client.container.StateCreationAspect0.invoke(StateCreationAspect0.java)
        at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.invokeNext(ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.java)
        at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.createConnectionDelegate(ClientConnectionFactoryDelegate.java)
        at org.jboss.jms.client.JBossConnectionFactory.createConnectionInternal(JBossConnectionFactory.java:205)
        at org.jboss.jms.client.JBossConnectionFactory.createConnection(JBossConnectionFactory.java:87)
        at ui.hosting.mgmtconsole.commonlib.ServiceBroker.getJMSConnection(ServiceBroker.java:109)
        ... 2 more
Caused by: java.lang.RuntimeException: Error setting up client lease upon performing connect.
        at org.jboss.remoting.Client.connect(Client.java:1529)
        at org.jboss.remoting.Client.connect(Client.java:462)
        at org.jboss.jms.client.remoting.JMSRemotingConnection$1.run(JMSRemotingConnection.java:319)
        at java.security.AccessController.doPrivileged(Native Method)
        at org.jboss.jms.client.remoting.JMSRemotingConnection.start(JMSRemotingConnection.java:315)
        at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.org$jboss$jms$client$delegate$ClientConnectionFactoryDelegate$createConnectionDelegate$aop(ClientConnectionFactoryDelegate.java:154)
        ... 10 more
Caused by: java.lang.Exception: Error setting up client lease
        at org.jboss.remoting.MicroRemoteClientInvoker.establishLease(MicroRemoteClientInvoker.java:430)
        at org.jboss.remoting.Client.setupClientLease(Client.java:1625)
        at org.jboss.remoting.Client.connect(Client.java:1525)
        ... 15 more
Caused by: org.jboss.remoting.marshal.InvalidMarshallingResource: Can not find a valid marshaller for data type: jms
        at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:79)
        at org.jboss.remoting.MicroRemoteClientInvoker.establishLease(MicroRemoteClientInvoker.java:398)
        ... 17 more
 
Ich habe die Ursache des Problems gefunden. Dieses Problem ist zwar sehr speziell, aber evtl. kommt jemand mal in die gleiche Situation.

Die eigentliche Ursache des Problems ist die, der OSGi Container verwendet für jedes zu ladende Bundle einen eigenen Classloader. Im Sinne der von OSGi angestrebten Modulkapselung ist das auch ok. Nur kollidiert das mit der Tatsache, dass die JBoss jars voneinander abhängig sind. Daraus resultiert, während die Applikation ohne OSGi funktioniert da es hier nur einen Classloader gibt, gibt es mit OSGi viele Probleme dieser Art. Leider sind die nur per Debugger zu finden da viele Stacktraces einfach gecatcht und weggeworfen werden.

Zum konkreten Fall :

Clientseitig wird beim Aufbau einer JMS Connection versucht den Marshaller mit dem Key "jms" zu laden. Dieser existiert jedoch nicht. Zur Verfügung stehen nur die Marshaller "serializable", "http" und "rmi". Deshalb wird auf die Infos des locator zurückgegriffen und versucht den Marshaller zur Laufzeit nachzuladen. Im locator ist der Marshaller "org.jboss.jms.wireformat.JMSWireFormat" angegeben.

Deshalb wird die Methode loadMarshaller(String FQN) der MarshalFactory.class mit dem Parameter "org.jboss.jms.wireformat.JMSWireFormat" aufgerufen.
(Einsprungspunkt : class org.jboss.jms.remote.MarshalFactory --> public static Marshaller getMarshaller(InvokerLocator locator, ClassLoader classLoader))

Code:
   private static Marshaller loadMarshaller(String marshallerFQN) {

....
         try
         {
            Class marshallerClass = Class.forName(marshallerFQN);
....

      return marshaller;
   }

Die class org.jboss.remoting.marshal.MarshalFactory befindet sich im jbossall-client.jar. Die gesuchte class "org.jboss.jms.wireformat.JMSWireFormat" befindet sich im jar jboss-messaging-client.jar. Beide jars befinden sich in getrennten Bundles. Deshalb wird eine ClassNotFoundException geworfen.

Sehr clever, die Message die OSGi extra an die Exception anhängt, wird per catch(Exception e) weggeworfen und ist somit nur per Debugger auffindbar. Der catch bewirkt, dass später nur noch "Can not find a valid marshaller for data type: jms" geloggt wird. Erschwerend kommt hinzu, dass die passenden Sourcen für org.jboss.remoting schwer zu bekommen sind.

Die Lösung des Problems :
Das Bundle das das jbossall-client.jar einbindet, muss zusätzlich 'org.jboss.jms.wireformat' importieren. Damit wären allerdings beide Bundles gegenseitig abhängig. Das widerspricht allerdings dem angestrebten Modulkonzept von OSGi. Dann kann man beide Bundles auch zusammenfassen. Unterm Strich hätte man dann ein großes JBoss-Bundle was auch nicht Sinn der Sache ist.

Fazit :
Je mehr man solche Abhängigkeitsprobleme in seiner Applikation vorfindet, um so genauer sollte man den Einsatz von OSGi hinterfragen. Aus meiner jetzigen Sicht, ich schlage mich mit dem Thema jetzt 6 Wochen herum, sehe ich keinen Mehrwert von OSGi. Wer auf das Feature des modularen Nachladens von Komponenten zur Laufzeit verzichten kann, sollte dies tun bzw. sich dieses selbst bauen. Damit spart man sich Nerven und graue Haare die der Einsatz von OSGi mit sich bringt.
 

Neue Beiträge

Zurück