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");
...
}