第 3 章 移植您的应用程序

3.1. 多数应用程序要求的修改

3.1.1. 复查多数程序所要求的修改

JBoss EAP 6 里的类加载和配置修改将影响几乎所有的应用程序。JBoss EAP 6 也使用标准的可移植的 JNDI 语法。这些修改将影响多数程序,所以我们推荐您在移植应用程序前先复查下面的信息。

3.1.2. 类加载的修改

3.1.2.1. 根据类加载的变化更新应用程序

在 JBoss EAP 6 里,模块化类加载是一个明显的变化,它将影响几乎所有的程序。在移植应用程序之前,请先查看下面的信息。
  1. 首先,查看您的应用程序的软件包结构及其依赖关系。详情请参考 第 3.1.2.3 节 “根据类加载的修改更新应用程序的依赖关系”
  2. 如果您的应用程序使用了日志,您需要制定正确的模块依赖关系。请查看 第 3.1.4.1 节 “修改日志依赖关系” 里的相关细节。
  3. 由于模块化类加载的修改,您可能需要修改 EAR 或 WAR 的软件包结构。详情请参考 第 3.1.5.1 节 “修改 EAR 和 WAR 的打包”

3.1.2.2. 了解模块依赖关系

介绍

模块只能访问自己的类,以及它具有显性或隐性依赖关系的任何模块上的类。

过程 3.1. 了解模块依赖关系

  1. 了解隐性依赖关系

    服务器里的部署者隐性地自动添加一些常用的模块依赖关系,如javax.apisun.jdk。这使得类在运行时对于部署可见,并让开发人员不用显性地添加依赖关系。关于如何和何时添加这些隐性的依赖关系,请查看 https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/ 上的《JBoss EAP 6 开发指南》里的『类记载和模块』章节的『隐性模块依赖关系』
  2. 了解显性依赖关系

    对于其他类,模块必须显性地指定,否则缺失的依赖关系会导致部署或运行时错误。如果缺失了依赖关系,您可以在服务器日志里看到 ClassNotFoundExceptionsNoClassDefFoundErrors 跟踪信息。如果多于一个模块加载了相同的 JAR 或一个模块加载的类扩展了不同模块加载的类,您会在服务器日志里看到 ClassCastExceptions。要显性地制定依赖关系,请修改 MANIFEST.MF 或创建一个 JBoss 专有的部署描述符文件 jboss-deployment-structure.xml。关于模块依赖关系的更多信息,请查看 https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/《JBoss EAP 6 开发指南》里的『开发应用程序起步』章节的『类记载和模块概述』

3.1.2.3. 根据类加载的修改更新应用程序的依赖关系

介绍

JBoss EAP 6 里的类加载和以前版本的很不一样。类加载现在基于 JBoss Modules 项目。它不是一个加载所有 JAR 到普通 Class path 里的单一的、层级的类加载器,而是每个库都成为一个模块,链接它所依赖的模块。JBoss EAP 6 里的部署也是模块,它们不能访问应用服务器里 JAR 中定义的类,除非在这些类上显性地定义了依赖关系。应用服务器里定义的一些模块依赖关系是自动设置的。例如,如果您在部署一个 Java EE 应用程序,Java EE API 的依赖关系将被自动或隐性地添加到您的模块里。关于自动添加的依赖关系的完整列表,请参考 https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/ 上的《JBoss EAP 6 开发指南》『类加载和模块』章节里的『隐性模块依赖关系』

任务

当您移植程序到 JBoss EAP 6 时,由于模块化类加载的变化,您可能需要执行一个或多个下列任务:

3.1.3. 配置文件的修改

3.1.3.1. 创建或修改控制 JBoss EAP 6.0 里类加载的文件

介绍

由于 JBoss EAP 6 里对于使用模块化类加载的修改,您可能需要修改或创建一个或多个文件来添加依赖关系或阻止对自动依赖关系的加载。关于类加载和类加载次序的更多信息,请参考 https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/ 上的《JBoss EAP 6 开发指南》里的『类加载与模块』章节。

下列文件用于控制 JBoss EAP 6 的类加载。
jboss-web.xml
如果您已经在 jboss-web.xml 文件里定义了一个 <class-loading> 元素,您需要删除它。JBoss EAP 5 里使用的这个行为现在是 EAP 6 里的默认类加载行为,所以不是必需的了。如果您没有删除这个元素,您会在服务器日志里看到一个 ParseError 和 XMLStreamException。
下面是 jboss-web.xml 文件里已注释的 <class-loading> 元素的例子。
<!DOCTYPE jboss-web PUBLIC
    "-//JBoss//DTD Web Application 4.2//EN"
    "http://www.jboss.org/j2ee/dtd/jboss-web_4_2.dtd">
<jboss-web>  
<!-- 
    <class-loading java2ClassLoadingCompliance="false">
        <loader-repository>
            seam.jboss.org:loader=MyApplication
            <loader-repository-config>java2ParentDelegation=false</loader-repository-config>
        </loader-repository>
    </class-loading>
 -->
 </jboss-web>


MANIFEST.MF
手动编辑的
根据您的应用程序使用的组件或模块,您可能需要添加一个或多个以来关系到这个文件里。您可以添加它们为 Dependencies Class-Path 条目。
下面是开发人员编辑的 MANIFEST.MF 例子:
Manifest-Version: 1.0
Dependencies: org.jboss.logmanager
Class-Path: OrderManagerEJB.jar

如果您修改了这个文件,请确保在文件结尾包含一个新行符号。
用 Maven 生成的
如果您使用 Maven,您需要修改您的 pom.xml 文件以生成用于 MANIFEST.MF 的依赖关系。如果您的应用程序使用了 EJB 3.0,您可能在 pom.xml 文件里有如下内容:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-ejb-plugin</artifactId>
    <configuration>
        <ejbVersion>3.0</ejbVersion>
    </configuration>
