vlambda博客
学习文章列表

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

Chapter 1. Getting Started with EJB 3.x

EJB 3.x 规范的目标 是通过改进 EJB 架构来简化其开发。这种简化是通过提供元数据注释来替换 XML 配置来实现的。它还通过使实体和会话 bean POJOs (Plain Old Java Objects ) 并让组件和 home 接口变得多余。 EJB 2.x 实体 bean 被 EJB 3.x 实体取代。 EJB 3.0 还引入了 Java Persistence APIJPA)<一个 id="id2" class="indexterm"> 用于 Java 对象的对象关系映射。

WildFly 8.x 支持 EJB 3.2 和 Java EE 7 的 JPA 2.1 规范。虽然支持 EJB 3.2,但本章中的示例应用程序没有使用 EJB 3.2 的新特性(例如新的 TimerService API 和禁用有状态会话 bean 的钝化)。示例应用程序基于 Java EE 6 和 EJB 3.1。还讨论了 EJB 3.x 与 Java EE 7 的配置,并且可以使用或修改示例应用程序以在 Java EE 7 项目上运行。我们使用了 Hibernate 4.3 持久性提供程序。与其他一些持久性提供程序不同,Hibernate 持久性提供程序支持自动生成关系数据库表,包括表的连接。

在本章中,我们将创建一个 EJB 3.x 项目,并使用 Maven 构建并部署该项目到 WildFly 8.1。本章包含以下部分:

  • 设置环境

  • 创建 WildFly 运行时

  • 创建 Java EE 项目

  • 使用 MySQL 数据库配置数据源

  • 创建实体

  • 创建 JPA 持久性配置文件

  • 创建会话 Bean 外观

  • 创建 JSP 客户端

  • 配置 jboss-ejb3-ejb 子项目

  • 配置 jboss-ejb3-web 子项目

  • 配置 jboss-ejb3-ear 子项目

  • 部署 EAR 模块

  • 运行 JSP 客户端

  • 配置 Java EE 7 Maven 项目

Setting up the Environment


我们需要下载并安装以下软件:

设置环境变量:JAVA_HOMEJBOSS_HOMEMAVEN_HOMEMYSQL_HOME。添加 %JAVA_HOME%/bin, %MAVEN_HOME%/bin, %JBOSS_HOME%/bin %MYSQL_HOME%/binPATH 环境变量。使用的环境设置是 C:\wildfly-8.1.0.Final for JBOSS_HOME, C:\Program Files\MySQL\MySQL Server 5.6.21 for MYSQL_HOME, C:\maven\apache-maven-3.0 .5 用于 MAVEN_HOMEC:\Program Files\Java\jdk1.7.0_51 用于 JAVA_HOME。从 %JBOSS_HOME%/bin 目录运行 add-user.bat 脚本,为 WildFly 管理员控制台创建用户。当提示您希望添加什么类型的用户?时,选择a) 管理用户 。另一个选项是 b) 应用程序用户

管理用户用于登录管理控制台,并且Application User 用于访问应用程序。随后,为新用户指定 UsernamePassword。当提示问题时,此用户是否将用于一个 AS 进程以连接到另一个 AS..?,输入答案为 <代码类="literal">无。安装和配置MySQL数据库时,为root用户指定密码(密码mysql在示例应用程序中)。

Creating a WildFly runtime


由于 应用程序是在WildFly 8.1 上运行的,我们需要在Eclipse 中为WildFly 8.1 创建一个运行时环境。选择窗口 | Eclipse 中的首选项。在首选项中,选择服务器 |运行环境。单击添加按钮以添加新的运行时环境,如以下屏幕截图所示:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

New Server Runtime Environment 中,选择 JBoss Community | WildFly 8.x 运行时。点击下一步

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

WildFly Application Server 8.x 中, 出现在 新建服务器运行时环境,为新运行时指定名称或选择默认名称,即WildFly 8.x Runtime< /代码>。使用浏览按钮选择 WildFly 8.x 服务器的主目录。主目录是安装 WildFly 8.1 的目录。默认路径为 C:\wildfly-8.1.0.Final 用于本章和 后续章节。选择 Runtime JRE 作为 JavaSE-1.7。如果 JDK 位置未添加到运行时列表,请首先从 Eclipse 的 JRE 首选项屏幕中添加它。在 Configuration base directory 中,选择 standalone 作为默认设置。在配置文件中,选择 standalone.xml 作为默认设置。点击完成:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

为 WildFly 8.x Runtime 创建了一个新的服务器运行时环境,如以下 屏幕截图所示。点击确定

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

为 WildFly 8.x 创建 Server Runtime Environment 不是在 Eclipse 中创建 Java EE 项目的先决条件。在下一节中,我们将为 EJB 3.x 应用程序创建一个新的 Java EE 项目。

Creating a Java EE project


