0

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

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 参数有关..但我不明白它是什么......

4

2 回答 2

0

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

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

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

我为 SO 文档贡献了以下内容。


使用 JBoss AS 7.1 设置 EJB

一、概述

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

2. Bean 的 Maven 依赖

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

<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 中部署、重新部署、取消部署或运行​​应用程序。

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

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 EJB3客户端的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_spec, jboss-ejb-api_3.1_spec, jboss-ejb-client, xnio-api, xnio-nio, jboss-remoting, jboss-sasl,jboss-marshalling-river具有运行时范围,因为它们是运行时必需的,而不是在编译时。

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

5.3 JBoss EJB 客户端属性

在“src/main/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 = 4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

6. 创建客户端类

首先我们创建一个 ClientUtility 类:

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:

public class Client {
    
    //The lookup method to get the EJB name
    private static HelloWorldRemote doLookup() {
        Context context = null;
        HelloWorldRemote bean = null;
        try {
            // 1. Obtaining Context
            context = ClientUtility.getInitialContext();
            // 2. Generate JNDI Lookup name
            String lookupName = getLookupName();
            // 3. Lookup and cast
            bean = (HelloWorldRemote) context.lookup(lookupName);
 
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return bean;
    }
 
    private static String getLookupName() {
        
         // The app name is the EAR name of the deployed EJB without .ear suffix.
         // Since we haven't deployed the application as a .ear, the app name for
         // us will be an empty string
         
        String appName = "";
 
        
         // The module name is the JAR name of the deployed EJB without the .jar
         // suffix.
        String moduleName = "ejb-remote-0.0.1-SNAPSHOT";
 
        
        // AS7 allows each deployment to have an (optional) distinct name. This
        // can be an empty string if distinct name is not specified.
        String distinctName = "";
 
        // The EJB bean implementation class name
        String beanName = "HelloWorldBean";
 
        // Fully qualified remote interface name
        final String interfaceName = "com.baeldung.ejb.tutorial.HelloWorldRemote";
 
        // Create a look up string name
        String name = "ejb:" + appName + "/" + moduleName + "/" + distinctName
                + "/" + beanName + "!" + interfaceName;
        
        return name;
    }
}

Client 类使用 bean 并输出结果。

7. 结论

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

于 2016-12-19T18:55:26.400 回答
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文件夹 ajboss-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 下找到一个有效的 hello world 示例:远程 EJB 客户端示例

于 2016-12-19T18:34:24.013 回答