</plugin>

如果 EJB 3.0 代码使用了 org.apache.commons.log,您需要在 MANIFEST.MF 文件里有这个以来关系。要生成这个以来关系,请添加 <plugin> 元素到 pom.xml 文件里:
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-ejb-plugin</artifactId>
    <configuration>
        <ejbVersion>3.0</ejbVersion>
        <archive>
            <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
        </archive>
    </configuration>
</plugin>

在上面的例子里,src/main/resources/META-INF/MANIFEST.MF 文件只需要包含以来关系条目:
Dependencies: org.apache.commons.logging
Maven 将生成完整的 MANIFEST.MF 文件:
Manifest-Version: 1.0
Dependencies: org.apache.commons.logging
jboss-deployment-structure.xml
这个文件是 JBoss 专有的部署描述符,它可以用来对类加载的细颗粒度控制。就像 MANIFEST.MF 一样,这个文件可以用来添加依赖关系。它也可以阻止添加自动依赖关系、定义额外的模块、修改 EAR 部署的隔离类加载行为,以及在模块里添加其他的资源根目录。
下面是一个 jboss-deployment-structure.xml 文件,它添加 JSF 1.2 模块的依赖关系且阻止了 JSF 2.0 模块的自动加载。
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.0">
  <deployment>
    <dependencies>
      <module name="javax.faces.api" slot="1.2" export="true"/>
      <module name="com.sun.jsf-impl" slot="1.2" export="true"/>
    </dependencies>
  </deployment>
  <sub-deployment name="jboss-seam-booking.war">
    <exclusions>
      <module name="javax.faces.api" slot="main"/>
      <module name="com.sun.jsf-impl" slot="main"/>
    </exclusions>
    <dependencies>
      <module name="javax.faces.api" slot="1.2"/>
      <module name="com.sun.jsf-impl" slot="1.2"/>
    </dependencies>
  </sub-deployment>
</jboss-deployment-structure>
关于这个文件的其他信息,请参考 第 3.1.3.2 节 “jboss-deployment-structure.xml”
application.xml
在以前的 JBoss EAP 版本里,您通过 jboss-app.xml 控制 EAR 里部署的顺序。现在不是这样了。Java EE6 规格在 application.xml 文件里提供了 <initialize-in-order> 元素来控制 EAR 里的 Java EE 模块的部署顺序。
在大多数情况下,您不许要指定部署顺序。如果您的应用程序使用了依赖关系注入和 resource-refs 来引入外部模块的组件,多数情况下都不要求 <initialize-in-order> 元素,因为应用服务器能够隐性地确定正确和优化的组件顺序。
让我们假设您有一个包含 myBeans.jarmyApp.war 打包在 myApp.ear 里的应用程序。 myApp.war 使用 @EJB 注解从 myBeans.jar 注入一个 bean。在这个例子里,应用服务器懂得如何确保 EJB 组件在 servlet 启动之前可用,而您不需要使用 <initialize-in-order> 元素。
然而,如果这个 servlet 使用了如下的传统 JNDI 查找风格的远程引用来访问 bean,您可能需要指定模块的顺序。
init() {
  Context ctx = new InitialContext();
  ctx.lookup("TheBeanInMyBeansModule");
}
在这种情况下,服务器不能确定 EJB 组件处于 myBeans.jar 里,您需要强制 myBeans.jar 里的组件被初始化并在 myApp.war 里的组件之前启动。为此,您可以设置 <initialize-in-order> 元素为 true 并指定 application.xml 文件里的 myBeans.jarmyApp.war 的顺序。
下面是一个使用 <initialize-in-order> 元素来控制部署顺序的例子。 myBeans.jarmyApp.war 文件之前被部署。
<application xmlns="http://java.sun.com/xml/ns/javaee" 
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="6"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
             http://java.sun.com/xml/ns/javaee/application_6.xsd">
    <application-name>myApp</application-name>
    <initialize-in-order>true</initialize-in-order>
    <module>
        <ejb>myBeans.jar</ejb>
    </module>
    <module>
        <web>
            <web-uri>myApp.war</web-uri>
            <context-root>myApp</context-root>
        </web>
    </module>
</application>
application.xml 文件的 schema 可以在这里找到:http://java.sun.com/xml/ns/javaee/application_6.xsd

注意

您应该意识到设置 <initialize-in-order> 元素为 true 会减慢部署速度。我们更倾向于使用依赖注入或 resource-refs 来定义正确的依赖关系,因为它们使容器在优化部署时更具灵活性。
jboss-ejb3.xml
jboss-ejb3.xml 部署描述符替换 jboss.xml 以覆盖和添加 Java EE 定义的 ejb-jar.xml 里提供的功能。这个新文件和 jboss.xml 兼容,而目前的部署里已经忽略了jboss.xml
login-config.xml
login-config.xml 文件不再用于安全配置。现在安全性是在服务器配置文件的 <security-domain> 元素里配置。这个文件是 standalone/configuration/standalone.xml,如果您是在受管域里运行服务器, 则是 domain/configuration/domain.xml

3.1.3.2. jboss-deployment-structure.xml

jboss-deployment-structure.xml 是 JBoss EAP 6 的一个新的可选的部署描述符。这个部署描述符提供了对部署里的类加载的控制。
这个部署描述符的 XML schema 位于 EAP_HOME/docs/schema/jboss-deployment-structure-1_2.xsd

3.1.3.3. 新模块化类加载系统的软件包资源

介绍

在以前的 JBoss EAP 版本里,WEB-INF/ 里面的所有资源都添加到了 WAR classpath。在 JBoss EAP 6 里,web 应用程序的 artifact 只从 WEB-INF/classesWEB-INF/lib 目录进行加载。没有在指定位置打包应用程序 artifact 会导致 ClassNotFoundException, NoClassDefError 或运行时错误。

