Java Solaris 加入Sun中国技术社区 我的社区 注册说明
 
JDK 6.0 API 中文版
 
 
 
 
 
Java API 文档中文版
使用GlassFish v2、Apache Maven 2和NetBeans IDE 6.0构建EJB 3.0 应用程序
 
By Jacek Laskowski, 10/24/07  
为了修复 Apache OpenEJB运行中的潜在错误,即 系统错误地拒绝使用remove()方法( GERONIMO-3452 Stateless Session EJBs cannot contain a remove() method),我需要构建一个环境,我决定使用一些可用的工具创建环境并最小化创建时间。我决定通过以下方法解决问题:首先在符合Java EE 5规范的 GlassFish v2应用服务器(Java EE 5的参考实现)上运行它,然后根据它是否能够正确运行再采取措施。

内容

  1. 软件需求
  2. 创建项目结构
    1. 创建父结构——ejb3-remove-stateless
    2. 创建子项目——ejb3-remove-stateless-ejb3
    3. 创建子项目——ejb3-remove-stateless-client
    4. 完整的项目结构
  3. 创建EJB bean——Removable
    1. 声明EJB 3.0库的依赖关系
    2. 远程业务接口——RemovableRemote
    3. bean类型——RemovableBean
  4. 创建远程客户机——RemovableClient
  5. 启动
    1. GlassFish服务器启动
    2. 安装EJB bean——Removable
    3. 远程客户机启动——RemovableClient

软件需求

要创建EJB 3.0应用程序构建环境,需要使用以下项目:

假定以上软件已全部安装并且运行正常。软件安装的方法为将文件解压到所选目录中。

要安装NetBeans Maven2项目支持插件,需要启动NetBeans IDE 6.0。接下来,选择 Tools > Plugins 菜单,从出现的对话框中选择 Available Plugins选项卡并选择插件。

完整的项目可从 ejb3-remove-stateless.zip获得.

创建项目结构

2.1 创建父项目——ejb3-remove-stateless

为了使Apache Maven 2(后文简称为 m2)运行的项目更具条理性,我们首先将创建一个父项目(主项目)。创建一个pom类型的项目,其中包含两个子项目——EJB bean模块和远程客户机模块。

我们也可以手动创建项目——使用 mvn命令,或者使用 NetBeans Maven2 project support插件。使用插件可以简化环境创建过程,并且可以更轻松地使用m2。有了插件后,我 们能够在IDE级别执行大部分的管理功能。目前,这些功能是通过命令行执行的。

假设NetBeans Maven2项目支持插件已正确安装,选择 File > New Project菜单,然后选择 Maven类别中的 Maven Project


单击 Next >


再次单击 Next > ,选择 Maven Quickstart Project 原型。

在接下来出来的界面中选择以下项目设置:

  • Project Name: ejb3-remove-stateless
  • Project Location: C:\
  • Group Id: pl.jaceklaskowski.javaee
  • Version: 1.0
  • Package: pl.jaceklaskowski.javaee


这些设置可能与前面给出的不同,但是本文后面的内容假设这些内容是相同的。

单击 Finish完成项目的创建。

现在,我们已经创建了一个jar类型的项目。我们将修改项目的配置,使它能够履行父项目的角色。选择新的ejb3-remove-stateless项目,右键单击鼠标并从下拉菜单中选择 Properties选项。将 Packaging字段的 jar值改为 pom


我们还需要修改项目的属性,因为我们要使用Java版本。


单击 OK,确认修改。

最后一步是删除 src目录,它是在创建项目时默认创建的,但我们在这里不会使用到,至此,项目准备完毕。要删除目录,转到 Files选项卡,选择 src目录,并从下拉菜单中选择 Delete

从项目中删除测试库 junit-3.8.1(我们稍后将修改为版本4.2)。

创建子项目——ejb3-remove-stateless-ejb3

要创建 ejb3-remove-stateless-ejb3 子项目,我们还要再一次使用NetBeans IDE 6.0。我 们将执行与创建ejb3-remove-stateless主项目类似的过程,仅仅需要修改目标子项目的位置,使它显示在主项目的目录中(类似于在父类别中执行mvn create:archetype命令)。& amp; amp; amp; amp; amp; amp; amp; amp; amp; lt; /p>

