EJB客户端无法连接到JBoss上部署的EJB有状态bean

时间:2016-12-17 07:09:13

标签: java-ee jboss ejb jndi remote-client

我使用eclipse创建了一个EJB项目,并创建了两个类,如下所示。

package com.abhijit.ejbs;

import java.util.List;

import javax.ejb.Remote;

@Remote
public interface TestEJBRemote {

    public void addElement(int a);
    public void removeElement(int a);
    public List getElements();


}

实际的EJB如下 -

package com.abhijit.ejbs;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.LocalBean;
import javax.ejb.Stateful;

/**
 * Session Bean implementation class TesEJB
 */
@Stateful
@LocalBean
public class TestEJB implements TestEJBRemote {

    List <Integer> myList = new ArrayList<>();
    /**
     * Default constructor. 
     */
    public TestEJB() {
        // TODO Auto-generated constructor stub
    }

    @Override
    public void addElement(int a) {
        myList.add(a);
    }

    @Override
    public void removeElement(int a) {
        myList.remove(a);
    }

    @Override
    public List getElements() {
        return myList;
    }

}

然后将此EJB部署在JBoss AS 7上,它运行时没有任何错误..我在控制台中看到此消息 -

**java:global/EJB1/TestEJB!com.abhijit.ejbs.TestEJBRemote
java:app/EJB1/TestEJB!com.abhijit.ejbs.TestEJBRemote
java:module/TestEJB!com.abhijit.ejbs.TestEJBRemote
java:jboss/exported/EJB1/TestEJB!com.abhijit.ejbs.TestEJBRemote
java:global/EJB1/TestEJB!com.abhijit.ejbs.TestEJB
java:app/EJB1/TestEJB!com.abhijit.ejbs.TestEJB
java:module/TestEJB!com.abhijit.ejbs.TestEJB**

现在,我正在创建第二个Eclipse Java项目并编写一个简单的Java远程客户端代码,如下所示 -

package com;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.abhijit.ejbs.TestEJB;
import com.abhijit.ejbs.TestEJBRemote;

public class EJBClient {

    public static void main(String[] args) {
        TestEJBRemote values; 

        try {
            System.out.println("----");

            final Hashtable<String, String> jndiProperties = new Hashtable();
            jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

            //tried with rmi:  also .. not working....
            jndiProperties.put(Context.PROVIDER_URL, "ejb://localhost:1099");

            InitialContext ic = new InitialContext(jndiProperties);

            values = (TestEJBRemote)ic.lookup("java:global/EJB1/TestEJB!com.abhijit.ejbs.TestEJB");
            System.out.println("---" + values.getElements());
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }

尝试使用lookup()中的各种组合但是当我运行这个将在单独的JVM中运行的java客户端代码时,它无法工作..我收到此错误 -

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
    at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)
    at javax.naming.InitialContext.lookup(Unknown Source)
    at com.EJBClient.main(EJBClient.java:25)

我确信它必须与jndi参数有关。但我不知道它是什么......

2 个答案:

答案 0 :(得分:0)

此解决方案适用于Wildfly 8,9和10。

1。添加所需的依赖项wildfly-ejb-client-bom

您需要将依赖项wildfly-ejb-client-bom添加到项目中。

如果您使用的是maven,可以将以下依赖项添加到pom

<dependency>
    <groupId>org.wildfly</groupId>
    <artifactId>wildfly-ejb-client-bom</artifactId>
    <version>10.1.0.Final</version>
    <type>pom</type>
    <scope>runtime</scope>
</dependency>

信息使用其他版本的wildfly 8(8.2.1.Final)或9(9.0.2.Final)。

2。创建jboss-ejb-client.properties

resources文件夹添加到jboss-ejb-client.properties并添加以下内容。

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port = 8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

3。创建初始上下文

您需要按如下方式创建初始上下文。

final Hashtable<String, String> jndiProperties = new Hashtable<>();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);

4。查找远程业务接口

最后,您可以查找有状态会话bean。

TestEJBRemote remote = (TestEJBRemote) context.lookup("ejb:/EJB1/TestEJB!" + TestEJBRemote.class.getName() + "?stateful");

如果您要查找无状态bean,则必须删除?stateful

不幸的是,最新的wildfly文档很乱,而且它们没有提供可行的解决方案。但是你可以在ejb-remote: Remote EJB Client Example下找到一个工作的hello world示例。

答案 1 :(得分:0)

您尝试连接的方式是错误的。

以下应该是连接到远程ejb的格式:

// Create a look up string name
String name = "ejb:" + appName + "/" + moduleName + "/" + distinctName
            + "/" + beanName + "!" + interfaceName;

我向SO文档提供了以下内容。

使用JBoss AS 7.1

设置EJB

<强> 1。概述

在本文中,我们将讨论如何开始使用Enterprise JavaBeans(EJB)。我们将使用JBoss AS 7.1.1.Final,但您可以自由使用您选择的任何服务器。

<强> 2。 Bean的Maven依赖

为了使用EJB,请确保将其最新版本添加到pom.xml文件的dependencies部分:

<dependency>
    <groupId>org.jboss.spec.javax.ejb</groupId>
    <artifactId>jboss-ejb-api_3.2_spec</artifactId>
    <version>1.0.0.Final</version>
</dependency>

确保正确添加JBoss依赖项,因为我们将在本教程中将JBoss用作应用程序服务器。 在本教程的后半部分,我们将详细讨论如何为项目设置maven构建。

第3。 EJB远程

让我们首先创建名为HelloWorldRemote的Bean接口。