要解决这些类加载的错误,您必须修改应用程序归档的结构或定义一个自定义模块。

修改资源打包
要使资源只对应用程序可用,您必须将属性文件、JAR 或其他具有 WAR 的 artifact 移至WEB-INF/classes/WEB-INF/lib/ 目录来进行绑定。详情请参考 第 3.1.3.4 节 “修改 ResourceBundle 属性的位置”
创建自定义模块
如果您想使自定义的资源对于运行在 JBoss EAP 服务器上的所有应用程序可用,您必须创建一个自定义的模块。关于这个途径的详情,请参考 第 3.1.3.5 节 “创建自定义模块”

3.1.3.4. 修改 ResourceBundle 属性的位置

介绍

在以前的 JBoss EAP 版本里,EAP_HOME/server/SERVER_NAME/conf/ 目录位于 classpath 里且可为应用程序所用。要使属性为 JBoss EAP 6 里的应用程序的 classpath 所用,您必须将其打包至您的应用程序里。

过程 3.2. 修改 ResourceBundle 属性的位置

  1. 如果您在开发 WAR 归档,您必须将这些属性包裹至 WAR 的 WEB-INF/classes/ 目录里。
  2. 如果您想要 EAP 里所有组件都可以访问这些属性,那您必须将其打包到 JAR 的根目录并将 JAR 放入 EAR 的 lib/ 目录下。

3.1.3.5. 创建自定义模块

下面的步骤描述了如何创建自定义模块以使书性文件和其他资源对于运行在 JBoss EAP 服务器上的所有应用程序所用。

过程 3.3. 创建自定义模块

  1. 创建和填充 module/ 目录结构。
    1. EAP_HOME/module 目录下创建一个目录结构来包含文件和 JAR。例如:
      $ cd EAP_HOME/modules/ 
      $ mkdir -p myorg-conf/main/properties
    2. 将属性文件移到您在前一步骤里创建的 EAP_HOME/modules/myorg-conf/main/properties/ 目录里。
    3. EAP_HOME/modules/myorg-conf/main/ 目录里创建一个包含下列 XML 内容的 module.xml 文件:
      <module xmlns="urn:jboss:module:1.1" name="myorg-conf">
          <resources>
              <resource-root path="properties"/>
          </resources>
      </module>
      
      
  2. 修改服务器配置文件里的 ee 子系统。您可以使用 JBoss CLI 或手动编辑这个文件。
    • 按照下列步骤使用 JBoss CLI 来修改服务器配置文件。
      1. 启动服务器并连接至管理 CLI。
        • 对于 Linux,输入下列命令:
          $ EAP_HOME/bin/jboss-cli.sh --connect
          
        • 对于 Windows,输入下列命令:
          C:\>EAP_HOME\bin\jboss-cli.bat --connect
          
        您应该看到下面的结果:
        Connected to standalone controller at localhost:9999
      2. 要在 ee 子系统里创建 myorg-conf<global-modules> 元素,输入下列命令:
        /subsystem=ee:write-attribute(name=global-modules, value=[{"name"=>"myorg-conf","slot"=>"main"}])
        
        您应该看到下面的结果:
        {"outcome" => "success"}
        
    • 如果您向手动编辑服务器配置文件,请按照下列步骤进行。
      1. 停止服务器并打开服务器配置文件。如果您使用的是独立服务器,这个文件是 EAP_HOME/standalone/configuration/standalone.xml,如果是受管域,这个文件是 EAP_HOME/domain/configuration/domain.xml
      2. 找到 ee 子系统并为 myorg-conf 添加全局模块。下面是 ee 子系统元素的例子,已经进行修改并包含了 myorg-conf 元素:
        <subsystem xmlns="urn:jboss:domain:ee:1.0" >            
            <global-modules>
                <module name="myorg-conf" slot="main" />            
            </global-modules>
        </subsystem>
        
        
  3. 假设您复制了一个名为 my.properties 的文件到正确的模块位置,您现在可以使用下面的代码来加载属性文件了:
    Thread.currentThread().getContextClassLoader().getResource("my.properties");
    

3.1.4. 日志的修改

3.1.4.1. 修改日志依赖关系

介绍

JBoss LogManager 支持所有日志框架的前端,所以您可以保持现有的日志代码或移至新的 JBoss 日志框架。不管用哪种方法,因为模块化类加载有改变,您可能需要修改您的应用程序来添加所需的依赖关系。

3.1.4.2. 为第三方日志框架更新应用程序代码

介绍

在 JBoss EAP 6 里,在默认情况下都已经添加了常见的第三方框架如 Apache Commons Loggin、Apache log4j、SLF4J 和 Java Logging 的日志依赖关系。在多数情况下,使用 JBoss EAP 容器提供的日志框架是更可取的。但是,如果您需要第三方框架提供的专有功能,您必须在部署里排除对应的 JBoss EAP 模块。请注意,虽然您的部署使用第三方的框架,服务器日志仍会继续使用 JBoss EAP 日志子系统配置。

下面的过程演示了如何从部署里排除 JBoss EAP 6 org.apache.log4j 模块。第一个过程适用于所有的 JBoss EAP 6 版本,而第二个过程只适用于 JBoss EAP 6.3 及以后的版本。

过程 3.5. 配置 JBoss EAP 6 以使用 log4j.properties 或 log4j.xml 文件

这个过程适用于所有的 JBoss EAP 6 版本。

注意

