出于测试目的,我正在寻找一种简单的方法来启动独立的 JNDI服务器,并以编程方式将我的javax.sql.DataSource绑定到"java:/comp/env/jdbc/mydatasource"
。
服务器应该将自己绑定到某个URL,例如:“java.naming.provider.url = jnp:// localhost:1099”(不一定是JNP),这样我就可以查找我的数据源从另一个过程。我不关心我必须使用哪个JNDI服务器实现(但我不想启动一个完整的JavaEE服务器)。
这应该很容易,但令我惊讶的是,我找不到任何(工作)教程。
答案 0 :(得分:8)
JDK包含JNDI provider for the RMI registry。这意味着您可以将RMI注册表用作JNDI服务器。所以,只需启动rmiregistry,将java.naming.factory.initial设置为com.sun.jndi.rmi.registry.RegistryContextFactory即可离开。
RMI注册表有一个扁平的命名空间,所以你将无法绑定到java:/ comp / env / jdbc / mydatasource,但是你可以绑定到某些东西所以它将接受java:/ comp / env / jdbc / mydatasource,但会将其视为单组件名称(感谢@EJP)。
我写了一个小应用程序来演示如何执行此操作:https://bitbucket.org/twic/jndiserver/src
我仍然不知道JNP服务器应该如何工作。
答案 1 :(得分:4)
我参与了约翰的代码,现在工作得很好。
在这个版本中,我使用的是JBoss5.1.0.GA的库,请参阅下面的jar列表:
这是新代码:
import java.net.InetAddress;
import java.util.Hashtable;
import java.util.concurrent.Callable;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.jnp.server.Main;
import org.jnp.server.NamingBeanImpl;
public class StandaloneJNDIServer implements Callable<Object> {
public Object call() throws Exception {
setup();
return null;
}
@SuppressWarnings("unchecked")
private void setup() throws Exception {
//configure the initial factory
//**in John´s code we did not have this**
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
//start the naming info bean
final NamingBeanImpl _naming = new NamingBeanImpl();
_naming.start();
//start the jnp serve
final Main _server = new Main();
_server.setNamingInfo(_naming);
_server.setPort(5400);
_server.setBindAddress(InetAddress.getLocalHost().getHostName());
_server.start();
//configure the environment for initial context
final Hashtable _properties = new Hashtable();
_properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
_properties.put(Context.PROVIDER_URL, "jnp://10.10.10.200:5400");
//bind a name
final Context _context = new InitialContext(_properties);
_context.bind("jdbc", "myJDBC");
}
public static void main(String...args){
try{
new StandaloneJNDIServer().call();
}catch(Exception _e){
_e.printStackTrace();
}
}
}
要获得良好的日志记录,请使用此log4j属性:
log4j.rootLogger=TRACE, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
要使用独立JNDI服务器,请使用此客户端类:
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
/**
*
* @author fabiojm - Fábio José de Moraes
*
*/
public class Lookup {
public Lookup(){
}
@SuppressWarnings("unchecked")
public static void main(String[] args) {
final Hashtable _properties = new Hashtable();
_properties.put("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
_properties.put("java.naming.provider.url", "jnp://10.10.10.200:5400");
try{
final Context _context = new InitialContext(_properties);
System.out.println(_context);
System.out.println(_context.lookup("java:comp"));
System.out.println(_context.lookup("java:jdbc"));
}catch(Exception _e){
_e.printStackTrace();
}
}
}
答案 2 :(得分:3)
这是一个改编自JBoss远程处理示例的代码片段。代码是 在样本(版本2.5.4.SP2)中不再有效。虽然修复 这很简单,我花了很多时间才想到想出来。 叹。无论如何,也许有人可以受益。
package org.jboss.remoting.samples.detection.jndi.custom;
import java.net.InetAddress;
import java.util.concurrent.Callable;
import org.jnp.server.Main;
import org.jnp.server.NamingBeanImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class StandaloneJNDIServer implements Callable<Object> {
private static Logger logger = LoggerFactory.getLogger( StandaloneJNDIServer.class );
// Default locator values - command line args can override transport and port
private static String transport = "socket";
private static String host = "localhost";
private static int port = 5400;
private int detectorPort = 5400;
public StandaloneJNDIServer() {}
@Override
public Object call() throws Exception {
StandaloneJNDIServer.println("Starting JNDI server... to stop this server, kill it manually via Control-C");
//StandaloneJNDIServer server = new StandaloneJNDIServer();
try {
this.setupJNDIServer();
// wait forever, let the user kill us at any point (at which point, the client will detect we went down)
while(true) {
Thread.sleep(1000);
}
}
catch(Exception e) {
e.printStackTrace();
}
StandaloneJNDIServer.println("Stopping JBoss/Remoting server");
return null;
}
private void setupJNDIServer() throws Exception
{
// start JNDI server
String detectorHost = InetAddress.getLocalHost().getHostName();
Main JNDIServer = new Main();
// Next two lines add a naming implemention into
// the server object that handles requests. Without this you get a nice NPE.
NamingBeanImpl namingInfo = new NamingBeanImpl();
namingInfo.start();
JNDIServer.setNamingInfo( namingInfo );
JNDIServer.setPort( detectorPort );
JNDIServer.setBindAddress(detectorHost);
JNDIServer.start();
System.out.println("Started JNDI server on " + detectorHost + ":" + detectorPort );
}
/**
* Outputs a message to stdout.
*
* @param msg the message to output
*/
public static void println(String msg)
{
System.out.println(new java.util.Date() + ": [SERVER]: " + msg);
}
}
答案 3 :(得分:2)
我知道我迟到了,但我最终还是像这样一起黑客攻击
InitialContext ctx = new InitialContext();
// check if we have a JNDI binding for "jdbc". If we do not, we are
// running locally (i.e. through JUnit, etc)
boolean isJndiBound = true;
try {
ctx.lookup("jdbc");
} catch(NameNotFoundException ex) {
isJndiBound = false;
}
if(!isJndiBound) {
// Create the "jdbc" sub-context (i.e. the directory)
ctx.createSubcontext("jdbc");
//parse the jetty-web.xml file
Map<String, DataSource> dataSourceProperties = JettyWebParser.parse();
//add the data sources to the sub-context
for(String key : dataSourceProperties.keySet()) {
DataSource ds = dataSourceProperties.get(key);
ctx.bind(key, ds);
}
}
答案 4 :(得分:0)
你考虑过使用Mocks吗?如果我没记错的话,你可以使用Interfaces与JNDI进行交互。我知道我以前至少曾经嘲笑过他们一次。
作为后备,你可能会使用Tomcat。它不是一个完整的J2EE impl,它启动速度很快,并且很容易配置JNDI资源。 DataSource设置已有详细记录。它是次优的,但应该有效。
答案 5 :(得分:0)
你暗示你发现了非工作教程;这可能意味着你已经看过这些:
我快速去了,但无法让这个工作。但是,坚持不懈可能会做到这一点。
答案 6 :(得分:0)
对于本地,一个进程独立的jar purpouses我会使用spring-test包:
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
SQLServerConnectionPoolDataSource myDS = new SQLServerConnectionPoolDataSource();
//setup...
builder.bind("java:comp/env/jdbc/myDS", myDS);
builder.activate();
启动日志:
22:33:41.607 [main] INFO org.springframework.mock.jndi.SimpleNamingContextBuilder - Static JNDI binding: [java:comp/env/jdbc/myDS] = [SQLServerConnectionPoolDataSource:1]
22:33:41.615 [main] INFO org.springframework.mock.jndi.SimpleNamingContextBuilder - Activating simple JNDI environment
答案 7 :(得分:0)
最近我一直在寻找类似的简单入门解决方案。 “ Sun Microsystems的文件系统服务提供商”对我来说很好。参见https://docs.oracle.com/javase/jndi/tutorial/basics/prepare/initial.html。
RMI注册表的问题是您需要查看器-在这里您只需要查看文件内容即可。
您可能需要fscontext-4.2.jar-我是从http://www.java2s.com/Code/Jar/f/Downloadfscontext42jar.htm获得的