在Tomcat上的java:comp / env之外查找JNDI名称?

时间:2019-07-19 04:41:11

标签: java tomcat jndi

我正在使用最初为IBM WebSphere设计的应用程序,但我也希望将其托管在Tomcat上。该应用程序无法更改,并且正在运行new InitialContext().lookup("servername"),可在WebSphere上运行。

但是在Tomcat上,当我在应用程序特定的上下文xml中指定<Environment>名称时,它们以java:comp/env为前缀,而上述查找找不到这些名称。

它将在容器中运行,因此,如果有必要,当然还有应用程序特定的上下文xml,则更新server.xml没问题。

如何让Tomcat在lookup("servername")上返回字符串?

3 个答案:

答案 0 :(得分:0)

看起来Tomcat进行了硬编码,以这种方式工作。

但是不必那样做。加入Tomcat user's mailing list并询问是否有某种特定的原因来说明事物的现状。如果没有特殊原因将环境条目限制为java:comp/env名称空间,那么我怀疑可以进行代码更改(可能涉及新的配置选项)。

答案 1 :(得分:0)

作为一个hack,我创建了这个InitialContextFactory,它只是将对字符串名称的查找委托给System.getenv()(环境变量)。这是非常不安全的,会破坏正确使用命名的应用程序,因此我不建议在生产环境或特定用例之外使用此功能。或真的给任何人。

尽管如此,通过使用此命令,我能够在命令行上通过(String) new InitialContext().lookup("servername")返回blah来返回特定值set servername=blah

import java.util.Hashtable;

import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;

public class EnvironmentInitialContextFactory implements InitialContextFactory {


    public Context getInitialContext(Hashtable<?,?> environment) throws NamingException {

        return new Context() {

            public Object lookup(String name) throws NamingException {

                return System.getenv(name);

            }

            public Object lookup(Name name) throws NamingException { return null; }
            public void bind(Name name, Object obj) throws NamingException {}
            public void bind(String name, Object obj) throws NamingException {}
            public void rebind(Name name, Object obj) throws NamingException {}
            public void rebind(String name, Object obj) throws NamingException {}
            public void unbind(Name name) throws NamingException {}
            public void unbind(String name) throws NamingException {}
            public void rename(Name oldName, Name newName) throws NamingException {}
            public void rename(String oldName, String newName) throws NamingException {}
            public NamingEnumeration<NameClassPair> list(Name name) throws NamingException { return null; }
            public NamingEnumeration<NameClassPair> list(String name) throws NamingException { return null; }
            public NamingEnumeration<Binding> listBindings(Name name) throws NamingException { return null; }
            public NamingEnumeration<Binding> listBindings(String name) throws NamingException { return null; }
            public void destroySubcontext(Name name) throws NamingException {}
            public void destroySubcontext(String name) throws NamingException {}
            public Context createSubcontext(Name name) throws NamingException { return null; }            
            public Context createSubcontext(String name) throws NamingException { return null; }
            public Object lookupLink(Name name) throws NamingException { return null; }
            public Object lookupLink(String name) throws NamingException { return null; }
            public NameParser getNameParser(Name name) throws NamingException { return null; }
            public NameParser getNameParser(String name) throws NamingException { return null; }
            public Name composeName(Name name, Name prefix) throws NamingException { return null; }
            public String composeName(String name, String prefix) throws NamingException { return null; }
            public Object addToEnvironment(String propName, Object propVal) throws NamingException { return null; }
            public Object removeFromEnvironment(String propName) throws NamingException { return null; }
            public Hashtable<?, ?> getEnvironment() throws NamingException { return null; }
            public void close() throws NamingException {}
            public String getNameInNamespace() throws NamingException { return null; }

        };

    }

}

编译类,并通过将以下行添加到setenv.bat(在%CATALINA_HOME%/bin/中创建)将其添加到CLASSPATH和系统属性中:

set CLASSPATH=C:\path\to\compiled\class
set CATALINA_OPTS=-Djava.naming.factory.initial=EnvironmentInitialContextFactory

答案 2 :(得分:0)

我正在重新研究这个问题(我是问问者)。受this answer的启发,我决定改为实施ServletContextListener

总而言之,您不能使Tomcat将环境资源放在java:comp/env/之外,但是您可以从那里读取它们并在“任何地方”重新分配它们。

初始化ServletContext时,我的侦听器将它们重新绑定:

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        Context ctx = new InitialContext();
        ctx.bind("servername", ctx.lookup("java:comp/env/servername"));
    }

这是一个更好的解决方案-它不会摆弄部署上下文之外的任何内容。

也有可能只是重新绑定comp/env/名称空间中的所有名称,以创建更通用的侦听器。目前,我只是绑定单个名称,因为该应用程序使用的名称很少。