因为这个方法使用了 log4j 配置文件,您将无法在运行时再修改 log4j 日志配置。
  1. 用下列内容创建一个 jboss-deployment-structure.xml 文件:
    <jboss-deployment-structure>
        <deployment>
            <!-- Exclusions allow you to prevent the server from automatically adding some dependencies -->
            <exclusions>
                <module name="org.apache.log4j" />
            </exclusions>
        </deployment>
    </jboss-deployment-structure>
    
    
  2. 如果您在部署 WAR,请将 jboss-deployment-structure.xml 文件放入 META-INF/WEB-INF/ 目录;如果是部署 EAR,则请放入 META-INF/ 目录。如果您的部署包含了依赖的子部署,您必须在每个子部署里排除这些模块。
  3. 在 EAR 的 lib/ 或 WAR 部署的 WEB-INF/classes/ 里包含 log4j.propertieslog4j.xml 文件。如果您想将文件放到 lib/ 目录里,您必须在 jboss-deployment-structure.xml 文件里指定 <resource-root> 路径。
    <jboss-deployment-structure>
        <deployment>
            <!-- Exclusions allow you to prevent the server from automatically adding some dependencies -->
            <exclusions>
                <module name="org.apache.log4j" />
            </exclusions>
            <resources>
                <resource-root path="lib" />
            </resources>
        </deployment>
    </jboss-deployment-structure>
    
    
  4. 用下列 runtime 参数启动 JBoss EAP 6 服务器以防止在部署应用程序时控制台出现 ClassCastException
    -Dorg.jboss.as.logging.per-deployment=false
  5. 部署您的应用程序

过程 3.6. 配置 JBoss EAP 6.3 或更新版本的日志依赖关系

在 JBoss EAP 6.3 和以后的版本里,您可以使用新的 add-logging-api-dependencies logging 系统属性来排除第三方的日志框架依赖关系。下面的步骤演示了在 JBoss EAP 独立服务器上如何修改这个 logging 属性。
  1. 用下列 runtime 参数启动 JBoss EAP 6 服务器以防止在部署应用程序时控制台出现 ClassCastException
    -Dorg.jboss.as.logging.per-deployment=false
  2. 打开终端窗口并连接至管理 CLI。
    • 对于 Linux,输入下列命令:
      $ EAP_HOME/bin/jboss-cli.sh --connect
      
    • 对于 Windows,输入下列命令:
      C:\>EAP_HOME\bin\jboss-cli.bat --connect
      
  3. 修改日志子系统里的 add-logging-api-dependencies 属性。
    这个属性控制容器是否添加隐性的 logging API 依赖关系到部署里。
    • 如果为 true(默认值),将添加所有隐性的 logging API 依赖关系。
    • 如果设置为 false,依赖关系不会添加到部署里。
    要排除第三方的日志框架依赖关系,您必须用下列命令设置这个属性为 false
    /subsystem=logging:write-attribute(name=add-logging-api-dependencies, value=false)
    这个命令添加了 <add-logging-api-dependencies> 元素到 standalone.xml 配置文件的 logging 子系统里。
    <subsystem xmlns="urn:jboss:domain:logging:1.4">
        <add-logging-api-dependencies value="false"/>
        ....
    </subsystem>
    
    
  4. 部署您的应用程序

3.1.4.3. 修改代码以使用新的 JBoss Logging 框架

介绍

要使用新的框架,请修改您的导入和代码:

过程 3.7. 修改代码和依赖关系以使用新的 JBoss Logging 框架

  1. 修改您的导入和日志代码

    下面是一个使用新的 JBoss Logging 框架的例子:
    import org.jboss.logging.Level;
    import org.jboss.logging.Logger;
    
    private static final Logger logger = Logger.getLogger(MyClass.class.toString());
    
    if(logger.isTraceEnabled()) {
        logger.tracef("Starting...", subsystem);
    }
    
  2. 添加日志依赖关系

    包含 JBoss Logging 类的 JAR 位于名为 org.jboss.logging 的模块。您的 MANIFEST-MF 文件应该类似要:
    Manifest-Version: 1.0
    Dependencies: org.jboss.logging
    

3.1.5. 应用程序包的修改

3.1.5.1. 修改 EAR 和 WAR 的打包

介绍

当您移植应用程序时,由于模块化类加载的修改,您可能需要修改 EAR 或 WAR 的打包结构。模块依赖关系是以特定的顺序加载的:

  1. 系统依赖关系
  2. 用户依赖关系
  3. 本地资源
  4. 部署间的依赖关系

过程 3.8. 修改归档的打包

  1. 打包 WAR

    WAR 是一个模块,它里面的所有类都用相同的类加载器加载。这意味着打包在 WEB-INF/lib/ 目录里的类将和 WEB-INF/classes 里的一样被对待。
  2. 打包 EAR

    EAR 由多个模块组成。EAR/lib/ 目录是一个单个的模块且 EAR 里每个 WAR 或 EJB JAR 都是一个独立的模块。除非定义了显性的依赖关系,类不能访问 EAR 里其他模块里的类。子部署总是对父部署有着自动的依赖关系,这让它们可以访问 EAR/lib/ 目录里的类。然而,子部署并不总由自动的依赖关系来允许它们访问彼此。这个行为是通过设置 ee 子系统配置里的 <ear-subdeployments-isolated> 元素来控制的:
    <subsystem xmlns="urn:jboss:domain:ee:1.0" >            
      <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
    </subsystem>
    
    在默认情况下,它被设置为 false,这允许子部署查看属于 EAR 里其他子部署的类。
    关于类加载的更多信息,请参考 https://access.redhat.com/site/documentation/JBoss_Enterprise_Application_Platform/ 上的《JBoss 开发指南》里的『类加载和模块』章节。

3.1.6. 数据源和资源适配器配置的修改

3.1.6.1. 根据配置的变化更新应用程序