JBoss Tools 为不同类型的 JBoss 项目提供 项目模板。在本节中,我们将为 EJB 3.x 应用程序创建一个 Java EE 项目。选择文件| | Other 在 Eclipse IDE 中。在 New 向导中,选择 JBoss Central | Java EE EAR 项目 向导。点击 下一步 按钮:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

Java EE EAR 项目 向导启动。默认情况下,会创建一个 Java EE 6 项目。 Java EE EAR 项目是一个 Maven 项目。 New Project Example 窗口列出需求并运行需求测试。 JBoss AS 运行时是必需的,Java EE 项目需要一些插件(包括 JBoss Maven 工具插件)。选择Target RuntimeWildFly 8.x Runtime,在 前面的部分。然后,选中 创建空白项目 复选框。点击 下一步 按钮:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

指定项目名称jboss-ejb3, 打包成org.jboss.ejb3,并勾选Use default Workspace location 框。点击 下一步 按钮:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

指定 Group Id 为 org.jboss.ejb3,Artifact Id 为 jboss-ejb3,版本为 1.0.0,Package 为 org.jboss.ejb3.model。点击完成:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

一个 Java EE 项目 被创建,如以下 Project Explorer 窗口所示。删除 jboss-ejb3/jboss-ejb3-ear/src/main/application/META-INF/jboss-ejb3-ds.xml 配置文件。 jboss-ejb3 项目由三个子项目组成:jboss-ejb3-earjboss-ejb3-ejbjboss-ejb3-web。每个子项目都包含一个用于 Maven 的 pom.xml 文件。最初,子项目用红色错误标记指示错误,但在本章稍后构建主项目时,这些将得到修复。最初,子项目可能会用红色错误标记指示错误,但是当本章稍后构建主项目时,这些会得到修复。我们将在后面的部分中使用 MySQL 数据库配置数据源。 jboss-ejb3-ejb 子项目由 JPA 数据库持久性配置的 src/main/resources 源文件夹中的 META-INF/persistence.xml 文件组成。

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

我们将使用 MySQL 作为 EJB 应用程序的数据数据库。在下一节中,我们将在 MySQL 数据库中创建一个数据源。

Configuring a data source with MySQL database


WildFly 8.1 中的默认数据源配置了H2 数据库引擎。数据库有几个可用的选项。 最常用的四个关系数据库是Oracle数据库、MySQL数据库、SQL Server和PostgreSQL Server。 Oracle 数据库和 SQL Server 是为企业级应用程序设计的,不是开源的。 Oracle 数据库提供了更多功能以方便系统和数据维护。与 SQL Server 相比,它还提供了防止系统和数据故障的功能。 MySQL 和 PostgreSQL 是具有类似功能的开源数据库,主要为小型应用程序设计。我们将使用 MySQL 数据库。选择 MySQL 的一些原因在 http://www.mysql.com/why-mysql/topreasons.html

我们将使用 MySQL 数据库配置数据源,以便在 EJB 3.x 应用程序中用于对象/关系映射。使用以下步骤配置数据源:

  1. 首先,我们需要为 MySQL 数据库创建一个模块。对于MySQL模块,在%JBOSS_HOME%/modules/mysql/main目录下创建module.xml文件; mysql/main 子目录也将被创建。 module.xml 文件在以下代码片段中列出:

    <module xmlns="urn:jboss:module:1.1" name="mysql" slot="main">
      <resources>  
        <resource-root path="mysql-connector-java-5.1.33-bin.jar"/>
      </resources>
      <dependencies>
        <module name="javax.api"/>
      </dependencies>
    </module>
  2. C:\Program Files (x86) 复制 mysql-connector-java-5.1.33-bin.jar (MySQL JDBC JAR) 文件\MySQL\Connector.J 5.1%JBOSS_HOME%/modules/mysql/main 目录。 module.xml中指定的MySQL mysql-connector-java JAR文件版本必须与JAR文件版本一致复制到 /modules/mysql/main 目录。

  3. 将 MySQL 数据库的 定义添加到 元素和 <driver/> 定义到 %JBOSS_HOME 中的 <drivers/> 元素 文件"literal"></subsystem> 元素。 <password/>配置标签中的 <password/>标签是MySQL数据库时配置的密码已安装。 MySQL驱动的数据源类是一个 XA数据源,用于分布式事务:

    <subsystem xmlns="urn:jboss:domain:datasources:2.0">
      <datasources>
        <datasource jndi-name="java:jboss/datasources/MySQLDS" pool-name="MySQLDS" enabled="true" use-java-context="true">
          <connection-url>jdbc:mysql://localhost:3306/test</connection-url>
          <driver>mysql</driver>
          <pool>
            <min-pool-size>10</min-pool-size>
            <max-pool-size>20</max-pool-size>
            <prefill>true</prefill>
          </pool>
          <security>
            <user-name>root</user-name>
            <password>mysql</password>
          </security>
        </datasource>
        <drivers>
          <driver name="mysql" module="mysql">
            <driver-class>com.mysql.jdbc.Driver</driver-class>
            <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
          </driver>
        </drivers>
      </datasources>
    </subsystem>
  4. 如果服务器正在运行修改standalone.xml配置文件后,重启WildFly 8.x 服务器。 MySQL 数据源已部署。要启动或重新启动 WildFly 服务器,请双击 C:\wildfly-8.1.0.Final\bin\standalone 批处理文件。

  5. 使用 URL 登录 WildFly 8 管理控制台:http://localhost:8080。点击Administration Console,如下图所示:

    读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门
  6. 登录对话框中,指定使用 add-user.bat 脚本添加的用户的用户名和密码。

  7. 在管理控制台中选择 Runtime 选项卡。 MySQL 数据源在 Datasources Subsystems 中列出,如以下屏幕截图所示。点击测试连接测试连接:

    读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门
  8. 如果与 MySQL 数据库 建立了连接,则成功创建 JDBC 连接 将显示消息:

    读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

