JNDI

Java Naming and Directory Interface

Java EEサーバのEJB、JDBCデータソースやJMSのConnectionFactoryなど、各種サービスにアクセスするためのエントリポイントである

★JNDIネームスペースとファイルシステム

★Global JNDI names for EJBs

・Global JNDI

java:global[/<app-name>l]/<module-name>/<bean-name>l[!<fully-qualified-interface-name>l]

Deployed on the same server but as part of a separate application.

・Application JNDI

java:app/<module-name>l/<bean-name>l[!<fully-qualified-interface-name>l]

Deployed on the same server but as part of the same application.

・Module JNDI

java:module/<bean-name>l[!<fully-qualified-interface-name>l]

Deployed on the same server but as part of the same module.

補足:

app-name デフォルトはearファイルの名前

module-name デフォルトはejb-jarファイルの名前

bean-name EJBクラス名

※warファイルの場合 app-nameは省略、module-nameはwarファイルの名前

>サンプル1

@Stateless(name="MyBean")

public class Bean implements Local, Remote { ... }

package com.xxx;

@Local

public interface Local { ... }

package com.yyy;

@Remote

public interface Remote { ... }

Local取得

java:global/myapp/mymodule/MyBean!com.xxx.Local

java:app/mymodule/MyBean!com.xxx.Local

java:module/MyBean!com.xxx.local

Remote取得

java:global/myapp/mymodule/MyBean!com.yyy.Remote

java:app/mymodule/MyBean!com.yyy.Remote

java:module/MyBean!com.yyy.Remote

>サンプル2

package com.xxx;

@Stateless

@Remote(Remote.class)

@LocalBean

public class Bean implements Remote { ... }

Bean取得

java:global/myapp/mymodule/Bean!com.xxx.Remote

java:global/myapp/mymodule/Bean!com.xxx.Bean

java:global/myapp/mymodule/Bean

java:app/mymodule/Bean!com.xxx.Remote

java:app/mymodule/Bean!com.xxx.Bean

java:app/mymodule/Bean

java:module/Bean!com.xxx.Remote

java:module/Bean!com.xxx.Bean

java:module/Bean

java:jboss/exported/myapp/mymodule/Bean!com.xxx.Remote

java:jboss/exported/myapp/mymodule/Bean!com.xxx.Bean

java:jboss/exported/myapp/mymodule/Bean

※他サイトを参照

★Lookupの引数

java:

Java VMローカル空間。

Java VMの外からリモートアクセスできない。

java:comp

コンポーネントローカル空間。

コンポーネントごと(EJBなど)に作られる隔離空間。

java:comp/env

環境ネーミングコンテキストと呼ばれて、コンポーネントで利用するJNDI空間。

"jdbc", "ejb", "jms", "mail"などのサブツリーをバインドする。

InitialContext context = new InitialContext();

DataSource ds = (DataSource) context.lookup("java:DefaultDS");

DataSource ds = (DataSource) context.lookup("java:comp/env/jdbc/SampleDS");

java:comp/env Configuration environment

java:comp/env/jdbc JDBC DataSource pools

java:comp/env/jms JMS connection factories

java:comp/env/mail JavaMail connection factories

java:comp/env/url URL connection factories

java:comp/UserTransaction

java:comp/EJBContext

java:comp/TransactionSynchronizationRegistry

java:/queues/xxxQueue

java:jboss/infinispan/cache/xxxCache

★プロパティについて

Properties props = new Properties();

props.put(Context.INITIAL_CONTEXT_FACTORY, "<サービス・プロバイダーのファクトリー・クラス名>");

props.put(Context.PROVIDER_URL, "<サービス・プロバイダーを示すURL>");

InitialContext context = new InitialContext(props);

★Get Resources in EJB

Approach 1 Default mapping rules

@Resource(name="jdbc/__default")

private DataSource defaultDataSource;

Approach 2 EJBContext lookup

@Resource

private SessionContext sctx;

DataSource dataSource = (DataSource) sctx.lookup("jdbc/test");

Connection connection = dataSource.getConnection();

ejb-jar.xml

<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

metadata-complete="false" version="3.0"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd">

<enterprise-beans>

<session>

<ejb-name>ResourceBean</ejb-name>

<resource-ref>

<res-ref-name>jdbc/test</res-ref-name>

<res-type>javax.sql.DataSource</res-type>

</resource-ref>

</session>

</enterprise-beans>

</ejb-jar>

Approach 3 Traditional JNDI lookup

import javax.naming.InitialContext;

import javax.naming.Context;

Context ctx = (Context) new InitialContext().lookup("java:comp/env");

DataSource dataSource = (DataSource) ctx.lookup("jdbc/test");

あるいは

Context ctx = (Context) new InitialContext();

DataSource dataSource = (DataSource) ctx.lookup("java:comp/env/jdbc/test");

web.xml

<resource-ref>

<res-ref-name>jdbc/test</res-ref-name>

<res-type>javax.sql.DataSource</res-type>

<res-auth>Container</res-auth>

<res-sharing-scope>Shareable</res-sharing-scope>

<mapped-name>jdbc/__default</mapped-name>

</resource-ref>

あるいは

ejb-jar.xml(同上)

★JNDI応用

サンプル1

import javax.jms.ConnectionFactory;

import javax.jms.Queue;

import java.util.Properties;

@BeforeClass

public static void configure() {

System.setProperty(

"aConnectionFactory",

"connectionfactory:org.apache.activemq.ActiveMQConnectionFactory:tcp://localhost:11616");

System.setProperty(

"aQueue",

"queue:org.apache.activemq.command.ActiveMQQueue:LISTENER");

}

@Test

public void shouldSend() throws Exception {

final Properties properties = new Properties();

properties.setProperty(

Context.INITIAL_CONTEXT_FACTORY,

"org.apache.openejb.client.RemoteInitialContextFactory");

final Context context = new InitialContext(properties);

final Queue destination = (Queue) context.lookup("java:aQueue");

assertNotNull(destination);

assertEquals("LISTENER", destination.getQueueName());

final ConnectionFactory connectionFactory

= (ConnectionFactory) context.lookup("java:aConnectionFactory");

assertNotNull(connectionFactory);

}

サンプル2

@Remote({MyEJBRemote.class})

@Local({MyEJBLocal.class})

@Stateless

public class MyEJB implements MyEJBLocal, MyEJBRemote {

...

}

private Context context;

protected void setUp() throws Exception {

context = EJBContainer.createEJBContainer().getContext();

}

public void shouldXxx() throws Exception {

MyEJBRemote ejb = (MyEJBRemote) context.lookup(

"java:global/<project>/MyEJB!xxx.MyEJBRemote");

...

MyEJBLocal ejb = (MyEJBLocal) context.lookup(

"java:global/<project>/MyEJB!xxx.MyEJBLocal");

...

}