在 JBoss EAP 5 里,服务和子系统是在多个文件里配置的。而在 JBoss EAP 6 里,配置主要是在一个文件里完成的。如果您的应用程序使用了任何下面的资源或服务,您就可能需要修改配置。
  1. 如果您的应用程序使用了数据源,请参考: 第 3.1.6.2 节 “更新数据源配置”
  2. 如果您的应用程序使用了 JPA 且捆绑了 Hibernate JAR,请参考下列移植选项: 第 3.1.6.4 节 “为 Hibernate 或 JPA 配置数据源”
  3. 如果您的应用程序使用了资源适配器,请参考: 第 3.1.6.5 节 “更新资源适配器配置”
  4. 关于如何配置基本安全性,请参考: 第 3.1.7.1 节 “应用程序安全性的修改”

3.1.6.2. 更新数据源配置

介绍

在以前的 JBoss EAP 版本里,JCA 数据源配置在一个后缀为 *-ds.xml 的文件里定义。这个文件然后部署在服务器的 deploy/ 下或和应用程序一起打包。JDBC 驱动会被复制到 server/lib/ 目录或打包在应用程序的 WEB-INF/lib/ 目录里。虽然这种配置数据源的方法仍被支持,我们不推荐在产品环境里使用它,因为 JBoss 的管理根据已不支持。

在 JBoss EAP 6 里,数据源是在服务器配置文件里进行配置的。如果 JBoss EAP 实例运行在受管域里,数据源是在 domain/configuration/domain.xml 文件里配置。如果 JBoss EAP 实例以独立服务器运行,那么数据源是在 standalone/configuration/standalone.xml file 里配置。以这种方式配置的数据源可以用 JBoss 管理接口(包括 Web 管理控制台和命令行接口)进行管理和控制。这些工具使得在受管域上管理部署和配置多个服务器更为容易。
下面的内容描述了如何修改您的数据源配置,从而可以通过不同的管理工具进行管理和支持。
移植到 JBoss EAP 6 的可管理数据源配置

JDBC 4.0 兼容的驱动可以作为部署或核心模块来安装。JDBC 4.0 兼容的驱动包含一个 META-INF/services/java.sql.Driver 文件,它制定驱动类名。非 JDBC 4.0 兼容的驱动需要其他的步骤。关于如何兼容 JDBC 4.0 驱动和更新您的数据源配置为 Web 管理控制台和 CLI 管理的配置,请参考 第 3.1.6.3 节 “安装和配置 JDBC 驱动”

如果您的应用程序使用了 Hibernate 或 JPA,它可能要求进行额外的修改。详情请参考 第 3.1.6.4 节 “为 Hibernate 或 JPA 配置数据源”
使用 IronJacamar 移植工具来转换配置数据

您可以使用 IronJacamar 工具来移植数据源和资源适配器配置。这个工具将 *-ds.xml 风格的配置文件转换为 JBoss EAP 6 所期望的格式。更多信息请参考 第 4.1.6 节 “使用 IronJacamar 工具来移植数据源和资源适配器配置”

3.1.6.3. 安装和配置 JDBC 驱动

介绍

JDBC 驱动可以下列两种方式之一安装到容器里。

  • 作为部署
  • 作为核心模块
每种方式各自的优缺点如下。

在 JBoss EAP 6 里,数据源是在服务器配置文件里进行配置的。如果 JBoss EAP 实例运行在受管域里,数据源是在 domain/configuration/domain.xml 文件里配置。如果 JBoss EAP 实例以独立服务器运行,那么数据源是在 standalone/configuration/standalone.xml file 里配置。Schema 引用信息两种模式都是一样的,您可以在 JBoss EAP 6 的 docs/schema/ 里找到。我们在这里假设服务器是作为独立服务器运行的,而数据源是在 standalone.xml 文件里进行配置的。