选择以下项目设置:

  • Project Name: ejb3-remove-stateless-ejb3
  • Project Location: C:\ejb3-remove-stateless
  • Group Id: pl.jaceklaskowski.javaee
  • Version: 1.0
  • Package: pl.jaceklaskowski.javaee


单击 Finish完成项目创建。

成功创建项目后,由于对模块ejb3-remove-stateless-ejb3进行了注册,父项目的pom.xml文件将被修改。

<modules>

<module>ejb3-remove-stateless-ejb3</module>
</modules>

同父项目的处理相同,我们将删除 junit-3.8.1测试库。我们还将删除用于单个测试的 Test Packages库(方法为选择 Files 选项卡,展开 ejb3-remove-stateless-ejb3 (jar) > src 文件夹并删除以感叹号标记的 test目录)。

我们将对项目进行配置,方法为:将 Packaging改为 ejb。右键单击鼠标,选择 Properties菜单并在对话框中将 Packaging字段的值由 jar改为 ejb


单击 OK确认修改。

删除 pl.jaceklaskowski.javaee.App类别(从 Source Packages部分)。最后,对项目进行配置,使它包含EJB 3.0 bean。要进行修改必须直接编辑pom.xml文件。我们将在文件配置中添加 maven-ejb-plugin

<plugin>

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<ejbVersion>3.0</ejbVersion>
</configuration>
</plugin>

pom.xml文件修改完毕后,将看到以下内容:

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

<project>
<parent>
<artifactId>ejb3-remove-stateless</artifactId>
<groupId>pl.jaceklaskowski.javaee</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>pl.jaceklaskowski.javaee</groupId>
<artifactId>ejb3-remove-stateless-ejb3</artifactId>
<name>ejb3-remove-stateless-ejb3</name>
<packaging>ejb</packaging>
<version>1.0</version>
<url>http://www.JacekLaskowski.pl</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<ejbVersion>3.0</ejbVersion>
</configuration>
</plugin>
</plugins>
</build>
</project>

创建子项目——ejb3-remove-stateless-client

我们将创建 ejb3-remove-stateless-client项目,方法与前一个子项目的创建方式相同。但是 Project Location 必须为 ejb3-remove-stateless 父项目目录。

选择以下项目设置

  • Project Name: ejb3-remove-stateless-client
  • Project Location: C:\ejb3-remove-stateless
  • Group Id: pl.jaceklaskowski.javaee
  • Version: 1.0
  • Package: pl.jaceklaskowski.javaee


删除 junit-3.8.1.jar 测试目录(测试库)、pl.jaceklaskowski.javee.App 类别(源代码包)以 及pl.jaceklaskowski.javaee.AppTest测试包,此时,我们已完成了项目的准备阶段。

完整的项目结构

项目结构如下所示:

创建EJB bean - Removable

声明EJB 3.0库的依赖关系

创建EJB bean的第一步是定义项目依赖关系。

我们将添加EJB 3.0库,org.apache.geronimo.specs:geronimo-ejb_3.0_spec:1.0.

远程业务接口——RemovableRemote

我们将在 ejb3-remove-stateless-ejb3 项目中创建远程业务接口RemovableRemote ( 类别pl.jaceklaskowski.javaee.RemovableRemote)。

package pl.jaceklaskowski.javaee;


import javax.ejb.Remote;

@Remote
public interface RemovableRemote {
public void remove(String message);
}

Bean类型——RemovableBean

我们将通过实现RemovableRemote业务接口创建bean类型RemovableBean(类别pl.jaceklaskowski.javaee.RemovableBean)。

package pl.jaceklaskowski.javaee;


import javax.ejb.Stateless;

@Stateless(mappedName="Removable")
public class RemovableBean implements RemovableRemote {
public void remove(String msg) {
System.out.println(msg);
}
}

使用@Stateless annotation mappedName属性可以指定一些名称,然后使用这些名称可以通过远程客户机搜索EJB bean(有关更多信息,请参阅 How are Global JNDI names assigned to Session / Entity beans?)。

创建远程客户机——RemovableClient

根据GlassFish—— How do I access a Remote EJB from a stand-alone java client?中针对bean操作的远程访问说明,我们将创建RemovableClient 。