在下一个 部分,我们将为 EJB 3.x 应用程序创建实体 .

Creating entities


在 EJB 3.x 中, 实体是 POJO (Plain Old Java Object) 表示数据库表行的持久域对象。由于实体是 Java 类,所以在 jboss-ejb3 项目的 jboss-ejb3-ejb 子项目中创建一个 Java 类。选择文件 | 。在 New 窗口中,选择 Java | Class 并点击下一步

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

选择/指定 jboss-ejb3/jboss-ejb3-ejb/src/main/java 作为 Java 来源 文件夹org .jboss.ejb3.model 作为 PackageCatalog 作为类名称。点击完成

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

同样,为 Edition.java, Section 添加 Java 类。 java,以及Article.java实体,如下图Project Explorer

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

接下来,我们开发 EJB 3.x 实体。 EJB 实体需要 JPA 持久性提供程序,我们将使用 Hibernate 持久性提供程序。 Hibernate 持久化提供程序有一些特性需要提及,如下所示:

  • 如果一个实体有多个以下类型的非惰性关联,Hibernate 将无法获取该实体:

    • 使用 @org.hibernate.annotations.CollectionOfElements 注释的 java.util.List, java.util.Collection 属性

    • 未使用 @org.hibernate.annotations.IndexColumn 注释的 @OneToMany@ManyToMany 关联

    • 标记为 mappedBy 的关联不得定义数据库映射(例如 @JoinTable 或 @JoinColumn)

我们将开发 Catalog、Edition、Section 和 Article 类,Catalog 和 Edition 类、Edition 和 Section 类、Section 和 Article 类之间存在一对多的关系,如下面的 UML 类图所示:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

使用@Entity 注释和@Table 注释来注释目录实体类。如果不使用@Table注解,则默认使用实体名作为表名。在@Table 注释中,将表名称指定为 CATALOG 和 uniqueConstraints,使用 id 列的 @UniqueConstraint 注释。将命名查询指定为 findCatalogAll,它将选择所有 Catalog 和 findCatalogByJournal 实体。这会使用 @NamedQueries 和 @NamedQuery 注释按 Journal 选择 Catalog 实体:

@Entity
@Table(name = "CATALOG", uniqueConstraints = @UniqueConstraint(columnNames = "ID"))
@NamedQueries({
  @NamedQuery(name="findCatalogAll", query="SELECT c FROM Catalog c"),
  @NamedQuery(name="findCatalogByJournal", 
    query="SELECT c FROM Catalog c WHERE c.journal = :journal")
})
public class Catalog implements Serializable {
}

指定实体类中需要的 no-argument 构造函数。 Catalog 实体类实现了 Serializable 接口,以便在持久化到数据库时将启用缓存的实体序列化到缓存中。要将版本号与序列化运行时的可序列化类相关联,请指定 serialVersionUID 变量。为 id 和日志 bean 属性以及 Set 的集合声明 String 变量类型,因为 Catalog 实体与 Edition 具有双向的一对多关联。由于前面提到的原因,该集合被选为 Set。 Hibernate 不支持多个 java.util.List 类型的 EAGER 关联。为 bean 属性添加 get/ set 方法。 @Id 注释指定标识符属性。 @Column 注释指定与属性关联的列名。可空元素设置为 false,因为主键不能为 null

Note

如果我们使用 Oracle 数据库,我们将指定主键生成器为 sequence 类型,使用 @SequenceGenerator 注释。生成策略由 @GeneratedValue 注释指定。对于Oracle数据库,生成策略是strategy=GenerationType.SEQUENCE,但是由于MySQL数据库支持通过生成序列来自动递增主键列值,所以我们设置了生成GenerationType.AUTO 的策略。