过程 3.9. 安装和配置 JDBC 驱动

  1. 安装 JDBC 驱动。

    1. 将 JDBC 驱动作为部署安装。

      这是我们推荐的安装驱动的方法。当 JDBC 驱动作为部署安装时,它会被部署为常规的 JAR。如果 JBoss EAP 实例作为独立服务器运行,请将兼容 JDBC 4.0 的 JAR 复制到 EAP_HOME/standalone/deployments/ 目录。对于受管域,您必须使用管理控制台或管理 CLI 将 JAR 部署到服务器组里。
      下面是一个安装为独立服务器的部署的 MySQL JDBC 驱动示例:
      $cp mysql-connector-java-5.1.15.jar EAP_HOME/standalone/deployments/
      任何兼容 JDBC 4.0 的驱动都自动会被承认且根据名称和版本安装至系统里。兼容 JDBC 4.0 的 JAR 都包含一个名为 META-INF/services/java.sql.Driver 的文本文件,它指定驱动类的名称。如果这个驱动不兼容 JDBC 4.0,它可以用下列方法来部署:
      • 创建并添加 java.sql.Driver 文件到 META-INF/services/ 路径下的 JAR。这个文件应该包含驱动类的名称,例如:
        com.mysql.jdbc.Driver
      • 在 deployment 目录里创建一个 java.sql.Driver 文件。对于作为独立服务器运行的 JBoss EAP 6 实例,这个文件应该位于:EAP_HOME/standalone/deployments/META-INF/services/java.sql.Driver。如果服务器位于受管服务器,您必须使用管理控制台或管理 CLI 来部署这个文件。
      这种方法的优点是:
      • 因为不需要定义模块,所以这是最简单的方法。
      • 当服务器运行在受管域里时,使用这个方法的部署将自动传播到域里的所有服务器。这意味着管理员不需要手动分发这个驱动 JAR。
      这种方法的缺点是:
      • 如果 JDBC 驱动由多个 JAR 组成,如驱动 JAR 以及依赖的许可证 JAR 或本地化 JAR,您不能将驱动安装为部署。您必须将其安装为核心模块。
      • 如果这个驱动不兼容 JDBC 4.0,您必须创建一个包含驱动类名的文件并导入至 JAR 或覆盖到 deployments/ 目录。
    2. 将 JDBC 驱动安装为核心模块。

      要将 JDBC 驱动安装为核心模块,您必须在 EAP_HOME/modules/ 下创建一个文件路径结构。这个结构包含 JDBC 驱动 JAR,任何其他供应商许可证或本地化 JAR,以及一个定义模块的 module.xml 文件。
      • 将 MySQL JDBC 驱动安装为核心模块

        1. 创建一个目录结构 EAP_HOME/modules/com/mysql/main/
        2. main/ 子目录里,创建一个包含下列为 MySQL JDBC 驱动定义的 module.xml 文件:
          <?xml version="1.0" encoding="UTF-8"?>
          <module xmlns="urn:jboss:module:1.0" name="com.mysql">
          <resources>
              <resource-root path="mysql-connector-java-5.1.15.jar"/>
          </resources>
          <dependencies>
              <module name="javax.api"/>
          </dependencies>
          </module>
          
          
          
          模块名 “com.mysql”,映射了这个模块的目录结构。<dependencies> 元素用来指定这个模块对其他模块的依赖关系。在这种情况下,所有的 JDBC 数据源都依赖于在另一个名为 javax.api 的模块里定义的 Java JDBC API。这个模块位于 modules/system/layers/base/javax/api/main/ 目录。

          注意

          确保您在 module.xml 文件的开头没有留下一个空格,否则您会遇到 "New missing/unsatisfied dependencies" 错误。
        3. 复制 MySQL JDBC 驱动 JAR 到 EAP_HOME/modules/com/mysql/main/ 目录:
          $ cp mysql-connector-java-5.1.15.jar EAP_HOME/modules/com/mysql/main/
      • 将 IBM DB2 JDBC 驱动和 license JAR 安装为核心模块。

        这个例子只是用来演示如何部署要求 JDBC Driver JAR 之外的 JAR 的驱动。
        1. 创建目录结构 EAP_HOME/modules/com/ibm/db2/main/
        2. main/ 子目录里,创建一个包含下列用于 IBM DB2 JDBC 驱动和许可证的模块定义的 module.xml 文件:
          <?xml version="1.0" encoding="UTF-8"?>
          <module xmlns="urn:jboss:module:1.1" name="com.ibm.db2">
            <resources>
              <resource-root path="db2jcc.jar"/>
              <resource-root path="db2jcc_license_cisuz.jar"/>
            </resources>
            <dependencies>
              <module name="javax.api"/>
              <module name="javax.transaction.api"/>
            </dependencies>
          </module>
          
          

          注意

          确保您在 module.xml 文件的开头没有留下一个空格,否则您会遇到 "New missing/unsatisfied dependencies" 错误。
        3. 复制 JDBC 驱动和 license JAR 到 EAP_HOME/modules/com/ibm/db2/main/ 目录里。
          $ cp db2jcc.jar EAP_HOME/modules/com/ibm/db2/main/
          $ cp db2jcc_license_cisuz.jar EAP_HOME/modules/com/ibm/db2/main/
      这种方法的优点是:
      • 当 JDBC 驱动由多个 JAR 组成时,这是唯一的途径。
      • 用这个方法,不兼容 JDBC 4.0 的驱动可以无需修改驱动 JAR 或创建覆盖文件就进行安装。
      这种方法的缺点是:
      • 通过设置模块要更为困难。
      • 您必须手动将模块复制到运行在受管域里的每个服务器里。
  2. 配置数据源。

    1. 添加数据库驱动。

      在相同的文件的 <drivers> 元素了添加 <driver> 元素。它也包含了之前的 *-ds.xml 文件里定义的一些数据源信息。
      首先确定驱动 JAR 是否兼容 JDBC 4.0。兼容 JDBC 4.0 的 JAR 包含一个指定驱动类名的 META-INF/services/java.sql.Driver。这个服务器使用这个文件来在 JAR 里查找驱动类的名称。兼容 JDBC 4.0 的 JAR 不要求 <driver-class> 元素,因为在 JAR 里它已被指定。下面是一个 JDBC 4.0 兼容的 MySQL 驱动的 driver 元素示例:
      <driver name="mysql-connector-java-5.1.15.jar" module="com.mysql"/>
      
      不兼容 JDBC 4.0 的驱动要求一个 <driver-class> 属性来确定驱动类,这是因为没有 META-INF/services/java.sql.Driver 文件来指定驱动类名。下面是一个不兼容 JDBC 4.0 的 MySQL 驱动的 driver 元素示例:
      <driver name="mysql-connector-java-5.1.15.jar" module="com.mysql">
      <driver-class>com.mysql.jdbc.Driver</driver-class></driver>
      
    2. 创建数据源。

      standalone.xml 文件的 <datasources> 部分创建一个 <datasource> 元素。这个文件包含之前的 *-ds.xml 文件里定义的大部分数据源信息。

      重要

      要使修改在服务器重启后仍然生效,您必须在编辑服务器配置文件前停止服务器。
      下面是 standalone.xml 文件里的一个 MySQL 数据源元素示例:
      <datasource jndi-name="java:/YourDatasourceName" pool-name="YourDatasourceName">
        <connection-url>jdbc:mysql://localhost:3306/YourApplicationURL</connection-url>
        <driver>mysql-connector-java-5.1.15.jar</driver>
        <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
        <pool>
          <min-pool-size>100</min-pool-size>
          <max-pool-size>200</max-pool-size>
        </pool>
        <security>
          <user-name>USERID</user-name>
          <password>PASSWORD</password>
        </security>
        <statement>
          <prepared-statement-cache-size>100</prepared-statement-cache-size>
          <share-prepared-statements/>
        </statement>
      </datasource>
      
      
  3. 更新程序代码里的 JNDI 引用。

    您必须在程序源代码里替换过时的 JNDI 查找名称以使用新的 JNDI 标准化数据源名称。详情请参考: 第 3.1.8.4 节 “修改应用程序以遵循新的 JNDI 命名规则”
    您也必须让现有的访问数据源的 @Resource 注解使用新的 JNDI 名称。例如:
    @Resource(name = "java:/YourDatasourceName").
    