首先,我们将通过 Libraries > Add Library...定义子项目 ejb3-remove-stateless-ejb3(客户机将使用这个子项目类别)的依赖关系。

添加了依赖关系后,您将在本地库中看到一条错误消息,表示依赖关系是无效的。


(单击查看大图)

要解决这个问题,我们需要构建一个EJB bean——也就是Removable,构建 ejb3-remove-stateless-ejb3 项目,然后将库放入m2本地库中。构建方法为选择 ejb3-remove-stateless-ejb3 项目,右键单击鼠标并从下拉菜单中选择Build选项。

正确执行这个命令并重新加载 ejb3-remove-stateless-client客户机项目(菜单 Reload Project)将解决这一问题。

下一步是创建客户机类——pl.jaceklaskowski.javaee.RemovableClient。这一步非常的简单,因此不多做说明。客户机的简单性源于GlassFish库——a ppserv-rt.jar,其中包含了JNDI配置。我们还需注意如何使用EJB bean的名称—— Removable——它是通过@Stateless annotation mappedName属性在bean类别中定义的。

package pl.jaceklaskowski.javaee;


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

public class RemovableClient {
public static void main(String[] args) throws Exception {
Context ctx = new InitialContext();
RemovableRemote removable = (RemovableRemote) ctx.lookup("Removable");
removable.remove("Look at the server's log");
}
}

这时,我们需要添加项目依赖关系,即属于GlassFish服务器—— appserv-rt.jar的库以及 system中的 javaee.jar system(根据 System Dependencies)。通过变量glassfish.home查看安装GlassFish的文件系统的依赖关系,默认位置为 c:/apps/glassfish

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

<project>
<parent>
<artifactId>ejb3-remove-stateless</artifactId>
<groupId>pl.jaceklaskowski.javaee</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>pl.jaceklaskowski.javaee</groupId>
<artifactId>ejb3-remove-stateless-client</artifactId>
<name>ejb3-remove-stateless-client</name>
<version>1.0</version>
<properties>
<glassfish.home>c:/apps/glassfish</glassfish.home>
</properties>
<dependencies>
<dependency>
<groupId>glassfish</groupId>
<artifactId>appserv-rt.jar</artifactId>
<version>LATEST</version>
<scope>system</scope>
<systemPath>${glassfish.home}/lib/appserv-rt.jar</systemPath>
</dependency>
<dependency>
<groupId>glassfish</groupId>
<artifactId>javaee.jar</artifactId>
<version>LATEST</version>
<scope>system</scope>
<systemPath>${glassfish.home}/lib/javaee.jar</systemPath>
</dependency>
<dependency>
<groupId>pl.jaceklaskowski.javaee</groupId>
<artifactId>ejb3-remove-stateless-ejb3</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>none</include>
</includes>
</configuration>
<executions>
<execution>
<id>run RemovableClientTest</id>
<phase>integration-test</phase>
<configuration>
<includes>
<include>**/RemovableClientTest.java</include>
</includes>
</configuration>
<goals>
<goal>test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

模块配置的一个有趣的部分是 maven-surefire-plugin的配置,默认情况下它只执行符合 none模式的测试,以这种方式进行配置(在本例中 none模式意味着不会执行任何测试,因为所有测试都不符合模式,但是执行单个的 RemovableClientTest会更加准确),并且只在完成集成测试阶段期间执行。

不管客户机类的可访问性如何,我们将从m2级别执行自动启动,此过程需要借助一个测试——RemovableClientTest( pl.jaceklaskowski.javaee.RemovableClientTest 类别),该测试是通过 Test Packages文件夹构建的。

package pl.jaceklaskowski.javaee;


import javax.naming.Context;
import javax.naming.InitialContext;
import org.junit.Test;

public class RemovableClientTest {

@Test
public void runRemoteClient() throws Exception {
Context ctx = new InitialContext();
RemovableRemote removable = (RemovableRemote) ctx.lookup("Removable");
removable.remove("Look at the server's log");
}
}

这种类型的测试在默认情况下不会启动(请参考pom.xml文件中的maven-surefire-plugin配置),因为在启动测试之前,需要在GlassFish应用服务器上先启动bean( 如果修改了测试实现方式,则不能够创建项目并且也不能在服务器上安装bean)。