public interface HelloWorldRemote {
    public String getHelloWorld();
}

现在我们将实现上述接口并将其命名为HelloWorldBean

@Stateless
public class HelloWorldBean implements HelloWorldRemote {

    public HelloWorldBean() {

    }

    @Override
    public String getHelloWorld(){
        return ("Hello World");
    }
}

请注意类声明顶部的@Stateless表示法。它表示无状态会话bean。

<强> 4。远程Bean的Maven设置

在本节中,我们将讨论如何设置maven以在服务器上构建和运行应用程序。

让我们一个接一个地查看插件。

4.1。编译器插件

maven-compiler-plugin用于编译项目的源代码。

这里我们使用了插件的2.3.1版本,其中源和目标JDK在配置下设置为1.7。

我们已将这些设置定义为标记内的属性,并通过$ {property}引用它。

<version.compiler.plugin>2.3.1</version.compiler.plugin>
<!-- maven-compiler-plugin -->
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>

4.2 EJB插件

此插件生成Bean文件以及相关的客户端jar。

我们已将ejb版本指定为3.2,并且generateClient属性设置为true以生成客户端。

4.3在JBoss中部署

jboss-as-maven-plugin用于在JBoss AS 7中部署,重新部署,取消部署或运行​​该应用程序。

在此配置中,我们指定构建文件名与项目构建文件名相同,在我们的案例ejb-remote-1.0-SNAPSHOT中默认使用artifactid-version格式。

4.4 EJB的所需Maven依赖项

jboss-javaee-6.0定义了我们想要使用的JBoss Java EE 6 API的版本。

JBoss分发一整套Java EE 6 API,包括物料清单(BOM)。

BOM指定工件的堆栈(或集合)的版本。我们在标记中指定它,以便我们始终获得正确的工件版本。这种依赖的类型本身就是一个包含所需依赖关系的pom。

<dependency>
    <groupId>org.jboss.spec</groupId>
    <artifactId>jboss-javaee-6.0</artifactId>
    <version>${version.org.jboss.spec.jboss.javaee.6.0}</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

4.5注释

以下内容将获得注释依赖项:

<dependency>
    <groupId>org.jboss.spec.javax.annotation</groupId>
    <artifactId>jboss-annotations-api_1.1_spec</artifactId>
    <scope>provided</scope>
</dependency>

4.6 EJB版本3.2

在下面的代码中,我们得到了最新版本的规范:

<dependency>
    <groupId>org.jboss.spec.javax.ejb</groupId>
    <artifactId>jboss-ejb-api_3.2_spec</artifactId>
    <version>1.0.0.Final</version>
</dependency>

要在JBoss服务器上运行上述项目,我们需要先运行:

mvn clean install

然后我们需要通过运行以下maven命令将其部署到正在运行的JBoss服务器:

jboss-as:deploy

现在你应该看到在jboss服务器中部署了jar文件。

或者,您可以从项目中的目标文件夹中复制可用的jar,并将其粘贴到服务器的webapp文件夹中。

<强> 5。设置客户端项目

在创建远程bean之后,我们应该通过创建客户端来测试已部署的bean。

首先让我们讨论项目的maven设置。

使用了5.1 Maven插件

maven-compiler-plugin用于编译项目的源代码。

我们为源类和目标类指定了jdk 1.7版本。

我们的客户端是一个Java程序,为了运行它,我们使用exec-maven-plugin来帮助执行系统和Java程序。我们需要指定可执行文件(即java),类路径和java类(com.baeldung.ejb.client.Client)。

类路径为空,因为插件包含基于所提供的依赖项所必需的类路径参数。

5.2 EJB客户端的Maven依赖

为了运行EJB3客户端,我们需要包含以下依赖项。

我们依赖此应用程序的EJB远程业务接口来运行客户端。所以我们需要指定ejb客户端jar依赖项。值为“ejb-client”的标记用于指定此项目对EJB客户端jar的依赖。

<dependency>
    <groupId>com.theopentutorials.ejb3</groupId>
    <artifactId>ejbmavendemo</artifactId>
    <type>ejb-client</type>
    <version>${project.version}</version>
</dependency>

依赖项jboss-transaction-api_1.1_specjboss-ejb-api_3.1_specjboss-ejb-clientxnio-apixnio-niojboss-remotingjboss-sasl,{{1具有作为运行时的作用域,因为这些是运行时所需而不是在编译期间。

dependencyManagement下的依赖关系 jboss-javaee-6.0 jboss-as-ejb-client-bom 的范围为import。这用于将来自远程POM的依赖关系管理信息包括到当前项目中。这些远程POM由JBoss提供,其中包含运行客户端所必需的依赖项。

5.3 JBoss EJB客户端属性

在“src / main / resources”下创建一个文件,并将其命名为jboss-ejb-client.properties。

jboss-marshalling-river

<强> 6。创建客户端类

首先我们创建一个ClientUtility类:

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port = 4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

现在让我们创建一个实际的Client类,它将使用我们在服务器中部署的bean:

public class ClientUtility {
    private static Context initialContext;
    private static final String PKG_INTERFACES = "org.jboss.ejb.client.naming";

    public static Context getInitialContext() throws NamingException {
        if (initialContext == null) {
            Properties properties = new Properties();
            properties.put(Context.URL_PKG_PREFIXES, PKG_INTERFACES);
            initialContext = new InitialContext(properties);
         }
        return initialContext;
    }
}

Client类使用bean并输出结果。

<强> 7。结论

因此,我们创建了一个EJB服务器和一个使用该服务的客户端。该项目可以在任何Application Server上运行。