3.1.6.4. 为 Hibernate 或 JPA 配置数据源

如果您的应用程序时用了 JPA 且捆绑了 Hibernate JAR,您可能会想要使用 JBoss EAP 6 附带的 Hibernate。要使用这个版本的 Hibernate,您必须从应用程序里删除旧的 Hibernate 捆绑。

过程 3.10. 删除 Hibernate 捆绑

  1. 从您的应用程序的库目录里将 Hibernate JAR 删除。
  2. 当不再需要 <hibernate.transaction.manager_lookup_class> 元素时,在 persistence.xml 里将其删除或注释。

3.1.6.5. 更新资源适配器配置

介绍

在以前的应用服务器版本里,资源适配器配置是在带有后缀 *-ds.xml 的文件里定义的。在 JBoss EAP 6 里,资源适配器是在服务器配置文件里配置的。如果您是在受管域里运行的,配置文件是 EAP_HOME/domain/configuration/domain.xml。如果您运行的是独立服务器,配置文件是 EAP_HOME/standalone/configuration/standalone.xml。Schema 引用信息两种模式都是一样的,您可以在 Iron Jacamar 网站 http://www.ironjacamar.org/documentation.htmlSchemas 里找到。

重要

要使修改在服务器重启后仍然生效,您必须在编辑服务器配置文件前停止服务器。
定义资源适配器

资源适配器描述符信息是在服务器配置文件中的下列 subsystem 元素里定义的:

<subsystem xmlns="urn:jboss:domain:resource-adapters:1.1"/>
您将使用资源适配器 *-ds.xml 文件里定义的相同的一些信息。

下面是服务器配置文件里的资源适配器元素示例:
<resource-adapters>
  <resource-adapter>
    <archive>multiple-full.rar</archive>
    <config-property name="Name">ResourceAdapterValue</config-property>
    <transaction-support>NoTransaction</transaction-support>
    <connection-definitions>
      <connection-definition
      class-name="org.jboss.jca.test.deployers.spec.rars.multiple.MultipleManagedConnectionFactory1"
      enabled="true" jndi-name="java:/eis/MultipleConnectionFactory1"
      pool-name="MultipleConnectionFactory1">
    <config-property name="Name">MultipleConnectionFactory1Value</config-property>
      </connection-definition>
      <connection-definition
      class-name="org.jboss.jca.test.deployers.spec.rars.multiple.MultipleManagedConnectionFactory2"
      enabled="true" jndi-name="java:/eis/MultipleConnectionFactory2"
      pool-name="MultipleConnectionFactory2">
    <config-property name="Name">MultipleConnectionFactory2Value</config-property>
      </connection-definition>
    </connection-definitions>
    <admin-objects>
      <admin-object
      class-name="org.jboss.jca.test.deployers.spec.rars.multiple.MultipleAdminObject1Impl"
      jndi-name="java:/eis/MultipleAdminObject1">
    <config-property name="Name">MultipleAdminObject1Value</config-property>
      </admin-object>
      <admin-object class-name="org.jboss.jca.test.deployers.spec.rars.multiple.MultipleAdminObject2Impl"
      jndi-name="java:/eis/MultipleAdminObject2">
    <config-property name="Name">MultipleAdminObject2Value</config-property>
      </admin-object>
      </admin-objects>
  </resource-adapter>
</resource-adapters>

3.1.7. 安全性的修改

3.1.7.1. 应用程序安全性的修改

配置基本验证的安全性

在以前的 JBoss EAP 版本里,放在 EAP_HOME/server/SERVER_NAME/conf/ 下的属性文件位于 classpath 上且可以轻易地被 UsersRolesLoginModule 找到。在 JBoss EAP 6 里,目录结构已经发生了变化。属性文件必须打包在应用程序里,使其在 classpath 上可用。

重要

要使修改在服务器重启后仍然生效,您必须在编辑服务器配置文件前停止服务器。
要配置基本验证的安全性,请在 standalone/configuration/standalone.xmldomain/configuration/domain.xml 服务器配置文件里的 security-domains 下添加一个新的安全域:
<security-domain name="example">
    <authentication>
        <login-module code="UsersRoles" flag="required">
            <module-option name="usersProperties" 
                    value="${jboss.server.config.dir}/example-users.properties"/>
            <module-option name="rolesProperties" 
                    value="${jboss.server.config.dir}/example-roles.properties"/>
        </login-module>
    </authentication>
</security-domain>
如果 JBoss EAP 6 实例作为独立服务器运行, ${jboss.server.config.dir} 指向 EAP_HOME/standalone/configuration/ 目录。如果它运行在受管域里, ${jboss.server.config.dir} 指向 EAP_HOME/domain/configuration/ 目录。
修改安全域的名称

在 JBoss EAP 6 里,安全域名称里不再使用前缀 java:/jaas/

  • 对于 Web 应用程序,您必须从 jboss-web.xml 里的安全域配置里删除这个前缀。
  • 对于企业级应用程序,您必须从 jboss-ejb3.xml 里的安全域配置里删除这个前缀。这个文件已经替换了 JBoss EAP 6 里的 jboss.xml

3.1.8. JNDI 的修改

3.1.8.1. 更新应用程序 JNDI 命名空间的名称

介绍

EJB 3.1 引入了一个标准化的全局 JNDI 命名空间和一系列相关的映射到不同 Java EE 应用程序作用域的命名空间。可移植 EJB 名称只能绑定其中三种:java:globaljava:modulejava:app。使用 JNDI 查找的应用程序必须进行修改以遵循新的标准化 JNDI 命名空间规则。

JNDI 映射示例

