Para fins de teste, estou procurando uma maneira simples de iniciar um servidor JNDI autônomo e vincular meu javax.sql.DataSource a "java:/comp/env/jdbc/mydatasource"
programaticamente.
O servidor deve ligar-se a alguma URL, por exemplo: “java.naming.provider.url = jnp: // localhost: 1099” (não precisa ser JNP), para que eu possa procurar minha fonte de dados de outro processo . Eu não me importo com qual implementação do servidor JNDI eu terei que usar (mas eu não quero iniciar um servidor JavaEE completo).
Isso deve ser fácil, mas para minha surpresa, não consegui encontrar nenhum tutorial (de trabalho).
O JDK contém um provedor JNDI para o registro RMI . Isso significa que você pode usar o registro do RMI como um servidor JNDI. Então, apenas inicie o rmiregistry , defina java.naming.factory.initial como com.sun.jndi.rmi.registry.RegistryContextFactory , e você está ausente.
O registro RMI tem um namespace simples, então você não será capaz de se ligar a java: / comp / env / jdbc / mydatasource, mas poderá se ligar a algo para aceitar java: / comp / env / jdbc / mydatasource, mas irá tratá-lo como um nome de componente único (obrigado, @ EJP).
Eu escrevi um pequeno aplicativo para demonstrar como fazer isso: https://bitbucket.org/twic/jndiserver/src
Eu ainda não tenho idéia de como o servidor JNP deve funcionar.
Eu trabalhei no código do John e agora está funcionando bem.
Nesta versão estou usando libs do JBoss5.1.0.GA, veja lista de jar abaixo:
Este é o novo código:
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
Para ter um bom registro, use estas propriedades 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
Para consumir o servidor JNDI Independente, use esta class de cliente:
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(); } } }
Aqui está um trecho de código adaptado das amostras remotas do JBoss. O código que está nas amostras (versão 2.5.4.SP2) não funciona mais. Embora a correção seja simples, levei mais horas do que quero pensar para descobrir. Suspiro. De qualquer forma, talvez alguém possa se beneficiar.
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
Eu sei que estou atrasado para a festa, mas acabei hackeando isso juntos assim
InitialContext ctx = new InitialContext(); // check if we have a JNDI binding for "jdbc". If we do not, we are // running locally (ie through JUnit, etc) boolean isJndiBound = true; try { ctx.lookup("jdbc"); } catch(NameNotFoundException ex) { isJndiBound = false; } if(!isJndiBound) { // Create the "jdbc" sub-context (ie the directory) ctx.createSubcontext("jdbc"); //parse the jetty-web.xml file Map 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); } }
Você já pensou em usar o Mocks? Se bem me lembro, você usa Interfaces para interagir com o JNDI. Eu sei que eu zombei deles pelo menos uma vez antes.
Como alternativa, você provavelmente poderia usar o Tomcat. Não é um completo J2EE impl, ele inicia rápido e é bastante fácil de configurar resources JNDI. A configuração do DataSource está bem documentada. É sub-ótimo, mas deve funcionar.
Você insinua que encontrou tutoriais que não funcionam; isso pode significar que você já viu estes:
Eu fui rápido, mas não consegui fazer isso funcionar. Um pouco mais de perseverança pode fazer isso, no entanto.
Para locais, um processo jar purpouses standalone eu usaria o pacote de teste de primavera:
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); SQLServerConnectionPoolDataSource myDS = new SQLServerConnectionPoolDataSource(); //setup... builder.bind("java:comp/env/jdbc/myDS", myDS); builder.activate();
log de boot:
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
Eu tenho procurado por uma solução inicial simples similar recentemente. O “provedor de serviços de sistema de arquivos da Sun Microsystems” funcionou bem para mim. Veja https://docs.oracle.com/javase/jndi/tutorial/basics/prepare/initial.html .
O problema com o registro RMI é que você precisa de um visualizador – aqui você só precisa olhar para o conteúdo do arquivo.
Você pode precisar de fscontext-4.2.jar – eu obtive de http://www.java2s.com/Code/Jar/f/Downloadfscontext42jar.htm