2

我正在使用 Jboss AS 6 尝试一个简单的 EJB 2.1 HelloWorld。我创建了一个具有以下结构的 EJB jar 文件:

HelloWorldEjb
    |-ex1
        |-ejb21
            |-ejb.jar.xml
            |-Hello.java
            |-HelloBean.java
            |-HelloHome.java
            |-HelloLocal.java
            |-HelloLocalHome.java

我还创建了一个客户端独立 java 类来测试上面的 ejb。我使用 Jboss 6 管理控制台在 Applications > EJB2 jars 下部署了 jar 文件,然后单击“添加新资源”。当我添加 jar 文件时,它给了我这条消息,所以我认为它已正确部署。

Resource HelloWorldEjb.jar created successfully! 

现在,当我运行客户端时,出现此错误:

log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
javax.naming.NameNotFoundException: HelloHome not bound
    at org.jnp.server.NamingServer.getBinding(NamingServer.java:771)
    at org.jnp.server.NamingServer.getBinding(NamingServer.java:779)
    at org.jnp.server.NamingServer.getObject(NamingServer.java:785)
    at org.jnp.server.NamingServer.lookup(NamingServer.java:443)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
    at sun.rmi.transport.Transport$1.run(Transport.java:159)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
    at java.lang.Thread.run(Thread.java:619)
    at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:255)
    at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:233)
    at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:142)
    at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:728)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:688)
    at javax.naming.InitialContext.lookup(InitialContext.java:392)
    at client.HelloClient.main(HelloClient.java:58)
Exception in thread "main" java.lang.NullPointerException
    at client.HelloClient.main(HelloClient.java:72)

最初我认为我必须配置客户端将用于连接的 JNDI 资源以在应用程序服务器上查找 EJB。这不是必需的吗?我正在使用的示例是在查找语句中使用 EJB 名称。这是用于建立连接的客户端代码部分。:

    Properties env = new Properties();

env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory" );
env.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces");
env.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");

    //env = new InitialContext(env);

InitialContext ctx = null;

try {
    ctx = new InitialContext(env);
} catch (NamingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}       

Object obj = null;