前一版本里的 JNDI 命名空间示例以及如何在 JBoss EAP 6 里指定可以在这里找到: 第 3.1.8.5 节 “以前版本的 JNDI 命名空间示例和它们在 JBoss EAP 6 里是如何指定的”

3.1.8.2. 可移植的 EJB JNDI 名称

介绍

Java EE 6 规格定义了 4 种逻辑命名空间,每种都有自己的作用域,但可移植的 EJB 名称只能绑定到其中三种。下表详述了何时和如何使用每种命名空间。

表 3.1. 可移植的 JNDI 命名空间

JNDI 命名空间 描述
java:global
这个命名空间里的名称是应用程序服务器实例里部署的所有应用程序共享的。您可以使用这个命名空间里的名称来查找部署到相同服务器里的 EJB 外部归档。
下面是一个 java:global 命名空间的示例:java:global/jboss-seam-booking/jboss-seam-booking-jar/HotelBookingAction
java:module
这个命名空间里的名称是由部署在模块里的所有组件共享的,例如单一 EJB 模块或 web 模块中所有组件里的所有 EJB。
下面是一个 java:module 命名空间的示例:java:module/HotelBookingAction!org.jboss.seam.example.booking.HotelBooking
java:app
这个命名空间里的名称是由单个应用程序里的所有模块里的所有组件共享的,例如相同 EJB 文件里的 WAR 或 EJB JAR 文件将可以访问 java:app 命名空间里的资源。
下面是一个 java:app 命名空间的示例:java:app/jboss-seam-booking-jar/HotelBookingAction
您在 EE.5.2.2 章节里可以找到关于 JNDI 命名上下文的更多信息,如 "JSR 316: JavaTM Platform, Enterprise Edition (Java EE) Specification, v6" 里的"Application Component Environment Namespaces"。您也可以在这里下载相关规格:http://jcp.org/en/jsr/detail?id=316

3.1.8.3. 复核 JNDI 命名空间规则

介绍

JBoss EAP 6 已经改进了 JNDI 命名空间,不只是为应用服务器里绑定的每个名称提供可预测和一致的规则,也防止了将来的兼容性问题。这意味着如果名称不遵循新的规则,应用程序里的当前命名空间也会出现问题。

命名空间应该遵循下列规则:

  1. 未限定的相对名称如 DefaultDSjdbc/DefaultDS 应该根据上下文限定于 java:comp/envjava:module/envjava:jboss/env
  2. 未限定的绝对名称如 /jdbc/DefaultDS 应该限定于 java:jboss/root
  3. 限定的绝对名称如 java:/jdbc/DefaultDS 应该和上面未限定的绝对名称采用相同的方式进行限定。
  4. java:jboss 命名空间在整个 AS 服务器实例间进行共享。
  5. 带有 java: 前缀的相对名称必须位于下列 5 个命名空间中的一个:compmoduleappglobal 或私有的 jboss。任何以 java:xxx 开始的名称里的 xxx 不匹配上面的 5 个命名空间都将导致无效名称错误。

3.1.8.4. 修改应用程序以遵循新的 JNDI 命名规则

  • 下面是一个 JBoss EAP 5.1 里的 JNDI 查找示例。这些代码是在一个初始方法里找到的。
    private ProductManager productManager;
    try {
        context = new InitialContext();
        productManager = (ProductManager) context.lookup("OrderManagerApp/ProductManagerBean/local");
    } catch(Exception lookupError) {
        throw new ServletException("Unable to find the ProductManager bean", lookupError);
    }
    
    请注意查找名称是 OrderManagerApp/ProductManagerBean/local
  • 下面是在 JBoss EAP 6 里如何用依赖关系注入编写相同查找的示例:
    @EJB(lookup="java:app/OrderManagerEJB/ProductManagerBean!services.ejb.ProductManager")
    private ProductManager productManager;
    
    查找值现在被定义为成员变量并使用新的可移植的 java:app JNDI 命名空间名 java:app/OrderManagerEJB/ProductManagerBean!services.ejb.ProductManager
  • 如果您不想使用依赖关系注入,您仍可以像上面那样创建新的 InitialContext 并修改查找以使用新的 JNDI 命名空间名称。
    private ProductManager productManager;
    try {
        context = new InitialContext();
        productManager = (ProductManager) context.lookup("java:app/OrderManagerEJB/ProductManagerBean!services.ejb.ProductManager");
    } catch(Exception lookupError) {
        throw new ServletException("Unable to find the ProductManager bean", lookupError);
    }
    

3.1.8.5. 以前版本的 JNDI 命名空间示例和它们在 JBoss EAP 6 里是如何指定的

表 3.2. JNDI 命名空间映射表

JBoss EAP 5.x 里的命名空间 JBoss EAP 6 里的命名空间 其他注释
OrderManagerApp/ProductManagerBean/local java:module/ProductManagerBean!services.ejb.ProductManager Java EE6 标准绑定。作用域为当前模块,只可以在相同模块里访问。
OrderManagerApp/ProductManagerBean/local java:app/OrderManagerEJB/ProductManagerBean!services.ejb.ProductManager Java EE6 标准绑定。作用域为当前应用程序,只可以在相同应用程序里访问。
OrderManagerApp/ProductManagerBean/local java:global/OrderManagerApp/OrderManagerEJB/ProductManagerBean!services.ejb.ProductManager Java EE6 标准绑定。作用域为应用服务器,可全局访问。
java:comp/UserTransaction java:comp/UserTransaction 命名空间作用域为当前组件。非 Java EE 6 的线程不可访问,例如您的应用程序直接创建的线程。
java:comp/UserTransaction java:jboss/UserTransaction 可全局访问,如果 java:comp/UserTransaction 不可用则使用它。
java:/TransactionManager java:jboss/TransactionManager
java:/TransactionSynchronizationRegistry java:jboss/TransactionSynchronizationRegistry