启动

要启动项目,首先要在GlassFish服务器上安装 Removable bean ,然后启动 RemovableClientTest

GlassFish服务器启动

在安装bean之前,我们先要使用asadmin start-domain命令启动GlassFish(之前已定义了变量PATH以包含GlassFish bin 目录)。

$ asadmin.bat start-domain domain1

Starting Domain domain1, please wait.
Log redirected to c:\apps\glassfish\domains\domain1\logs\server.log.
Redirecting output to C:/apps/glassfish/domains/domain1/logs/server.log
Domain domain1 is ready to receive client requests. Additional services are being started in background.
Domain [domain1] is running [Sun Java System Application Server 9.1 (build b58d-fcs)]
with its configuration and logs at: [c:\apps\glassfish\domains].
Admin Console is available at [http://localhost:4848].
Use the same port [4848] for "asadmin" commands.
User web applications are available at these URLs:
[http://localhost:8080 https://localhost:8181 ].
Following web-contexts are available:
[/web1 /__wstx-services ].
Standard JMX Clients (like JConsole) can connect to JMXServiceURL:
[service:jmx:rmi:///jndi/rmi://dev:8686/jmxrmi] for domain management purposes.
Domain listens on at least following ports for connections:
[8080 8181 4848 3700 3820 3920 8686 ].
Domain does not support application server clusters and other standalone instances.

安装EJB bean——Removable

在创建之前,先要安装bean 。然而,在定义客户机依赖关系( ejb3-remove-stateless-client 项目)的过程中实际已经完成了这一步骤。在 ejb3-remove-stateless-ejb3项目target 目录,存在一个ejb3-remove-stateless-ejb3-1.0.jar文件。这 是一个bean分配文件。我们将使用asadmin deploy 命令安装该文件。

$ asadmin.bat deploy --user admin
ejb3-remove-stateless-ejb3/target/ejb3-remove-stateless-ejb3-1.0.jar

Command deploy executed successfully.

在服务器的管理控制台(默认情况下通过地址 http://localhost:4848访问),我 们将查看EJB Removable bean是否已经正确安装。


远程客户机启动——RemovableClient

首先,我们将构建完整的ejb3-remove-stateless项目,方法为从菜单中选择 Build选项。

成功启动命令后,您将看到以下通知内容:

...

------------------------------------------------------------------------
Reactor Summary:
------------------------------------------------------------------------
ejb3-remove-stateless ................................. SUCCESS [1.500s]
ejb3-remove-stateless-ejb3 ............................ SUCCESS [0.610s]
ejb3-remove-stateless-client .......................... SUCCESS [0.921s]
------------------------------------------------------------------------
------------------------------------------------------------------------
BUILD SUCCESSFUL
------------------------------------------------------------------------
...

当然,选择 Build选项即可执行在m2中的 安装 步骤,同时也宣告 集成测试阶段的完成,本文的测试也告一段落。

使用mvn integration-test 命令即可立即启动客户机,在本文的例子中使用NetBeans IDE 6.0作为图形工具来启动m2命令——即选择 ejb3-remove-stateless-client 项目,右键单击鼠标并从菜单中选择 Custom > Goals...选项

可通过 Build Lifecycle Phases页面获得m2阶段列表。

接下来我们将执行集成测试阶段。

成功启动测试后,您将在NetBeans IDE看到如下所示的内容:

...

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running pl.jaceklaskowski.javaee.RemovableClientTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.203 sec
Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
------------------------------------------------------------------------
BUILD SUCCESSFUL
------------------------------------------------------------------------
...

同时将在事件的GlassFish日志(GlassFisha主目录的 domains/domain1/logs/server.log文件)中看到如下内容

[#|2007-09-03T22:41:59.750+0200|INFO|sun-appserver9.1|javax.enterprise.system.stream.out|_ThreadID=16;_ThreadName=p:

thread-pool-1; w: 8;|
Look at the server's log|#]

尽管已经成功启动了远程服务器,但并不表示解决方案已经完成。还需要启动测试来安装bean。如果在安装之前尝试执行
Build选项,则会收到一条错误消息。欢迎提出改进建议。接下来的文章将介绍Apache OpenEJB 3.0-SNAPSHOT服务器。