使用 @Edition 的双向一对多关联文字">OneToMany 注释。 mappedBy 元素在关系的非拥有方指定,即 Catalog 实体。 cascade 元素设置为 ALL。级联用于将数据库表操作级联到关联表。 fetch 元素设置为 EAGER。使用 EAGER 获取关联实体,在检索到实体时立即获取集合:

// bi-directional many-to-one association to Edition
@OneToMany(mappedBy = "catalog", targetEntity=org.jboss.ejb3.model.Edition.class, cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
  public Set<Edition> getEditions() {
    return this.editions;
  }
}

如前所述,用 mappedBy 标记的关联不能指定@JoinTable 或@JoinColumn Edition 集合的 get 和 set 方法也被指定。 Catalog.java 实体类 可在 http://www.packtpub.com/support

接下来,为 EDITION 数据库表开发实体类:Edition.java。指定 @Entity, @Table, @Id , @Column@GeneratedValue 注释,如针对 Catalog 实体所讨论的。指定 findEditionAllfindEditionByEdition 命名查询以查找版本集合。为 idedition 指定 bean 属性和相关的 get/set 方法。此外,使用 Set 类型的集合指定与 Section 实体的一对多关联。 Catalog 关系的双向多对一关联是使用 @ManyToOne 注释指定的,并具有级联键入 PERSISTMERGEREFRESHEdition 实体是关系的拥有方。使用 @JoinTable 注释,在拥有方包含一个连接表以启动级联操作。连接列是使用 @JoinColumn 注释指定的。 Edition.java 实体类可在本章的代码下载中找到。

SECTION表开发实体类:Section.java。指定 findSectionAllfindSectionBySectionName 命名查询以查找 Section 实体。指定 idsectionname bean 属性。使用 @ManyToOne 注释和双向一对一指定与 Edition 的双向多对一关联- 使用 @OneToManyArticle 关联。 @JoinTable@JoinColumn 仅为 @ManyToOne 关联指定其中 Section 是拥有方。 Section.java 实体类可在本章的代码下载中找到。

ARTICLE表指定实体类:Article.java< /代码>。 Article 实体使用 @TABLE 映射到 ARTICLE 数据库表注解。添加 findArticleAllfindArticleByTitle 命名查询以查找 Article 实体。指定 idsectionname bean 属性以及关联的 get/set 方法。 Article 实体是与 Section 的双向多对一关联的拥有方。因此,指定了 @JoinTable@JoinColumnArticle.java 类在本章下载的代码中可用。

Creating a JPA persistence configuration file


ejb 中的 META-INF/persistence.xml 配置文件jboss-ejb3-ejb 子项目中的 /src/main/resources 文件夹是在我们创建 Java EE 项目时创建的。 persistence.xml 指定用于将对象/关系实体映射到数据库的持久性提供程序。指定持久性单元使用 persistence-unit 元素。将 transaction-type 设置为 JTA(默认值)。将持久性提供程序指定为 Hibernate 持久性提供程序:org.hibernate.ejb.HibernatePersistence。将 jta-data-source 元素值设置为我们之前创建的 java:jboss/datasources/MySQLDS 数据源。使用 class 元素指定实体类。使用 hibernate.hbm2ddl.auto 属性将 DDL 生成策略设置为 create-drop,该属性会自动验证或导出 DDL当创建 SessionFactory 类时,数据库的架构。使用 create-drop 策略,在 SessionFactory 关闭时创建和删除所需的表。 hibernate.show_sql 属性设置为 false。将其设置为 true 意味着所有 SQL 语句都是输出,这是一种替代的调试方法。 hibernate.dialect 属性设置为 MySQL 数据库的 org.hibernate.dialect.MySQLDialect。其他 Hibernate 属性 (http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/session-configuration.html) 也可以根据需要指定。 persistence.xml 配置文件在以下代码中列出:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation=" http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
  <persistence-unit name="em" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <!-- If you are running in a production environment, add a managed data source, the example data source is just for development and testing! -->
    <jta-data-source>java:jboss/datasources/MySQLDS</jta-data-source>
    <class>org.jboss.ejb3.model.Article</class>
    <class>org.jboss.ejb3.model.Catalog</class>
    <class>org.jboss.ejb3.model.Edition</class>
    <class>org.jboss.ejb3.model.Section</class>
    <properties>
      <!-- Properties for Hibernate -->
      <property name="hibernate.hbm2ddl.auto" value="create-drop" />
      <property name="hibernate.show_sql" value="false" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
    </properties>
  </persistence-unit>
</persistence>

JPA 规范 不强制持久性提供程序创建具有 hibernate.hbm2ddl.auto 属性集的表create-dropcreate。 Hibernate 持久性提供程序支持创建表。除了实体表之外,Hibernate 持久性提供程序还创建了一些附加表(例如连接表和序列表)。

Creating a session bean facade