try {
    obj = ctx.lookup("HelloHome");
} catch (NamingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

HelloHome home = (HelloHome) javax.rmi.PortableRemoteObject.narrow(obj, HelloHome.class);

这里是 ejb-jar.xml 的内容

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar
    xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instalce"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd"
    version="2.1">

    <enterprise-beans>
        <session>
            <ejb-name>HelloWorldEJB</ejb-name>
            <home>ex1.ejb21.HelloHome</home>
            <remote>ex1.ejb21.Hello</remote>
            <local-home>ex1.ejb21.HelloLocalHome</local-home>
            <local>ex1.ejb21.HelloLocal</local>
            <ejb-class>ex1.ejb21.HelloBean</ejb-class>
            <session-type>Stateless</session-type>
            <transaction-type>Container</transaction-type>
        </session>  
    </enterprise-beans>

</ejb-jar>

我发现有趣的一件事是,当我编译客户端类时,它拒绝编译,除非它引用了 HelloHome 类。为了解决这个问题,我必须将 ejb jar 文件添加到客户端类的类路径中。这是它应该如何工作的吗?即ejb jar 文件需要在客户端的类路径上?

就用于查找的 jndi 名称而言,我是否需要创建一个新名称?在上面的示例中,看起来 EJB 名称被用作查找。

编辑

我目前正在阅读一本关于 EJB 3.0 的书。EBJ 3.0 的部分介绍是向我介绍 2.0 变体,因此我为什么要尝试这个示例。我认为即使我不打算使用 EJB2,至少对它们的工作方式有一点了解也是有意义的。

我查看了控制台以获取已部署应用程序的列表,但我在 EJB2.0 菜单项上看不到我的应用程序。我认为这意味着 jar 文件没有正确部署。Jboss 日志确实显示它已部署(见下面的第 4 行)。

16:36:50,982 INFO  [org.rhq.core.pc.PluginContainer] Plugin Container initialized.
16:36:50,987 INFO  [org.jboss.on.embedded.manager.pc.PluginContainerResourceManager] Discovering Resources...
16:36:50,988 INFO  [org.rhq.core.pc.inventory.AutoDiscoveryExecutor] Executing server discovery scan...
16:36:53,920 INFO  [org.rhq.core.pc.inventory.InventoryManager] Detected new Server [Resource[id=-3, type=JBossAS Server, key=C:\bin\appservers\jboss-6.1.0.Final\server\default, name=JBoss AS 6 (default), parent=<null>, version=6.1.0.Final]] - adding to local inventory...
16:36:54,032 INFO  [org.rhq.core.pc.inventory.AutoDiscoveryExecutor] Found 0 servers.
16:36:54,032 INFO  [org.rhq.core.pc.inventory.RuntimeDiscoveryExecutor] Running runtime discovery scan rooted at [platform]
16:36:54,093 INFO  [org.rhq.core.pc.inventory.InventoryManager] Detected new Server [Resource[id=-4, type=JBoss AS JVM, key=JVM, name=JVM, parent=<null>, version=1.6.0_07]] - adding to local inventory...
16:36:54,097 INFO  [org.rhq.plugins.jmx.JMXServerComponent] Starting connection to JMX Server JVM
16:36:54,695 INFO  [org.rhq.core.pc.inventory.RuntimeDiscoveryExecutor] Scanned [0] servers and found [0] total descendant Resources.

我上面描述的结构中有什么看起来不对的地方吗?

编辑

好的,我在richj 的评论的帮助下设法解决了这个问题。看起来我将 ejb-jar.xml 文件放在了错误的位置。它应该在 META-INF 文件夹中。我将它从 ext1/ejb21 复制到 /META-INF 并且 jboss 拿起了 jar 文件。

17:21:44,376 INFO  [org.rhq.core.pc.inventory.RuntimeDiscoveryExecutor] Scanned [0] servers and found [0] total descendant Resources.
17:21:45,301 INFO  [org.jboss.ejb.plugins.local.BaseLocalProxyFactory] Unbind EJB LocalHome 'HelloWorldEJB' from jndi 'local/HelloWorldEJB@21777607'
17:21:45,349 INFO  [org.jboss.proxy.ejb.ProxyFactory] Unbind EJB Home 'HelloWorldEJB' from jndi 'HelloWorldEJB'
17:21:45,358 INFO  [org.jboss.ejb.EjbModule] Undeployed HelloWorldEJB
17:21:45,437 INFO  [org.jboss.ejb.deployers.EjbDeployer] installing bean: ejb/#HelloWorldEJB,uid10624357
17:21:45,438 INFO  [org.jboss.ejb.deployers.EjbDeployer]   with dependencies:
17:21:45,439 INFO  [org.jboss.ejb.deployers.EjbDeployer]   and supplies:
17:21:45,440 INFO  [org.jboss.ejb.deployers.EjbDeployer]        jndi:HelloWorldEJB/ex1.ejb21.Hello
17:21:45,441 INFO  [org.jboss.ejb.deployers.EjbDeployer]        jndi:local/HelloWorldEJB@28622485
17:21:45,442 INFO  [org.jboss.ejb.deployers.EjbDeployer]        jndi:HelloWorldEJB/ex1.ejb21.HelloLocal
17:21:45,443 INFO  [org.jboss.ejb.deployers.EjbDeployer]        jndi:HelloWorldEJB
17:21:45,466 INFO  [org.jboss.ejb.EjbModule] Deploying HelloWorldEJB
17:21:45,495 INFO  [org.jboss.ejb.plugins.local.BaseLocalProxyFactory] Bound EJB LocalHome 'HelloWorldEJB' to jndi 'local/HelloWorldEJB@28622485'
17:21:45,503 INFO  [org.jboss.proxy.ejb.ProxyFactory] Bound EJB Home 'HelloWorldEJB' to jndi 'HelloWorldEJB'

我还对 xml 文件做了一些小改动,因为使用的命名空间中有错字。

我使用 HelloWorldEJB 作为客户端的 jndi 名称,它终于奏效了。

谢谢。

4

1 回答 1

4

我认为您的例外意味着:

  • 客户端代码使用错误的名称来查找 EJB,或者...
  • EJB 未在 JNDI 中注册

这行得通吗?

obj = ctx.lookup("HelloHomeEJB");

可以使用 <jndi-name> 标记为远程 home 定义 JNDI 名称(使用 <local-jndi-name> 标记为本地 home 定义 JNDI 名称。)

这是它应该如何工作的吗?即ejb jar 文件需要在客户端的类路径上?

客户端需要访问接口类。最简单的方法是使用 ejb jar 文件,但最简单的方法是创建一个客户端版本的 ejb jar 文件,其中不包含任何仅与 EJB 实现相关的类。

编辑 - 未部署 jar 文件

当部署 EJB 时,应该将类似这样的内容写入日志文件:

18:49:33,979 INFO  [EjbDeployer] installing bean: ejb/helloworld-ejb.jar#HelloWorld,uid181111540
18:49:33,979 INFO  [EjbDeployer]   with dependencies:
18:49:33,980 INFO  [EjbDeployer]   and supplies:
18:49:33,980 INFO  [EjbDeployer]        jndi:HelloWorldLocal
18:49:33,980 INFO  [EjbDeployer]        jndi:HelloWorld

部署 EJB jar 文件的常用方法是将其放入您正在使用的服务器的部署目录中(注意,标准的 JBoss 安装通常提供多个服务器配置。)在我的系统上,部署目录是:

/usr/local/jboss/server/default/deploy

有时多个jar文件打包在一个ear文件中。部署方法相同,但 jar 文件应列在 ear 文件的 META-INF/application.xml 部署描述符中。

于 2011-12-20T16:37:24.793 回答