Search code examples
javajndisolace

Why InitialContext throws naming exception when call getEnvironment()?


The exception stack trace does not give much information, just

javax.naming.OperationNoSupportedException

public static Connection getConnection(Context ctx, String factoryName) throws JMSException, NamingException {
    Object objfac = null;
    try {
        objfac = ctx.lookup(factoryName);
    } catch (NoClassDefFoundError e) {
        throw new NamingException("Lookup failed: "+e.toString());
    }
    if (objfac instanceof javax.jms.ConnectionFactory) {
        @SuppressWarnings("unchecked") // The environment is supposed to use String keys only
        Map<String, Object> env = (Map<String, Object>)ctx.getEnvironment();
        if(env.containsKey(Context.SECURITY_PRINCIPAL)) {
            String username = (String)env.get(Context.SECURITY_PRINCIPAL);
            String password = (String)env.get(Context.SECURITY_CREDENTIALS);
            return ((javax.jms.ConnectionFactory) objfac).createConnection(username, password);                
        }
        else {
            return ((javax.jms.ConnectionFactory) objfac).createConnection();
        }
    }
    throw new NamingException("Expected javax.jms.ConnectionFactory, found "+(objfac != null ? objfac.getClass().getName(): "null"));
}

The stacktrace is:

javax.naming.OperationNotSupportedException at com.solacesystems.jndi.SolJNDIInitialContextFactory$SolJNDIInitialContextImpl.getEnvironment(SolJNDIInitialContextFactory.java:230) at javax.naming.InitialContext.getEnvironment(InitialContext.java:544) at javax.naming.InitialContext.getEnvironment(InitialContext.java:544) at org.apache.jmeter.protocol.jms.Utils.getConnection(Utils.java:155) at org.apache.jmeter.protocol.jms.client.Publisher.(Publisher.java:130) at org.apache.jmeter.protocol.jms.sampler.PublisherSampler.initClient(PublisherSampler.java:135) at org.apache.jmeter.protocol.jms.sampler.PublisherSampler.sample(PublisherSampler.java:154) at org.apache.jmeter.protocol.jms.sampler.BaseJMSSampler.sample(BaseJMSSampler.java:80) at org.apache.jmeter.threads.JMeterThread.process_sampler(JMeterThread.java:429) at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:257) at java.lang.Thread.run(Thread.java:722)


Solution

  • The JNDI implementation you are using does not support the getEnvironment method, which means that any credentials for accessing the JMS server cannot be accessed by that code. Here is my attempt at a fix (it's possible that this will only work in your case if no credentials are needed, I'm not sure):

    if (objfac instanceof javax.jms.ConnectionFactory) {
        @SuppressWarnings("unchecked") // The environment is supposed to use String keys only
        Map<String, Object> env = null;
        try {
           env = (Map<String, Object>)ctx.getEnvironment();
        } catch (javax.naming.OperationNotSupportedException ex) {}
        if(env != null && env.containsKey(Context.SECURITY_PRINCIPAL)) {
            String username = (String)env.get(Context.SECURITY_PRINCIPAL);
            String password = (String)env.get(Context.SECURITY_CREDENTIALS);
            return ((javax.jms.ConnectionFactory) objfac).createConnection(username, password);                
        }
        else {
            return ((javax.jms.ConnectionFactory) objfac).createConnection();
        }
    }