mercredi 3 juin 2015

loading Glassfish JMS jars dynamically at runtime throws a NoClassDefFoundError javax/jms/Destination

I'm desperate for any help on this issue as i'm stuck for a while now.

Part of my application using Glassfish JMS to transfer messages, the application works smoothly om my development machine if the jars are included, now i have the need to load the JMS jars dynamically on runtime, so i used the following code to load the jars in the classloader at runtime

public class ClassPathHack {
    private static final Class<?>[] parameters = new Class[]{URL.class};
    public static synchronized void addFile(String s) throws IOException, Exception {
        File f = new File(s);
        try {
            java.net.URLClassLoader loader = (java.net.URLClassLoader)ClassLoader.getSystemClassLoader();
            java.net.URL url = f.toURI().toURL();
            for (java.net.URL it : java.util.Arrays.asList(loader.getURLs())){
                if (it.equals(url)){
                    return;
                }
            }
            java.lang.reflect.Method method = java.net.URLClassLoader.class.getDeclaredMethod("addURL", new Class[]{java.net.URL.class});
            method.setAccessible(true); 
            method.invoke(loader, new Object[]{url});
        } catch (final java.lang.NoSuchMethodException | 
            java.lang.IllegalAccessException | 
            java.net.MalformedURLException | 
            java.lang.reflect.InvocationTargetException e){
            throw new Exception(e);
        }
    }
}

and in the main method i've loaded all the JMS used jars before raising the thread that connect to JMS using the following code:

public static void loadGlassfishJars(){
    try {
        System.out.println("DEBUGGNG: Loading Glassfish jars");
        ClassPathHack.addFile(glassfishPath + "\\glassfish\\lib\\appserv-rt.jar");
        ClassPathHack.addFile(glassfishPath + "\\glassfish\\modules\\console-jms-plugin.jar");
        ClassPathHack.addFile(glassfishPath + "\\glassfish\\lib\\gf-client.jar");
        ClassPathHack.addFile(glassfishPath + "\\mq\\lib\\imq.jar");
        ClassPathHack.addFile(glassfishPath + "\\mq\\lib\\imqbroker.jar");            
        ClassPathHack.addFile(glassfishPath + "\\glassfish\\lib\\install\\applications\\jmsra\\imqjmsra.jar");
        ClassPathHack.addFile(glassfishPath + "\\glassfish\\lib\\javaee.jar");
        ClassPathHack.addFile(glassfishPath + "\\glassfish\\modules\\jms-admin.jar");
        ClassPathHack.addFile(glassfishPath + "\\glassfish\\modules\\jms-core.jar");
        ClassPathHack.addFile(glassfishPath + "\\mq\\lib\\jms.jar");
        ClassPathHack.addFile(glassfishPath + "\\glassfish\\modules\\jmxremote_optional-repackaged.jar");
    } catch (Exception ex) {
        Logger.getLogger(ZMQTranslator.class.getName()).log(Level.SEVERE, null, ex);
    }

and the main method is something like the following:

     public static void main(String[] args) {

        //loading glassfish jms jars

        loadGlassfishJars();

        //JMS connector thread
        System.out.println("DEBUGGNG:initiating ZMQConnectionReceiver");
        ZMQConnectionReceiver zmqCon = new ZMQConnectionReceiver();
        Thread t = new Thread(zmqCon);
        t.start();
}

the exception is thrown while calling the constructor of ZMQConnectionReceiver class, which imports the following classes

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
//NOT RELATED IMPORTS
import java.io.FileInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.Properties;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.json.Json;
import model.DeviceConnection;
import org.zeromq.ZMQ;
import javax.json.stream.*;

and it has a simple constructor as follows:

 public ZMQConnectionReceiver(){
            lostNFound = new ConcurrentLinkedDeque();
    }

The exception is thrown when calling the constructor

Exception in thread "main" java.lang.NoClassDefFoundError: javax/jms/Destination

I've checked the existence of Destination Class in jms.jar and it's there.

Note. Glassfish JMS have a weird behavior that it require that the application connecting to it should have the JARs installed with the same Glassfish version you are trying to connect to, any other jars will fail even if it was from the same Glassfish version but other installation.

How can I solve this issue?





Aucun commentaire:

Enregistrer un commentaire