Простой способ запустить автономный сервер JNDI (и зарегистрировать некоторые ресурсы) - PullRequest
9 голосов
/ 03 мая 2011

В целях тестирования я ищу простой способ запуска автономного сервера JNDI и привязки моего javax.sql.DataSource к "java:/comp/env/jdbc/mydatasource" программным способом.

Сервердолжен привязать себя к некоторому URL, например: «java.naming.provider.url = jnp: // localhost: 1099» (не обязательно должен быть JNP), чтобы я мог найти свой источник данных из другого процесса.Меня не волнует, какую реализацию JNDI-сервера мне придется использовать (но я не хочу запускать полноценный JavaEE-сервер).

Это должно быть так просто, но, к моему удивлению,Я не смог найти ни одного (рабочего) учебника.

Ответы [ 8 ]

8 голосов
/ 04 мая 2011

JDK содержит провайдера JNDI для реестра RMI . Это означает, что вы можете использовать реестр 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.

4 голосов
/ 30 января 2014

Я работал над кодом Джона и сейчас хорошо работает.

В этой версии я использую библиотеки JBoss5.1.0.GA, см. Список jar ниже:

  • jboss-5.1.0.GA \ клиент \ jbossall-client.jar
  • jboss-5.1.0.GA \ сервер \ минимален \ Lib \ jnpserver.jar
  • jboss-5.1.0.GA \ сервер \ минимален \ Lib \ log4j.jar
  • jboss-remote-naming-1.0.1.Final.jar (загружается с http://search.maven.com)

Это новый код:

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();
    }
}

}
3 голосов
/ 19 июня 2012

Вот фрагмент кода, адаптированный из примеров удаленного взаимодействия 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);
    } 
}
2 голосов
/ 31 июля 2012

Я знаю, что опаздываю на вечеринку, но в итоге я взломал это вместе вот так

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);
    }
}
0 голосов
/ 31 июля 2018

Недавно я искал подобное простое стартовое решение.«Поставщик услуг файловой системы от 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

0 голосов
/ 11 сентября 2017

Для локальных однопроцессных банок с одним процессом я бы использовал пакет весеннего тестирования:

    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
0 голосов
/ 03 мая 2011

Вы подразумеваете, что нашли неработающие учебники;это может означать, что вы уже видели это:

Я быстро пошел, но не смог заставить это работать.Впрочем, немного большей настойчивости это может сделать.

0 голосов
/ 03 мая 2011

Рассматривали ли вы использование Mocks? Если я правильно помню, вы используете интерфейсы для взаимодействия с JNDI. Я знаю, что издевался над ними хотя бы раз.

В качестве запасного варианта вы, вероятно, могли бы использовать Tomcat. Это не полноценный J2EE-импл, он запускается быстро и довольно прост в настройке ресурсов JNDI. Настройка источника данных хорошо документирована. Это неоптимально, но должно работать.

...