[英]Lookup JNDI names outside of java:comp/env on Tomcat?
I am working with an application originally designed for IBM WebSphere, but I want to also host it on Tomcat. 我正在使用最初为IBM WebSphere设计的应用程序,但我也希望将其托管在Tomcat上。 The application cannot be changed, and is doing a
new InitialContext().lookup("servername")
, which works on WebSphere. 该应用程序无法更改,并且正在执行一个
new InitialContext().lookup("servername")
,它可以在WebSphere上运行。
But on Tomcat, when I specify <Environment>
names in the application specific context xml they are prefixed with java:comp/env
, and the names aren't found by the above lookup. 但是在Tomcat上,当我在特定于应用程序的上下文xml中指定
<Environment>
名称时,它们以java:comp/env
为前缀,并且上述查找找不到这些名称。
It will run in a container, so there's no problem to update server.xml
if I have to, and of course, the application specific context xml. 它将在容器中运行,因此,如果需要,并且当然是针对应用程序的特定上下文xml,则更新
server.xml
也没有问题。
How can I get Tomcat to return a string on lookup("servername")
? 如何获得Tomcat在
lookup("servername")
上返回字符串?
It looks like Tomcat is hard-coded to behave in this way. 看起来Tomcat已硬编码为以这种方式运行。
But it doesn't have to stay that way. 但这并不一定要坚持下去。 Join the Tomcat user's mailing list and ask if there is a particular reason why things are the way they are.
加入Tomcat用户的邮件列表 ,询问是否有某种特定的原因。 If there are no specific reasons to limit environment entries to the
java:comp/env
namespace, then I suspect a code change (probably involving a new configuration option) is definitely possible. 如果没有特殊原因将环境条目限制为
java:comp/env
命名空间,那么我怀疑代码更改(可能涉及新的配置选项)肯定是可能的。
As a hack, I created this InitialContextFactory, which simply delegates the looking up of String names to System.getenv()
(Environment variables). 作为一种技巧,我创建了这个InitialContextFactory,它只是将对String名称的查找委托给
System.getenv()
(环境变量)。 This is very insecure, and will break apps which use naming properly, so I wouldn't recommend this for Production or outside of specific use cases. 这是非常不安全的,会破坏正确使用命名的应用程序,因此我不建议在生产环境或特定用例之外使用此功能。 Or to any one at all really.
或真的对任何一个人。
Nevertheless, by using this, I was able to get (String) new InitialContext().lookup("servername")
to return a specific value blah
via set servername=blah
at the command line. 然而,通过使用这个,我能得到
(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; }
};
}
}
Compile the class, and add it to the CLASSPATH and system properties, by adding these lines to setenv.bat
(create in %CATALINA_HOME%/bin/
): 通过将以
setenv.bat
添加到setenv.bat
(在%CATALINA_HOME%/bin/
创建),编译该类并将其添加到CLASSPATH和系统属性中:
set CLASSPATH=C:\path\to\compiled\class
set CATALINA_OPTS=-Djava.naming.factory.initial=EnvironmentInitialContextFactory
I'm revisiting this (I'm the asker). 我正在重新审视(我是问问者)。 Inspired by this answer , I decided to implement a
ServletContextListener
instead. 受此答案的启发,我决定改为实现
ServletContextListener
。
In summary, you can't make Tomcat put the environment resources outside of java:comp/env/
but you can read them from there and reassign them "wherever". 总之,您不能使Tomcat将环境资源放置在
java:comp/env/
之外,但是您可以从那里读取它们,然后在“任何地方”重新分配它们。
When the ServletContext is initialized, my listener just rebinds them: 初始化ServletContext后,我的侦听器将它们重新绑定:
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
Context ctx = new InitialContext();
ctx.bind("servername", ctx.lookup("java:comp/env/servername"));
}
This is a much better solution - it doesn't fiddle with anything outside of the deployment context. 这是一个更好的解决方案-它不会摆弄部署上下文之外的任何内容。
It's probably also possible to just rebind all names in the comp/env/
namespace, to make a more generic listener. 也可以只重新绑定
comp/env/
名称空间中的所有名称,以创建更通用的侦听器。 For now I am just binding the single names as there are few used by the app. 目前,我仅绑定单个名称,因为该应用程序使用的名称很少。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.