开发实体以分离关注点和可维护代码并因此获得更好性能的 最佳实践之一是将实体包装在会话 bean 外观中。使用 Session Facade,需要更少的远程方法调用,并创建一个外部事务上下文,每个 get 方法调用不会启动一个新事务。会话外观是 Java EE 设计模式的核心之一(http://www.oracle.com/technetwork/java/sessionfacade-141285.html)。在 org.jboss.ejb3.model 包中创建一个 CatalogSessionBeanFacade 会话 bean 类,如以下屏幕截图所示。 Session Facade 类也可以在不同的包中创建(例如 org.jboss.ejb3.view):

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

会话 bean 类使用 @Stateless 注释进行注释:

@Stateless
public class CatalogSessionBeanFacade {}

在 bean 会话中,我们使用 EntityManager 来创建、删除、查找和查询持久化实体实例.使用 @PersistenceContext 注释注入 EntityManager。将 unitName 指定为 persistence.xml 中配置的 unitName。接下来,指定 getAllEditionsgetAllSectionsgetAllArticlesgetAllCatalogs 获取获取实体集合的方法。 get 方法使用实体中指定的命名查询获取所有实体的集合。 EntityManagercreateNamedQuery 方法用于从一个命名查询。将TransactionAttribute注解的TransactionAttributeType枚举指定为REQUIRES_NEW,这样做的好处是如果由于调用会话 bean 的不同事务上下文中的错误而回滚事务,则它不会影响会话 bean。

为了演示实体的使用,使用会话 bean 中的 createTestData 便捷方法创建测试数据。或者,也可以使用单元测试或扩展类。创建一个 Catalog 实体并使用 setJournal 方法设置日志。我们没有为 Catalog 实体设置 id,因为我们为 GenerationType.AUTO 生成策略文字">ID 列。使用 EntityManager 对象的 persist 方法持久化实体。但是,persist 方法不会将实体 持久保存到数据库中。它仅使实体实例受管理并将其添加到持久性上下文中。 EntityManager.flush() 方法不需要被调用来将实体与数据库同步,因为 EntityManager 配置了 < code class="literal">FlushModeType 为 AUTO (另一个设置是 COMMIT)并且刷新将是调用 EntityManager.persist() 时自动完成:

Catalog catalog1 = new Catalog();
catalog1.setJournal("Oracle Magazine");
em.persist(catalog1);

同样,创建并持久化一个 Edition 实体对象。添加 Catalog 对象:catalog1 使用 setCatalog 方法class="literal">Edition 实体类:

Edition edition = new Edition();
edition.setEdition("January/February 2009");
edition.setCatalog(catalog1);
em.persist(edition);

同样添加 SectionArticle 实体实例。添加另一个 Catalog 对象,但没有任何关联的 EditionSectionArticle 实体:

Catalog catalog2 = new Catalog();
catalog2.setJournal("Linux Magazine");
em.persist(catalog2);

接下来,我们将使用 deleteSomeData 方法删除数据,其中我们首先使用命名查询 Query 对象"literal">findCatalogByJournal。使用 Query 对象的 setParameter 方法指定要删除的日志。使用 Query 对象的 getResultList 方法获取 List 结果。迭代 List 结果并使用 remove 方法删除 Catalog 对象EntityManager 对象。 remove 方法只从持久化上下文中移除 Catalog 对象:

public void deleteSomeData() {
  // remove a catalog
  Query q = em.createNamedQuery("findCatalogByJournal");
  //q.setParameter("journal", "Linux Magazine");
  q.setParameter("journal", "Oracle Magazine");
  List<Catalog> catalogs = q.getResultList();
  for (Catalog catalog : catalogs) {
    em.remove(catalog);
  }
}

CatalogSessionBeanFacade 会话 bean 类在本章下载的代码中可用。

Creating a JSP client


接下来,我们将创建一个JSP 客户端来测试EJB 实体。我们将使用本地 JNDI 名称查找会话 bean。随后,我们将调用会话 bean 的 testData 方法来使用这些实体测试数据库持久性。首先创建一个JSP 文件。选择文件 | | Other,然后在 New 向导中,选择 网络 | JSP File 并点击下一步,如下图所示:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

New JSP File 向导中,选择 jboss-ejb3/web/src/main/webapp jboss-ejb3-web 子项目中的 文件夹。将 catalog.jsp 指定为 文件名并点击下一步。然后点击完成

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

catalog.jsp 文件被添加到 jboss-ejb3-web 子项目中:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

我们需要从 JSP 客户端 检索 CatalogSessionBeanFacade 组件。 WildFly 8 提供本地 JNDI (Java 命名和目录接口)命名空间:Java 和 以下 JNDI 上下文:

JNDI 上下文

描述

java:comp

这是作用于当前组件 EJB 的命名空间。

java:module

此命名空间的范围为当前模块。

java:app

此命名空间的范围仅限于当前应用程序。

java:global

此名称空间的范围仅限于应用程序服务器。

jboss-ejb3 应用程序被部署时,命名空间中的 JNDI 绑定(在上表中讨论)被创建,如服务器消息所示:

JNDI bindings for session bean named CatalogSessionBeanFacade in deployment unit subdeployment "jboss-ejb3-ejb.jar" of deployment "jboss-ejb3-ear.ear" are as follows:
  java:global/jboss-ejb3-ear/jboss-ejb3-ejb/CatalogSessionBeanFacade!org.jboss.ejb3.model.CatalogSessionBeanFacade
  java:app/jboss-ejb3-ejb/CatalogSessionBeanFacade!org.jboss.ejb3.model.CatalogSessionBeanFacade
  java:module/CatalogSessionBeanFacade!org.jboss.ejb3.model. CatalogSession
BeanFacade
  java:global/jboss-ejb3-ear/jboss-ejb3-ejb/CatalogSessionBeanFacade
  java:app/jboss-ejb3-ejb/CatalogSessionBeanFacade
  java:module/CatalogSessionBeanFacade

接下来我们将使用标准的Java SE JNDI API检索会话bean外观:CatalogSessionBeanFacade,它没有需要任何其他配置,使用 java:app 命名空间中的本地 JNDI 查找。对于本地 JNDI 查找,我们需要创建一个 InitialContext 对象:

Context context = new InitialContext();

使用 java:app 命名空间中的本地 JNDI 名称查找,检索 CatalogSessionBeanFacade 组件:

CatalogSessionBeanFacade bean = (CatalogSessionBeanFacade) context .lookup("java:app/jboss-ejb3-ejb/CatalogSessionBeanFacade!org.jboss.ejb3.model.CatalogSessionBeanFacade");

调用 createTestData 方法并检索 List Catalog 实体。遍历 Catalog 实体并将目录 ID 作为期刊名称输出:

bean.createTestData();
List<Catalog> catalogs = beanRemote.getAllCatalogs();
out.println("<br/>" + "List of Catalogs" + "<br/>");
for (Catalog catalog : catalogs) {
  out.println("Catalog Id:");
  out.println("<br/>" + catalog.getId() + "<br/>");
  out.println("Catalog Journal:");
  out.println(catalog.getJournal() + "<br/>");
}

同理,获取EntitySectionArticle实体并输出实体属性值。 catalog.jsp 文件可在为本章下载的代码中找到。

Configuring the jboss-ejb3-ejb subproject


我们将使用Maven项目生成一个EAR文件:jboss-ejb3,其中包括jboss-ejb3-ejbjboss-ejb-webjboss-ejb3-ear子项目/工件。我们将使用 Maven 构建工具来编译、打包和部署 EAR 应用程序。部署到 WildFly 的 jboss-ejb3-ear 模块有两个子模块:jboss-ejb3-webjboss-ejb3-ejb

jboss-ejb3-earjboss-ejb3-webjboss-ejb3-ejb 模块可以称为 earwebejb 模块分别。 ear 模块依赖于 web 模块和 web 模块对ejb模块有依赖,如下图所示:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

ejbwebear 模块可以单独构建和安装使用子项目特定的 pom.xml,或者这些可以使用 pom.xml 文件一起构建"literal">jboss-ejb3 项目。如果单独构建,则必须在 web 模块之前构建和安装 ejb 模块,如 web 模块依赖于 ejb 模块。 ear 模块将在 webejb 模块之后构建已建成并安装。我们将使用 jboss-ejb3 项目中的 pom.xml 文件来构建和安装顶级项目,该文件具有指定的依赖项在 jboss-ejb3-webjboss-ejb3-ejb 工件上。 jboss-ejb3-ejb 子项目的 pom.xml 文件将打包指定为 ejb< /代码>。 WildFly 8.x 提供了 EJB 3.x 应用程序所需的大部分 API。提供的 API 在 pom.xml 中指定为 providedscope . EJB 3.1 API 和 JPA 2.0 API 的依赖关系是预先指定的。为 Hibernate Annotations API 添加以下依赖项:

<dependency>
  <groupId>org.jboss.spec.javax.ejb</groupId>
  <artifactId>jboss-ejb-api_3.1_spec</artifactId>
  <version>1.0.0.Final</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.hibernate.javax.persistence</groupId>
  <artifactId>hibernate-jpa-2.0-api</artifactId>
  <version>1.0.0.Final</version>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-annotations</artifactId>
  <version>3.5.6-Final</version>
</dependency>

Hibernate Validator API 依赖项也在 pom.xml 中进行了预配置。该构建预配置了 Maven EJB 插件,这是将子项目打包成 EJB 模块所必需的。 Maven EJB 插件中的 EJB 版本是 3.1:

<build>
  <finalName>${project.artifactId}</finalName>
  <plugins>
    <plugin>
      <artifactId>maven-ejb-plugin</artifactId>
      <version>${version.ejb.plugin}</version>
      <configuration>
        <!-- Tell Maven we are using EJB 3.1 -->
        <ejbVersion>3.1</ejbVersion>
      </configuration>
    </plugin>
  </plugins>
</build>

EJB 子项目的 Maven POM.xml 文件在本章下载的代码中可用。

Configuring the jboss-ejb3-web subproject


jboss-ejb3-web 子项目所需的大部分配置都是预先指定的。 jboss-ejb3-web 工件的打包设置为 war

<artifactId>jboss-ejb3-web</artifactId>
<packaging>war</packaging>
<name>jboss-ejb3 Web module</name>

子项目的 pom.xml 文件预先指定了大部分所需的依赖项。它还指定了对 jboss-ejb3-ejb 工件的依赖:

<dependency>
  <groupId>org.jboss.ejb3</groupId>
  <artifactId>jboss-ejb3-ejb</artifactId>
  <type>ejb</type>
  <version>1.0.0</version>
  <scope>provided</scope>
</dependency>

provided 范围所示,EJB 3.1 API、JPA 2.0 API、JSF 2.1 API 和 JAX-RS 1.1 API 由 WildFly 8.x 服务器提供在 dependency 声明中。添加hibernate-annotations 工件的依赖。构建预配置了 Maven WAR 插件,这是将子项目打包成 WAR 文件所必需的:

<?xml version="1.0" encoding="UTF-8"?>
<build>
  <finalName>${project.artifactId}</finalName>
  <plugins>
    <plugin>
      <artifactId>maven-war-plugin</artifactId>
      <version>${version.war.plugin}</version>
      <configuration>
        <!-- Java EE 6 doesn't require web.xml, Maven needs to catch up! -->
        <failOnMissingWebXml>false</failOnMissingWebXml>
      </configuration>
    </plugin>
  </plugins>
</build>

jboss-ejb3-web 子项目的 pom.xml 文件在本章下载的代码中可用。

Configuring the jboss-ejb3-ear subproject


pom.xml 中,jboss-ejb3-ear 子项目,jboss-ejb3-ear 工件的打包指定为 ear

<artifactId>jboss-ejb3-ear</artifactId>
<packaging>ear</packaging>

pom.xml 文件指定了对 ejb 和 web 模块的依赖:

<dependencies>
  <!-- Depend on the ejb module and war so that we can package them -->
  <dependency>
  <groupId>org.jboss.ejb3</groupId>
  <artifactId>jboss-ejb3-web</artifactId>
  <version>1.0.0</version>
  <type>war</type>
</dependency>
  <dependency>
  <groupId>org.jboss.ejb3</groupId>
  <artifactId>jboss-ejb3-web</artifactId>
  <version>1.0.0</version>
  <type>war</type>
</dependency>
</dependencies>

pom.xml 文件 中的 build 标签指定 maven-ear-plugin 插件的配置,输出目录为 WildFly 8.x 独立服务器中的 deployments 目录.从 Maven 项目生成的 EAR 文件部署到 <outputDirectory/> 元素中指定的目录。将 <outputDirectory/> 元素指定为 C:\wildfly-8.1.0.Final\standalone\deployments 目录. outputDirectory 可能需要根据 WildFly 8.1 的安装目录进行修改。部署部署目录中的 EARWARJAR 模块如果服务器正在运行,则自动发送到 WildFly:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-ear-plugin</artifactId>
  <version>2.8</version>
  <configuration>
    <!-- Tell Maven we are using Java EE 6 -->
    <version>6</version>
    <!-- Use Java EE ear libraries as needed. Java EE ear libraries are in easy way to package any libraries needed in the ear, and automatically have any modules (EJB-JARs and WARs) use them -->
    <defaultLibBundleDir>lib</defaultLibBundleDir>
    <fileNameMapping>no-version</fileNameMapping>    
    <outputDirectory>C:\wildfly-8.1.0.Final\standalone\deployments</outputDirectory>
  </configuration>
</plugin>

Deploying the EAR module


在本节中,我们将构建应用程序 EAR 模块并将其部署到 WildFly 8.x 服务器。 jboss-ejb3 Maven 项目的 pom.xml 指定了三个模块: jboss-ejb3 -ejbjboss-ejb3-webjboss-ejb3-ear

<modules>
  <module>jboss-ejb3-ejb</module>
  <module>jboss-ejb3-web</module>
  <module>jboss-ejb3-ear</module>
</modules>

将 JBoss AS 版本指定为 8.1.0.Final

<version.jboss.as>8.1.0.Final</version.jboss.as>

jboss-ejb3pom.xml项目指定对 jboss-ejb3-webjboss-ejb3-ejb 工件的依赖:

<dependency>
  <groupId>org.jboss.ejb3</groupId>
  <artifactId>jboss-ejb3-ejb</artifactId>
  <version>${project.version}</version>
  <type>ejb</type>
</dependency>
<dependency>
  <groupId>org.jboss.ejb3</groupId>
  <artifactId>jboss-ejb3-web</artifactId>
  <version>${project.version}</version>
  <type>war</type>
  <scope>compile</scope>
</dependency>

接下来,我们将在服务器运行时构建 EAR 模块并将其部署到 WildFly 8.x。右键点击 jboss-ejb3 Maven 项目的 pom.xml 并选择 运行方式 | Maven 安装,如下图所示:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

正如 pom.xml 的输出 表示所有三个模块:ejbwebear 构建完成。 ear 模块被复制到 WildFly 8.x 中的 deployments 目录:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

启动 WildFly 8.x 服务器(如果尚未启动)。 jboss-ejb3.ear 文件被部署到 WildFly 8.x 服务器并且 jboss-ejb3-web 上下文被注册. jboss-ejb3.ear.deployed 文件在 deployments 目录中生成,如下图所示:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

EntityManager em 持久性单元被注册并生成 CatalogSessionBeanFacade 会话 bean 的 JNDI 绑定:

Starting Persistence Unit (phase 1 of 2) Service 'jboss-ejb3-ear.ear/jboss-e
jb3-ejb.jar#em'
12:30:32,047 INFO  [org.hibernate.jpa.internal.util.LogHelper] (ServerService Th
read Pool -- 50) HHH000204: Processing PersistenceUnitInfo [
  name: em
...]

实体的 MySQL 数据库表被创建,如以下屏幕截图所示:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

要登录 WildFly 8 管理控制台,请在任意 Web 中打开 http://localhost:8080浏览器。点击 管理控制台 链接。指定 用户名密码 并点击 登录。选择 运行时 标签。 jboss-ejb3.ear 应用程序被列为部署在 Deployments | 管理部署部分:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

Running the JSP client


接下来,打开 http://localhost:8080/jboss-ejb3-web/catalog.jsp 并运行 JSP 客户端。将显示 目录列表deleteSomeData 方法删除 Oracle Magazine目录。由于 Linux Magazine 目录没有任何数据,所以会显示空列表,如下图所示:

读书笔记《advanced-java-ee-development-with-wildfly》Ejb 3.x入门

Configuring a Java EE 7 Maven project


默认创建的 JBoss Java EE EAR 项目是一个 Java EE 6 项目。如果 Java EE 7 项目需要使用 EJB 3.2、Servlet 3.1、JSF 2.2 和 Hibernate JPA 2.1 API,则 pom.xml literal">ejb 模块和 web 模块子项目应包含 BOM (材料清单) 适用于 Java EE 7 和 Nexus 存储库:

<repositories>
  <repository>
    <id>JBoss Repository</id>
    <url>https://repository.jboss.org/nexus/content/groups/public/</url>
  </repository>
</repositories>
<dependencyManagement>
  <dependencies>
      <dependency>
        <groupId>org.jboss.spec</groupId>
        <artifactId>jboss-javaee-7.0</artifactId>
        <version>1.0.0.Final</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
  </dependencies>
</dependencyManagement>

中为 ejb 添加 pom.xml module 和 web 模块子项目应根据需要指定 EJB 3.2、JSF 2.2、Servlet 3.1 和 Hibernate JPA 2.1 规范的依赖关系,而不是 EJB 3.1 的依赖关系, JSF 2.1、Servlet 3.0 和 Hibernate JPA 2.0:

<dependency>
  <groupId>org.jboss.spec.javax.ejb</groupId>
  <artifactId>jboss-ejb-api_3.2_spec</artifactId>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.hibernate.javax.persistence</groupId>
  <artifactId>hibernate-jpa-2.1-api</artifactId>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.jboss.spec.javax.servlet</groupId>
  <artifactId>jboss-servlet-api_3.1_spec</artifactId>
  <scope>provided</scope>
</dependency>
<dependency>
  <groupId>org.jboss.spec.javax.faces</groupId>
  <artifactId>jboss-jsf-api_2.2_spec</artifactId>
  <scope>provided</scope>
</dependency>

Summary


在本章中,我们使用 Eclipse Luna 中的 JBoss Tools 插件 4.2 在 Eclipse IDE for Java EE Developers 中为 EJB 3.x 应用程序生成 Java EE 项目。我们创建实体来创建 Catalog 并使用 Hibernate 持久性提供程序将实体映射到 MySQL 5.6 数据库。随后,我们为实体创建了会话 bean 外观。在会话 bean 中,我们使用 EntityManager API 创建了一个目录。我们还创建了一个 JSP 客户端来使用本地 JNDI 查找调用会话 bean 外观,然后调用会话 bean 方法来显示数据库数据。我们使用 Maven 构建了 EJBWebEAR 模块和将 EAR 模块部署到 WildFly 8.1。我们在浏览器中运行 JSP 客户端以从 MySQL 数据库中获取和显示数据。在下一章中,我们将讨论另一种数据库持久化技术:Hibernate