Red Hat Training

A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform

第 5 章 应用程序迁移的修改

5.1. Web Service 的应用程序修改

JBossWS 5 为 JBoss EAP 7 Web Services 带来了新的功能和性能改进,这主要是通过升级 Apache CXFApache WSS4JApache Santuario 完成的。

5.1.1. JAX-RPC 支持的修改

基于 XML 的 RPC(JAX-RPC)的 Java API 在 Java EE 6 已被舍弃,在 Java EE 7 里是可选的。在 JBoss EAP 7 里它不再可用也不被支持。使用 JAX-RPC 的应用程序必须迁移以使用目前 Java EE 的标准 Web Service 框架 JAX-WS

JAX-RPC Web Service 可以用下列途径确认:

  • 使用 JAX-RPC 映射文件,它是一个 XML 文件,其根元素是 <java-wsdl-mapping>
  • 使用包含 <webservice-description> 元素(包含 <jaxrpc-mapping-file> 子元素)的 webservices.xml XML 描述符文件。下面是一个定义 JAX-RPC web service 的 webservices.xml 描述符文件示例。

    <webservices xmlns="http://java.sun.com/xml/ns/j2ee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd" version="1.1">
      <webservice-description>
        <webservice-description-name>HelloService</webservice-description-name>
        <wsdl-file>WEB-INF/wsdl/HelloService.wsdl</wsdl-file>
        <jaxrpc-mapping-file>WEB-INF/mapping.xml</jaxrpc-mapping-file>
        <port-component>
          <port-component-name>Hello</port-component-name>
          <wsdl-port>HelloPort</wsdl-port>
          <service-endpoint-interface>org.jboss.chap12.hello.Hello</service-endpoint-interface>
          <service-impl-bean>
            <servlet-link>HelloWorldServlet</servlet-link>
          </service-impl-bean>
        </port-component>
      </webservice-description>
    </webservices>
  • 使用 ejb-jar.xml 文件,它包含引用 JAX-RPC 映射文件的 <service-ref> 元素。

5.1.2. Apache CXF Spring Web Services 的修改

在以前的 JBoss EAP 版本里,您可以通过在端点部署归档里包含 jbossws-cxf.xml 配置文件来自定义 JBossWS 和 Apache CXF 集成。其中已一个例子是为 Apache CXF 总线上的 Web Service 客户和服务器端点配置连接器链。这个集成要求在 JBoss EAP 服务器里部署 Spring。

JBoss EAP 7 不再支持 Spring 集成。任何包含 jbossws-cxf.xml 描述符配置文件的应用程序必须进行修改,替换该文件里定义的自定义配置。虽然您仍可以直接访问 Apache CXF API,请注意应用程序将会是不可迁移的。

我们建议的方法是尽量用新的 JBossWS 描述符配置选项替换 Spring 自定义配置。基于 JBossWS 描述符的方法提供了类似的功能而无需修改客户端点代码。在某些情况下,您可以用 Context Dependency Injection (CDI) 替代 Spring。

Apache CXF 拦截器

JBossWS 描述符提供了新的配置选项,允许您声明拦截器而无需修改客户端点代码。通过指定 cxf.interceptors.incxf.interceptors.out 属性的拦截器类名,您可以在预定义的客户和端点配置里声明拦截器。

下面是一个 jaxws-endpoint-config.xml 文件示例,它用这些属性声明拦截器。

<?xml version="1.0" encoding="UTF-8"?>
<jaxws-config xmlns="urn:jboss:jbossws-jaxws-config:4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
  xsi:schemaLocation="urn:jboss:jbossws-jaxws-config:4.0 schema/jbossws-jaxws-config_4_0.xsd">
  <endpoint-config>
    <config-name>org.jboss.test.ws.jaxws.cxf.interceptors.EndpointImpl</config-name>
    <property>
      <property-name>cxf.interceptors.in</property-name>
      <property-value>org.jboss.test.ws.jaxws.cxf.interceptors.EndpointInterceptor,org.jboss.test.ws.jaxws.cxf.interceptors.FooInterceptor</property-value>
    </property>
    <property>
      <property-name>cxf.interceptors.out</property-name>
      <property-value>org.jboss.test.ws.jaxws.cxf.interceptors.EndpointCounterInterceptor</property-value>
    </property>
  </endpoint-config>
</jaxws-config>
Apache CXF 功能

JBossWS 描述符允许您通过指定 cxf.features 属性的功能类名列表,在预定义的客户和端点配置里声明功能。

下面是一个 jaxws-endpoint-config.xml 文件示例,它用这些属性声明了一个功能。

<?xml version="1.0" encoding="UTF-8"?>
<jaxws-config xmlns="urn:jboss:jbossws-jaxws-config:4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
  xsi:schemaLocation="urn:jboss:jbossws-jaxws-config:4.0 schema/jbossws-jaxws-config_4_0.xsd">
  <endpoint-config>
    <config-name>Custom FI Config</config-name>
    <property>
      <property-name>cxf.features</property-name>
      <property-value>org.apache.cxf.feature.FastInfosetFeature</property-value>
    </property>
  </endpoint-config>
</jaxws-config>
Apache CXF 的 HTTP 传输

在 Apache CXF 里,HTTP 传输配置是通过 org.apache.cxf.transport.http.HTTPConduit 属性实现的。JBoss WS 集成允许在程序里使用 Apache CXF API 修改 Conduit。

import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;

// Set chunking threshold before using a JAX-WS port client
...
HTTPConduit conduit = (HTTPConduit)ClientProxy.getClient(port).getConduit();
HTTPClientPolicy client = conduit.getClient();

client.setChunkingThreshold(8192);
...

您也通过设置系统属性来控制和覆盖 Apache CXF HTTPConduit 的默认值。

属性类型描述

cxf.client.allowChunking

布尔值

指定是否用分块发送请求。

cxf.client.chunkingThreshold

整数

设置从非分块切模式切换至分块模式时的极限值。

cxf.client.connectionTimeout

长整数

设置连接超时(毫秒)。

cxf.client.receiveTimeout

长整数

设置接收超时(毫秒)。

cxf.client.connection

字符串

指定是否使用 Keep-Aliveclose 连接类型。

cxf.tls-client.disableCNCheck

布尔值

指定是否禁用 CN 主机名称检查。

5.1.3. WS-Security 修改

  • 如果您的应用程序包含了自定义的访问 org.apache.ws.security.WSPasswordCallback 类的回调处理程序,请注意这个类已经移至 org.apache.wss4j.common.ext 软件包。
  • org.apache.ws.security.saml.ext 软件包里大多数 SAML bean 对象已经移至 org.apache.wss4j.common.saml package
  • 使用 RSA v1.5 关键字传输并默认禁用所有相关的算法。
  • 安全令牌服务(Security Token Service,STS)之前只检验 onBehalfOf 令牌。它现在可以检验 ActAs 令牌。因此,您必须在为 ActAs 令牌提供的 UsernameToken 里指定有效的用户名和密码。
  • SAML Bearer 令牌现在要求具有内部签名。org.apache.wss4j.dom.validate.SamlAssertionValidator 类现在有一个 setRequireBearerSignature() 方法来启用或禁用签名验证。

5.1.4. JBoss 模块结构的修改

cxf-apicxf-rt-core JAR 已合并到一个 cxf-core JAR。因此,JBoss EAP 里的 org.apache.cxf 模块现在包含了 cxf-core JAR 并较之以前的版本开放了更多的类。

5.1.5. Bouncy Castle 的要求和修改

如果您想对 XML/WS-Security 里的对称加密使用 AES 加密和 Galois/Counter Mode (GCM),您需要 BouncyCastle 安全提供者。

JBoss EAP 7 附带了 org.bouncycastle 模块,JBossWS 现在能够依赖自己的类加载来获取和使用 BouncyCastle 安全提供者。因此不再需要再当前 JMV 里静态地安装 BouncyCastle。对于运行在容器外而要访问安全提供者的应用程序,你可以添加 BouncyCastle 库到 classpath 里。

您可以通过设置 jaxws-endpoint-config.xml(服务器)或 jaxws-client-config.xml (客户)里的 org.jboss.ws.cxf.noLocalBC 属性值为 true 来禁用这个行为。

如果您不想使用 JBoss EAP 附带的版本,您仍可以将 BouncyCastle 静态地安装到 JVM 里。在这种情况下,静态安装的 BouncyCastle 将优先于 classpth 的安全提供者。要避免这种情况,您必须使用 BouncyCastle 1.49、1.51 或更高的版本。

5.1.6. Apache CXF 总线选择策略

容器里运行的客户的默认总线选择策略已从 THREAD_BUS 改为 TCCL_BUS。对于在容器外运行的客户,默认的策略仍是 THREAD_BUS。您可以用下列方法来恢复之前版本里的设置。

  • 将系统属性 org.jboss.ws.cxf.jaxws-client.bus.strategy 设置为 THREAD_BUS 来引导 JBoss EAP 服务器。
  • 显性地在客户代码里设置选择策略。

5.1.7. WebServiceRef 对 JAX-WS 2.2 的要求

容器必须使用JAX-WS 2.2 风格的构造器,它使用 WebServiceFeature 类来构建注入到 Web service 引用里的客户。这意味着用户提供的服务类(由容器注入)必须实现 JAX-WS 2.2 或更高规格。

5.1.8. 忽略 HttpsHost CN 检查

在以前的版本里,通过设置系统属性 org.jboss.security.ignoreHttpsHosttrue,您可以禁用对证书里服务器的公共名称(Common Name,CN) 的 HTTPS URL 主机名检查。这个系统属性名称已被 cxf.tls-client.disableCNCheck 所替代。

5.1.9. 服务器端的配置和类加载

As a consequence of enabling injections into service endpoint and service client handlers, it is no longer possible to automatically load handler classes from the org.jboss.as.webservices.server.integration JBoss module. If your application depends on a given predefined configuration, you might need to explicitly define new module dependencies for your deployment. For more information, see Migrate Explicit Module Dependencies

5.1.10. 舍弃 Java Endorsed Standards Override Mechanism

JDK 1.8_40 已舍弃 Java Endorsed Standards Override Mechanism 而 JDK 9 将删除它。这个机制允许开发人员将 JAR 放入 JRE 里支持的目录,从而使这些库为所有部署的应用程序所用。

如果您的应用程序使用了 Apache CXF 的 JBossWS 实现,JBoss EAP 7 会确保以正确的顺序添加所需的依赖关系,所以您不会受这些改动的影响。如果您的应用程序直接访问 Apache CXF,作为应用程序部署的一部分,在 JBossWS 依赖关系之后您现在必须提供 Apache CXF 依赖关系。

5.1.11. EAR 归档里的描述符规格

在以前的 JBoss EAP 版本里,您可以为 JAR 归档的 META-INF/ 里的 EJB Web Service 部署或 WEB-INF/ 里的 POJO Web Service 部署及 WAR 归档捆绑的 EJB Web Service 端点配置 jboss-webservices.xml 部署描述符文件。

在 JBoss EAP 7 里,您现在可以在 EAR 归档的 META-INF/ 目录里配置 jboss-webservices.xml 部署描述符文件。如果 EAR 归档和 JAR 或 WAR 归档里都有 jboss-webservices.xml 文件,JAR 或 WAR 的 jboss-webservices.xml 里的配置数据会覆盖 EAR 描述符文件里对应的数据。

5.2. 更新远程 URL 连接器和端口

在 JBoss EAP 7 里,默认的连接器已从 remote 改为 http-remoting,且默认的远程连接端口已从 4447 改为 8080。默认配置的 JNDI 供应商 URL 已从 remote://localhost:4447 改为 http-remoting://localhost:8080

If you use the JBoss EAP 7 migrate operation to update your configuration, you do not need to modify the remote connector, remote port, or JNDI provider URLs because the migration operation preserves the JBoss EAP 6 remoting connector and 4447 port configuration settings in the subsystem configuration. For more information about the migrate operation, see Management CLI Migration Operation.

如果您没有使用 migrate 操作而用新的 JBoss EAP 7 默认配置来运行,你必须修改远程连接、远程端口以及 JNDI 供应商 URL 来使用上述新的设置。

5.3. 消息应用程序的修改

5.3.1. 替换或更新 JMS 部署描述符

JBoss EAP 7 舍弃了用命名模式 -jms.xml 标识的私有 JMS 资源部署描述符文件。下面是一个 JBoss EAP 6 的 JMS 资源部署描述符示例。

<?xml version="1.0" encoding="UTF-8"?>
<messaging-deployment xmlns="urn:jboss:messaging-deployment:1.0">
  <hornetq-server>
    <jms-destinations>
      <jms-queue name="testQueue">
        <entry name="queue/test"/>
        <entry name="java:jboss/exported/jms/queue/test"/>
      </jms-queue>
      <jms-topic name="testTopic">
        <entry name="topic/test"/>
        <entry name="java:jboss/exported/jms/topic/test"/>
      </jms-topic>
    </jms-destinations>
  </hornetq-server>
</messaging-deployment>

在以前的版本里,如果您的应用程序使用了 -jms.xml JMS 部署描述符,您可以按照 Java EE 7 规格的 EE.5.18 章节转成使用标准 Java EE 7 部署描述符,或者升级部署描述符来使用 JBoss EAP 7 里的 messaging-activemq 子系统。

如果您选择更新描述符,您需要进行下列修改。

  • 修改命名空间 "urn:jboss:messaging-deployment:1.0" 为 "urn:jboss:messaging-activemq-deployment:1.0"。
  • 修改 <hornetq-server> 元素名为 <server>

修改后的文件应该类似于下面的例子。

<?xml version="1.0" encoding="UTF-8"?>
<messaging-deployment xmlns="urn:jboss:messaging-activemq-deployment:1.0">
  <server>
    <jms-destinations>
      <jms-queue name="testQueue">
        <entry name="queue/test"/>
        <entry name="java:jboss/exported/jms/queue/test"/>
      </jms-queue>
      <jms-topic name="testTopic">
        <entry name="topic/test"/>
        <entry name="java:jboss/exported/jms/topic/test"/>
      </jms-topic>
    </jms-destinations>
  </server>
</messaging-deployment>

关于和消息相同相关的服务器配置修改,请参考 Messaging Server Configuration Changes

5.3.2. 更新外部的 JMS 客户

JBoss EAP 7 仍支持 JMS 1.1 API,所以您不需要修改您的代码。

JBoss EAP 7 修改了默认的远程连接器和端口。关于这种改动的细节,请参考更新远程 URL 连接器和端口

如果您用 migrate 操作移您的服务器配置,旧的设置将被保留,您不需要更新 PROVIDER_URL。然而,如果您用新的 JBoss EAP 7 的默认配置来运行,您必须在客户代码里修改 PROVIDER_URL 并使用新的 http-remoting://localhost:8080 设置。更多信息请参考迁移远程命名客户代码

如果您计划将您的代码迁移至 JMS 2.0 API,请参考 helloworld-jms quickstart 里的用法。

5.3.3. 替代 HornetQ API

JBoss EAP 6 包含 org.hornetq 模块,它允许您在代码里使用 HornetQ API

JBoss EAP 7 里 Apache ActiveMQ Artemis 替代了 HornetQ,所以您必须迁移任何使用 HornetQ API 的代码,使其使用 Apache ActiveMQ Artemis API。这个 API 库包含在 org.apache.activemq.artemis 模块里。

ActiveMQ Artemis 是 HornetQ 的演化版本,所以许多概念仍然适用。

5.4. JAX-RS 和 RESTEasy 应用程序的修改

之前的 JBoss EAP 版本捆绑了实现 JAX-RS 1.x 的 RESTEasy 2。JBoss EAP 7 附带实现 JAX-RS 2.0(由 JSR 339: JAX-RS 2.0: The Java API for RESTful Web Services 规格定义)的 RESTEasy 3。关于用于 RESTful Web Service 的 Java API 的更多信息,请参考 JAX-RS 2.0 API 规格

JBoss EAP 7 里包含的 Jackson 版本已有改变。之前的 JBoss EAP 包含的是 Jackson 1.9.9,而 JBoss EAP 7 现在包含 Jackson 2.6.3 或更高的版本。

This section describes how these changes might impact applications that use RESTEasy or JAX-RS.

5.4.1. RESTEasy 已舍弃的类

Interceptor 和 MessageBody 类

JSR 311: JAX-RS: The Java™ API for RESTful Web Services did not include an interceptor framework, so RESTEasy 2 provided one. JSR 339: JAX-RS 2.0: The Java API for RESTful Web Services introduced an official interceptor and filter framework, so the interceptor framework included in RESTEasy 2 is now deprecated, and is replaced by the JAX-RS 2.0 compliant interceptor facility in RESTEasy 3.x. The relevant interfaces are defined in the javax.ws.rs.ext package of the jaxrs-api module.

注意

之前 RESTEasy 版本的所有拦截器都可以和新的 JAX-RS 2.0 过滤器和拦截器接口并行运行。

For more information about interceptors, see RESTEasy Interceptors in Developing Web Services Applications for JBoss EAP.

关于新的替代 API 的更多信息,请参考 RESTEasy JAX-RS 3.0.13.Final API 或更新的版本。

Client API

resteasy-jaxrs 里的 RESTEasy 客户框架已被兼容 JAX-RS 2.0 的 resteasy-client 模块替代。因此,某些 RESTEasy Client API 类和方法已被舍弃。

注意

关于 org.jboss.resteasy.client.jaxrs API 类的更多信息,请参考 RESTEasy JAX-RS JavaDoc

StringConverter

RESTEasy 3.x 已舍弃了 org.jboss.resteasy.spi.StringConverter 类。这个功能可以用 JAX-RS 2.0 jax.ws.rs.ext.ParamConverterProvider 类替代。

5.4.2. 已删除或变成 protected 权限的 RESTEasy 类

ResteasyProviderFactory 的 Add 系列方法

在 RESTEasy 3.0 里,大部分 org.jboss.resteasy.spi.ResteasyProviderFactory add() 方法已被删除或权限变为 protected。例如,addBuiltInMessageBodyReader{}addBuiltInMessageBodyWriter() 方法已被删除而 addMessageBodyReader()addMessageBodyWriter() 方法的权限已变成 protected。

现在您应该使用 registerProvider()registerProviderInstance() 方法。

RESTEasy 3 里删除的其他类

指定 JAX-RS 方法的响应应该在服务器上缓存的 @org.jboss.resteasy.annotations.cache.ServerCached 注解,已从 RESTEasy 3 删除且必须从应用程序代码里删除。

5.4.3. 其他 RESTEasy 修改

SignedInput 和 SignedOuput
  • 用于 resteasy-cryptoSignedInputSignedOutput 必须将 RequestResponse 对象里的 Content-Type 设置为 multipart/signed,或者使用 @Consumes@Produces 注解。
  • 通过在 @Produces@Consumes 注解里设置 application/pkcs7-signature MIME 类型,SignedOutputSignedInput 可以用来以二进制形式返回 "application/pkcs7-signature" MIME 类型。
  • 如果 @Produces@Consumestext/plain MIME 类型,SignedOutput 将用 base64 编码并作为 String 发送。
安全过滤器

@RolesAllowed@PermitAll@DenyAll 的安全过滤器现在返回 "403 Forbidden" 而不是 "401 Unauthorized"。

客户端过滤器

当您使用之前版本的 RESTEasy client API 时,新的 JAX-RS 2.0 客户端过滤器不会被绑定和运行。

对异步 HTTP 的支持

Because the JAX-RS 2.0 specification adds asynchronous HTTP support using the @Suspended annotation and the AsynResponse interface, the RESTEasy proprietary API for asynchronous HTTP has been deprecated and might be removed as soon as RESTEasy 3.1. The asynchronous Tomcat and asynchronous JBoss Web modules have also been removed from the server installation. If you are not using the Servlet 3.0 container or higher, asynchronous HTTP server-side processing will be simulated and run synchronously in same request thread.

服务器端的缓存

服务器端的缓存设置已经改变,更多信息请参考 RESTEasy Documentation

5.4.4. 对 RESTEasy SPI 的修改

SPI 异常

我们已舍弃所有的 SPI 失败异常,不再在内部使用它们。它们已被对应的JAX-RS 2.0 异常所替代。

已舍弃的异常jaxrs-api 模块里的替代异常

org.jboss.resteasy.spi.ForbiddenException

javax.ws.rs.ForbiddenException

org.jboss.resteasy.spi.MethodNotAllowedException

javax.ws.rs.NotAllowedException

org.jboss.resteasy.spi.NotAcceptableException

javax.ws.rs.NotAcceptableException

org.jboss.resteasy.spi.NotFoundException

javax.ws.rs.NotFoundException

org.jboss.resteasy.spi.UnauthorizedException

javax.ws.rs.NotAuthorizedException

org.jboss.resteasy.spi.UnsupportedMediaTypeException

javax.ws.rs.NotSupportedException

InjectorFactory 和 Registry

InjectorFactoryRegistry SPI 已有改动。如果您按照文档和支持来使用 RESTEasy,这不应该成为问题。

5.4.5. Jackson 提供者的变动

JBoss EAP 7 里包含的 Jackson 版本已有改变。之前的 JBoss EAP 包含的是 Jackson 1.9.9,而 JBoss EAP 7 现在包含 Jackson 2.6.3 或更高的版本。因此,Jackson 提供者已从 resteasy-jackson-provider 变为 resteasy-jackson2-provider

升级至 resteasy-jackson2-provider 要求修改一些软件包。例如,Jackson 注解软件包已从 org.codehaus.jackson.annotate 改成 com.fasterxml.jackson.annotation

To switch your application to use the default provider that was included in the previous release of JBoss EAP, see Switching the Default Jackson Provider in Developing Web Services Applications for JBoss EAP.

5.4.6. Spring RESTEasy 集成的修改

Spring 4.0 框架引入了对 Java 8 的支持。如果您计划集成 RESTEasy 3.x 和 Spring,请确保在部署里指定最低的 Spring 版本为 4.2.x,因为这是 JBoss EAP 7 支持的最早的稳定版本。

5.4.7. RESTEasy Jettison JSON 提供者的修改

JBoss EAP 7 已舍弃了 RESTEasy Jettison JSON 提供者,默认不再将其添加到部署里。我们鼓励您切换至我们推荐的 RESTEasy Jackson 提供者。如果您宁愿继续使用 Jettison 提供者,您必须在 jboss-deployment-descriptor.xml 文件里为其定义一个显性依赖关系,如下例所示。

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
  <deployment>
    <exclusions>
      <module name="org.jboss.resteasy.resteasy-jackson2-provider"/>
      <module name="org.jboss.resteasy.resteasy-jackson-provider"/>
    </exclusions>
    <dependencies>
      <module name="org.jboss.resteasy.resteasy-jettison-provider" services="import"/>
    </dependencies>
  </deployment>
</jboss-deployment-structure>

For more information about how to define explicit dependencies, see Add an Explicit Module Dependency to a Deployment in the JBoss EAP Development Guide.

5.5. CDI 1.2 应用程序的修改

JBoss EAP 7 includes support for CDI 1.2. As a result, applications written using CDI 1.0 might see some changes in behavior when migrated to JBoss EAP 7. This section summarizes only a few of those changes.

您可以在下列引用里找到关于 Weld 和 CDI 1.2 的更多信息:

Bean 归档

已启用的 bean 的 Bean 类必须部署在 bean 归档里以确保被 CDI 扫描并发现和处理 bean 类。

在 CDI 1.0 里,对于应用程序客户、EJB 或库 JAR,如果归档的 META-INF/ 目录包含了 beans.xml,或者是 WAR 的 WEB-INF/ 目录包含了 beans.xml 文件,这个就被定义为显性的 bean 归档。

CDI 1.1 引入了隐性的 bean 归档,也就是包含一个或多个带有 bean 定义注解 bean 类或者会话 bean 的归档。隐性的 bean 归档会被 CDI 扫描,在类型发现过程中,只有带有 bean 定义注解的类会被发现。详情请参考Java EE 平台的上下文和依赖关系注入里的类型和 Bean 的发现

Bean 归档具有 allannotatednone 发现模式。包含不带版本的 beans.xml 文件的 bean 归档的默认发现模式是 all。包含 1.1 或更高版本的 beans.xml 文件的 bean 归档必须指定 bean-discovery-mode 属性。这个属性的默认值是 annotated

在下列情况下归档不是 Bean 归档:

  • 它包含 bean-discovery-modenonebeans.xml 文件。
  • 它包含不带有 beans.xml 文件的 CDI 扩展。

在下列情况下归档是显性的 Bean 归档:

  • 归档包含版本为 1.1 或更高的 beans.xml 文件,且 bean-discovery-mode 模式为 all
  • 归档包含没有版本号的 beans.xml 文件。
  • 归档包含空的 beans.xml 文件。

在下列情况下归档是隐性的 Bean 归档:

  • 归档包含一个或多个带有 bean 定义注解 bean 类或者会话 bean,即使它没有包含 beans.xml 文件。
  • 归档包含 bean-discovery-modeannotatedbeans.xml 文件。

CDI 1.2 将 bean 定义注解限制为:

  • @ApplicationScoped@SessionScoped@ConversationScoped@RequestScoped 注解。
  • 所有其他的普通作用域类型
  • @Interceptor@Decorator 注解
  • 使用 @Stereotype 的所有原型注解
  • @Dependent 作用域注解

关于 Bean 归档的更多信息,请参考Java EE 平台的上下文和依赖关系注入里的 Bean 归档

会话解析(Conversation Resolution)的说明

会话上下文生命周期已被修改以防止和 CDI Specification Issue CDI-411 里描述的 Servlet 规格冲突。会话作用域在所有 Servlet 请求期间都时是活动的,它不应该阻止其他 Serlet 或 Servlet 过滤器设置请求主体或字符编码。

Observer 解析

CDI 1.2 已部分地重写了事件解析(Event resolution)。在 CDI 1.0 里,如果一个 observer 方法具有所有的事件限定符,事件将被递送给它。在 CDI 1.2 里,如果一个 observer 方法没有事件限定符或只有一个子集,事件将被递送给它。

5.6. 迁移显性模块依赖关系

之前 JBoss EAP 版本里引入模块化类加载系统和 JBoss Modules 允许对应用程序可用的类进行细颗粒度的控制。这个功能允许您用应用程序的 MANIFEST.MFjboss-deployment-structure.xml 部署描述符文件配置显性的模块依赖关系。

如果您在应用程序里定义了显性的模块依赖关系,您应该意识到 JBoss EAP 7 里下列的变化。

复查依赖关系的可用性

JBoss EAP 里包含的模块已经改动。当您迁移应用程序至 JBoss EAP 7 时,请复查您的 MANIFEST.MFjboss-deployment-structure.xml 文件以确保它们没有引用本版本已删除的模块。

要求注解扫描的依赖关系

在之前 JBoss EAP 版本里,如果依赖关系包含了在注解扫描时需要处理的注解,如声明 EJB 拦截器时,您会被要求在新的 JAR 文件里生成和包括 Jandex 索引并在 MANIFEST.MFjboss-deployment-structure.xml 部署描述符文件里设置一个标记。

JBoss EAP 7 现在为静态模块提供了注解索引的运行时自动生成,所以您不再需要手动生成它们。然而,您仍需要添加 annotations 标记到应用程序的 MANIFEST.MFjboss-deployment-structure.xml 文件(如下所示)。

MANIFEST.MF 文件里的注解标记示例

Dependencies: com.company.my-ejb annotations, com.company.other

jboss-deployment-structure.xml 文件里的注解标记示例

<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="com.company.my-ejb" annotations="true"/>
      <module name="com.company.other"/>
    </dependencies>
  </deployment>
</jboss-deployment-structure>

5.7. Hibernate 和 JPA 迁移的修改

5.7.1. Hibernate ORM 3.0

The integration classes that made it easier to use Hibernate ORM 3 in the previous release were removed from JBoss EAP 7. If your application still uses Hibernate ORM 3 libraries, it is strongly recommended that you migrate your application to use Hibernate ORM 5 as Hibernate ORM 3 will no longer work in JBoss EAP without a lot of effort. If you can not migrate to Hibernate ORM 5, you must define a custom JBoss Module for the Hibernate ORM 3 JARs and exclude the Hibernate ORM 5 classes from your application.

5.7.2. Hibernate ORM 4.0 - 4.3

If your application needs second-level cache enabled, you should migrate to Hibernate ORM 5, which is integrated with Infinispan 8.x.

Applications written with Hibernate ORM 4.x can still use Hibernate ORM 4.x. You must define a custom JBoss module for the Hibernate ORM 4.x JARs and exclude the Hibernate ORM 5 classes from your application. However, it is strongly recommended that you rewrite your application code to use Hibernate ORM 5. For information about migrating to Hibernate ORM 5, see Migrating to Hibernate ORM 5.

5.7.3. Hibernate ORM 5

If your application contains a persistence.xml file or the code uses the @PersistenceContext or @PersistenceUnit annotations, JBoss EAP 7 detects this during deployment and assumes the application uses JPA. It implicitly adds the Hibernate ORM 5 libraries plus a few other dependencies to your application class path and defaults to using these libraries.

5.7.4. Migrating to Hibernate ORM 5

This section highlights the changes you need to make when migrating from Hibernate ORM version 4.3 to version 5. For more information about the changes implemented between Hibernate ORM 4 and Hibernate ORM 5, see the Hibernate ORM 5.0 Migration Guide.

Removed and Deprecated Classes

The following deprecated classes were removed from Hibernate ORM 5.

Other Changes to Classes and Packages
Type Handling
  • Built-in org.hibernate.type.descriptor.sql.SqlTypeDescriptor implementations no longer auto-register themselves with org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry. Applications using custom SqlTypeDescriptor implementations that extend the built-in implementations and rely on that behavior must be updated to call SqlTypeDescriptorRegistry.addDescriptor() themselves.
  • For IDs defined as generated UUIDs, some databases require you to explicitly set the @Column(length=16) in order to generate BINARY(16) so that comparisons work properly.
  • For EnumType mappings defined in the hbm.xml, where you want javax.persistence.EnumType.STRING name-mapping, this configuration must be explicitly stated by using either the useNamed(true) setting or by specifying a VARCHAR value of 12.
Transaction Management
Other Hibernate ORM 5 Changes
  • The cfg.xml files are again fully parsed and integrated with events, security, and other functions.
  • The properties loaded from the cfg.xml using the EntityManagerFactory did not previously prefix names with hibernate. This has now been made consistent.
  • The configuration is no longer serializable.
  • The org.hibernate.dialect.Dialect.getQuerySequencesString() method now retrieves catalog, schema, and increment values.
  • The AuditConfiguration modifier was removed from org.hibernate.envers.boot.internal.EnversService.
  • The AuditStrategy method parameters were changed to remove the obsolete AuditConfiguration and use the new EnversService.
  • Various classes and interfaces in the org.hibernate.hql.spi package and subpackages have been moved to the new org.hibernate.hql.spi.id package. This includes the MultiTableBulkIdStrategy class and the AbstractTableBasedBulkIdHandler, TableBasedDeleteHandlerImpl, and TableBasedUpdateHandlerImpl interfaces and their subclasses.
  • There was a complete redesign of property access contracts.
  • Valid hibernate.cache.default_cache_concurrency_strategy setting values are now defined using the org.hibernate.cache.spi.access.AccessType.getExternalName() method rather than the org.hibernate.cache.spi.access.AccessType enum constants. This is more consistent with other Hibernate settings.

5.8. Hibernate Search 的修改

JBoss EAP 7 附带的 Hibernate Search 版本已被修改。之前版本的 JBoss EAP 附带 Hibernate Search 4.6.x,而 JBoss EAP 7 附带 Hibernate Search 5.5.x。

Hibernate Search 5.5 is built upon Apache Lucene 5.3.1. If you use any native Lucene APIs, be sure to align with this version. The Hibernate Search 5.5 API wraps and hides the complexity of many of the Lucene API changes made between version 3 and version 5, however, some classes are now deprecated, renamed, or repackaged. This section describes how these changes might impact your application code.

Hibernate Search Mapping 的修改

内嵌关系的 ID 字段的索引

当使用 @IndexedEmbedded 注解来包含相关实体的字段时,相关实体的 id 字段不再被包含。您可以用 @IndexedEmbedded 注解的 includeEmbeddedObjectId 属性启用对 id 的包含。

@IndexedEmbedded(includeEmbeddedObjectId=true)
数字和日期索引格式的修改

数字和日期现在默认用数值型字段作为索引。intlongfloatdouble类型的属性及对应的 Wrapper 类都不再用字符串进行索引了。它们现在改为使用 Lucene 的数字编码来索引。id 字段是这个规则的一个例外。即使它们用数字类型来表达,它们的索引默认仍使用字符串键值。@NumericField 现在已废弃,除非您希望为数字编码定制精度。您可以通过制定一个字符串编码的字段桥(field bridge)来保留旧的基于字符串的索引格式。对于整型,它就是 org.hibernate.search.bridge.builtin.IntegerBridge。关于其他可用的公用字段桥,请参考org.hibernate.search.bridge.builtin软件包。

DateCalendar 不再以字符串为索引。它们改为用长整型来代表自 1970 年 1 月1 日 00:00:00 GMT 以来的毫秒数。您可以用新的EncodingType 枚举来切换索引格式。例如:

@DateBridge(encoding=EncodingType.STRING)
@CalendarBridge(encoding=EncodingType.STRING)

数字和日期的编码修改是很重要的,这对应用程序的行为有重大影响。如果以字段为目标的查询之前是用字符串编码,而现在是数字编码,您就必须更新这个查询。数字型的字段必须用 NumericRangeQuery 进行搜索。您也必须确保所有按目标分类的字段都是用字符串编码的。如果您使用 Search 查询 DSL,正确的查询应该会自动创建。

其他的 Hibernate Search 修改

  • 我们改进了排序选项,排序选项的错误字段编码现在会导致 runtime 异常抛出。如果预先知道排序使用的字段,Lucene 也提供了更高性能的排序方式。Hibernate Search 5.5 提供了新的 @SortableField 注解及其多值选项 @SortableFields。更多信息请参考《从 Hibernate Search 5.4 到 5.5 的迁移指南》
  • Lucene SortField API 要求进行下列程序代码的修改。

    在以前的 JBoss EAP 6 版本里,您可以像下面这样设置排序字段的类型。

    fulltextQuery.setSort(new Sort(new SortField("title", SortField.STRING)));

    下面是在 JBoss EAP 7 进行设置的例子。

    fulltextQuery.setSort(new Sort(new SortField("title", SortField.Type.STRING)));
  • 既然 SearchFactory 只应被 ORM 集成使用,它从 hibernate-search-engine 模块移至 hibernate-search-orm 模块。其他集成应该专门地依赖于 SearchIntegrator,它替代了已舍弃的 SearchFactoryIntegrator
  • 枚举值 SpatialMode.GRID 被重命名为 SpatialMode.HASH
  • FullTextIndexEventListener 现在是 final 类。如果您目前继承了这个类,您必须找到替代方案来实现相同的功能。
  • hibernate-search-analyzers 模块已删除。我们推荐的方法是直接使用合适的 Lucene 工件,例如 org.apache.lucene:lucene-analyzers-common
  • The JMS controller API has changed. The JMS back-end dependency on Hibernate ORM was removed so that it could be used in other non-ORM environments. A consequence is that implementors of org.hibernate.search.backend.impl.jms.AbstractJMSHibernateSearchController must adjust to the new signature. This class is an internal class and it is recommended to use it as an example instead of extending it.
  • org.hibernate.search.spi.ServiceProvider SPI 已被重构。如果您要集成旧的服务合约,新合约的细节请参考 ServiceManagerServiceStartableStoppableHibernate Search 5.5 Javadoc
  • 如果您已保留了 Lucene 3.x 生成的索引且没有用 Hibernate Search 5.0 或更新的版本进行重构,您将遇到 IndexFormatTooOldException。我们推荐您用 mass indexer 重构索引。如果您不能这样做,请试图使用 Lucene 的 IndexUpgrader。如果默认行为已修改,您必须小心地更新 Hibernate Search 映射。更多的信息请参考《Apache Lucene 迁移指南》
  • JBoss EAP 7 已将 Apache Lucene 升级为 3.6 到 5.3。如果您的代码直接导入了 Lucene 代码,相关细节请参考《Apache Lucene 迁移指南》。其他信息可以在 Lucene 更新日志里找到。
  • 当使用 @Field(indexNullAs=) 来对索引里的空 marker 值编码时,这个 marker 的类型必须和在相同字段里其他索引值兼容。例如,之前可能对数值型字段用字符串 "null" 编码空的值。现在这是不允许的。相反,您必须选择一个数字来表示 null 值,如 -1
  • 我们对 faceting 引擎进行了重大改进。多数改动不会影响 API。一个值得注意的例外是您必须注解任何要用 @Facet@Facets 注解进行 faceting 的字段。

Hibernate Search 重命名和重打包的类

下面是被重新打包或重命名的 Hibernate Search 类的列表。

之前的软件包和类新的软件包和类

org.hibernate.search.Environment

org.hibernate.search.cfg.Environment

org.hibernate.search.FullTextFilter

org.hibernate.search.filter.FullTextFilter

org.hibernate.search.ProjectionConstants

org.hibernate.search.engine.ProjectionConstants

org.hibernate.search.SearchException

org.hibernate.search.exception.SearchException

org.hibernate.search.Version

org.hibernate.search.engine.Version

Lucene - 重命名和重打包的类

查询解析器已移至新的模块,所在软件包从 org.apache.lucene.queryParser.QueryParser 改为 org.apache.lucene.queryparser.classic.QueryParser

许多 Lucene 分析器都已重构,导致软件包的变动。要寻找替代的软件包,请查看 Apache Lucene 文档

某些 Apache Solr 工具类,如 TokenizerFactoryTokenFilterFactory,都已移至 Apache Lucence。如果您的应用程序使用了这些工具或自定义的分析器,您必须找到 Apache Lucene 里新的软件包名称。

更多的信息请参考《Apache Lucene 迁移指南》

Hibernate Search 已舍弃的 API

关于 Hibernate Search 已舍弃的接口、类、枚举、注解类型、方法、构造器和枚举常量的完整列表,请参考 Hibernate Search 已舍弃的 API 文档

Hibernate Search 已舍弃的接口
接口描述

org.hibernate.search.store.IndexShardingStrategy

从 Hibernate Search 4.4 开始已舍弃,可能在 Search 5 里删除。现在请使用 ShardIdentifierProvider

org.hibernate.search.store.Workspace

This interface will be moved and should be considered non-public API. For more information, see HSEARCH-1915.

Hibernate Search 已舍弃的类
描述

org.hibernate.search.filter.FilterKey

自定义的过滤器键已舍弃且在 Hibernate Search 6 里将被删除。从 Hibernate Search 5.1 开始,用于缓存 Lucene 过滤器的键将基于给定的过滤器参数自动计算。

org.hibernate.search.filter.StandardFilterKey

自定义的过滤器键已舍弃且在 Hibernate Search 6 里将被删除。从 Hibernate Search 5.1 开始,用于缓存 Lucene 过滤器的键将基于给定的过滤器参数自动计算。

Hibernate Search 已舍弃的枚举
枚举描述

org.hibernate.search.annotations.FieldCacheType

请删除已舍弃的 CacheFromIndex 注解。详情请参考Hibernate Search 已舍弃的注解

Hibernate Search 已舍弃的注解
注解描述

org.hibernate.search.annotations.CacheFromIndex

请删除这个注解,不需要其他接替者。

org.hibernate.search.annotations.Key

自定义的过滤器缓存键已舍弃且在 Hibernate Search 6 里将被删除。从 Hibernate Search 5.1 开始,过滤器缓存键将基于过滤器参数自动确定,所以不再需要提供键对象。

Hibernate Search 已舍弃的方法
方法描述

org.hibernate.search.FullTextSharedSessionBuilder.autoClose()

没有接替者

org.hibernate.search.FullTextSharedSessionBuilder.autoClose(boolean)

没有接替者

org.hibernate.search.cfg.IndexedMapping.cacheFromIndex(FieldCacheType…​)

它将被删除且没有接替者。

org.hibernate.search.cfg.EntityDescriptor.getCacheInMemory()

它将被删除且没有接替者。

org.hibernate.search.cfg.ContainedInMapping.numericField()

请改为调用 field().numericField()

org.hibernate.search.cfg.EntityDescriptor.setCacheInMemory(Map<String, Object>)

它将被删除且没有接替者。

org.hibernate.search.MassIndexer.threadsForSubsequentFetching(int)

这个方法将被删除。

org.hibernate.search.query.dsl.FuzzyContext.withThreshold(float)

请使用 FuzzyContext.withEditDistanceUpTo(int)

Hibernate Search 已舍弃的构造器
构造器描述

org.hibernate.search.cfg.NumericFieldMapping(PropertyDescriptor, EntityDescriptor, SearchMapping)

请改为使用 NumericFieldMapping.NumericFieldMapping(String, PropertyDescriptor, EntityDescriptor, SearchMapping)

影响高级集成器的修改

本节描述了非公用 API 的修改。它们不应该影响普通开发人员,因为这些工件只应该由继承 Hibernate Search 框架的集成者访问。

5.9. 迁移 Entity Bean 至 JPA

Java EE 7 对 EJB Entity Bean 的支持是可选的,它们不再受到支持。这意味着迁移到 JBoss EAP 7 时,您必须重写 CMP(container-managed persistence)和 BMP(bean-managed persistence)来使用 Java Persistence API (JPA) 实体。

在以前的 JBoss EAP 版本里,Entity Bean 是通过应用程序代码继承 javax.ejb.EntityBean 类并实现所需方法来创建的。它们然后在 ejb-jar.xml 文件里进行配置,CMP Entity Bean 用包含值为 Container<persistence-type> 子元素的 <entity> 元素来指定。BMP entity bean 用包含值为 Bean 的子元素 <persistence-type><entity> 元素来指定。

在 JBoss EAP 7 里,您必须用 Java Persistence API (JPA) 实体替换任何 CMP 和 BMP Entity Bean。JPA 实体使用 javax.persistence.* 类创建并在 persistence.xml 文件里定义的。

下面是一个 JPA 实体类示例。

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
// User is a keyword in some SQL dialects!
@Table(name = "MyUsers")
public class MyUser {
    @Id
    @GeneratedValue
    private Long id;

    @Column(unique = true)
    private String username;
    private String firstName;
    private String lastName;

    public Long getId() {
        return id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

下面是一个 persistence.xml 文件示例。

<persistence version="2.1"
      xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
        http://xmlns.jcp.org/xml/ns/persistence
        http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="my-unique-persistence-unit-name">
    <properties>
      // properties...
    </properties>
  </persistence-unit>
</persistence>

关于 JPA 实体的示例,请参考 JBoss EAP 7 附带的 bmtcmthibernate5 Quickstarts 例程。

5.10. JPA 持久化属性的修改

我们添加了新的持久性属性 jboss.as.jpa.deferdetach 来提供对之前版本的 JBoss EAP 里的持久性行为的支持。

jboss.as.jpa.deferdetach 属性控制每次 EntityManager 调用后非 JTA 事务线程里使用的事务作用域的持久化上下文是否分离加载的实体,或者等待至持久化上下文关闭。例如,当 Session Bean 调用结束时。这个属性值默认是 false,表示实体在每次 EntityManager 调用后被分离或清除。这是 JPA 规格里定义的正确的默认行为。如果属性被设置为 true,实体在持久化上下文关闭前不会被分离。

在 JBoss EAP 5 里,持久化的行为就像将 jboss.as.jpa.deferdetach 属性设置为 true 一样。要在迁移至 JBoss EAP 7 时获得相同的行为,您必须在 persistence.xml 里将 jboss.as.jpa.deferdetach 属性设置为 true,如下例所示。

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
    <persistence-unit name="EAP5_COMPAT_PU">
    <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
    <properties>
         <property name="jboss.as.jpa.deferdetach" value="true" />
    </properties>
  </persistence-unit>
</persistence>

在 JBoss EAP 6 里,持久化的行为就像将 jboss.as.jpa.deferdetach 属性设置为 false 一样。这在 JBoss EAP 7 里是相同的,所以迁移应用程序时不需要进行修改。

5.11. 迁移 EJB 客户代码

JBoss EAP 7 修改了默认的远程连接器和端口。关于这种改动的细节,请参考更新远程 URL 连接器和端口

如果您使用了 migrate 操作来迁移服务器配置,旧的设置将被保留,您不需要修改下面的细节。然而,如果您用新的 JBoss EAP 7 默认配置运行,您必须进行下列修改。

5.11.1. 更新默认的远程连接端口

jboss-ejb-client.properties 文件里将远程连接端口值从 4447 改为 8080

下面是之前和当前版本里的 jboss-ejb-client.properties 文件示例。

示例:JBoss EAP 6 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

示例:JBoss EAP 7 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

5.11.2. 更新默认的连接器

如果您使用新的 JBoss EAP 7 配置运行,默认的连接器已从 remote 改为 http-remoting。这次改动影响了使用某个版本里的库并连接不同版本的服务器的客户。

  • 如果客户应用程序使用 JBoss EAP 6 里的 EJB 客户库并希望连接至 JBoss EAP 7 服务器,您必须配置服务器通过 8080 之外的端口开放 remote 连接器。然后客户必须使用新配置的连接器进行连接。
  • 使用 JBoss EAP 7 里的 EJB 客户库并希望连接至 JBoss EAP 6 服务器的客户应用程序必须意识到服务器实例没有使用 http-remoting 而是 remoting 连接器。这是通过定义新的客户端连接属性来实现的。

    remote.connection.default.protocol=remote

5.11.3. 迁移远程命名客户代码

如果您用新的默认 JBoss EAP 7 配置运行,你必须修改客户代码以使用新的默认远程端口和连接器。

下面是 JBoss EAP 6 里如何在客户代码里指定远程命名属性的例子。

java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory
java.naming.provider.url=remote://localhost:4447

下面是 JBoss EAP 7 里如何在客户代码里指定远程命名属性的例子。

java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory
java.naming.provider.url=http-remoting://localhost:8080

5.12. 迁移部署计划配置

The Java EE Application Deployment specification (JSR-88) was intended to define a standard contract to enable tools from multiple providers to configure and deploy applications on any Java EE platform product. The contract required Java EE Product Providers to implement the DeploymentManager and other javax.enterprise.deploy.spi interfaces to be accessed by the Tool Providers. In case of JBoss EAP 6, a deployment plan is identified by an XML descriptor named deployment-plan.xml that is bundled in a ZIP or JAR archive.

我们已很少采用这个规格,因为多数应用服务器产品提供了自己更“功能丰富”的部署方案。出于这个原因,Java EE 7 取消了对 JSR-88 的支持,所以 JBoss EAP 7 也不再支持。

If you used JSR-88 to deploy your application, you must now use another method to deploy the application. The JBoss EAP management CLI deploy command provides a standard way to deploy archives to standalone servers or to server groups in a managed domain. For more information about the management CLI, see the Management CLI Guide.

5.13. 迁移自定义应用程序阀

您必须手动迁移自定义阀或任何在 jboss-web.xml XML 文件里定义的阀。这包含通过继承 org.apache.catalina.valves.ValveBase 类创建以及在 jboss-web.xml 描述符文件的 <valve> 元素里配置的阀。

重要

自定义阀和 jboss-web.xml 文件里定义的阀必须被重写或用对应的 Undertow 内置处理程序替代。关于映射阀到 Undertow 处理程序的更多信息,请参考迁移 JBoss Web 阀

验证阀必须用 Undertow 内嵌的验证机制手动替换。

迁移部署里配置的阀

在 JBoss EAP 6,您可以在 jboss-web.xml 描述符文件里进行配置来定义应用程序级别的自定义阀。而在 JBoss EAP 7 里,您可以用 Undertow 处理程序来实现。

下面是 JBoss EAP 6 里的 jboss-web.xml 文件配置的阀的示例。

<jboss-web>
    <valve>
        <class-name>org.jboss.examples.MyValve</class-name>
​        <param>
    ​        <param-name>myParam</param-name>
​            <param-value>foobar</param-value>
    ​    </param>
    </valve>
</jboss-web>

For more information about how to create and configure custom handlers in JBoss EAP, see Creating Custom Handlers in the JBoss EAP Development Guide.

迁移自定义验证器阀

关于如何迁移验证器阀的信息,请参考安全性应用程序的修改

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

用 Undertow 替代 JBoss Web 要求修改 JBoss EAP 7 的安全性配置。

5.14.1. 迁移

验证器阀(Authenticator Valve)必须用 Undertow 内置的验证机制手动替代。关于如何迁移验证器阀的信息,请阅读下面的章节。

5.14.3. 其他安全性应用程序的修改

For information about the differences in SSO configuration with Kerberos, see Differences from Configuring Previous Versions JBoss EAP in How to Set Up SSO with Kerberos for JBoss EAP.

5.15. JBoss Logging 的修改

如果您的应用程序使用了 JBoss Logging,请注意 JBoss EAP 7 已舍弃在 org.jboss.logging 软件包里进行注解。它们被移至 org.jboss.logging.annotations 软件包,所以您必须更新源码来导入新的软件包。

这些注解也已移至单独的 Maven groupId:artifactId:version (GAV) ID,所以您需要在 pom.xml 文件里为 org.jboss.logging:jboss-logging-annotations 添加一个新的依赖关系。

注意

只移动了日志注解。org.jboss.logging.BasicLoggerorg.jboss.logging.Logger 仍存在于 org.jboss.logging 软件包里。

下表列出已舍弃的注解类和对应的接替者。

表 5.1. 已舍弃的 Logging 注解的接替者

已舍弃的类替代的类

org.jboss.logging.Cause

org.jboss.logging.annotations.Cause

org.jboss.logging.Field

org.jboss.logging.annotations.Field

org.jboss.logging.FormatWith

org.jboss.logging.annotations.FormatWith

org.jboss.logging.LoggingClass

org.jboss.logging.annotations.LoggingClass

org.jboss.logging.LogMessage

org.jboss.logging.annotations.LogMessage

org.jboss.logging.Message

org.jboss.logging.annotations.Message

org.jboss.logging.MessageBundle

org.jboss.logging.annotations.MessageBundle

org.jboss.logging.MessageLogger

org.jboss.logging.annotations.MessageLogger

org.jboss.logging.Param

org.jboss.logging.annotations.Param

org.jboss.logging.Property

org.jboss.logging.annotations.Property

5.16. JavaServer Faces (JSF) 代码的修改

取消对 JSF 1.2 的支持

JBoss EAP 6 允许您通过创建 jboss-deployment-structure.xml 文件继续使用 JSF 1.2。

JBoss EAP 7 包含 JSF 2.2 且不再支持 JSF 1.2 API。如果您的应用程序使用 JSF 1.2,您必须重写代码以使用 JSF 2.2。

JSF 2.1 和 JSF 2.2 间的兼容性问题

JSF 2.1 和 JSF 2.2 API 不是完全兼容的。FACELET_CONTEXT_KEY 常量从 com.sun.faces.facelets.FACELET_CONTEXT 改成了 javax.faces.FACELET_CONTEXT。编译器内联这个值,根据某个版本编译的代码将无法在其他版本里使用。

用 JSF 2.1 API 编译的包含和下面例子相似的代码的应用程序,如果在使用 JSF 2.2 API 的 JBoss EAP 7 里运行会导致 NullPointerException。要修复这个问题,您必须用 JSF 2.2 API 重新编译应用程序。

Object obj = FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);

详情请参考 JAVASERVERFACES_SPEC_PUBLIC-1257

5.17. 模块类加载的修改

在 JBoss EAP 7 里,多个模块包含相同的类或软件包时的类加载行为已修改。

假设有两个模块 MODULE_AMODULE_B,彼此依赖并包含一些相同的软件包。在 JBoss EAP 6 里,从依赖关系加载的类或软件包优先于 module.xml 文件的 resource-root 元素里指定的。这意味着 MODULE_A 可以看到 MODULE_B 的软件包而 MODULE_B 可以看到 MODULE_A 的软件包。这种行为让人困惑且可能导致冲突。而 JBoss EAP 7 已修改了这种行为。现在 module.xml 文件的 resource-root 元素指定的类或软件包优先于依赖关系所指定的。这意味着 MODULE_A 只可以看到 MODULE_A 的软件包而 MODULE_B 可以看到 MODULE_B 的软件包。这防止了冲突并提供了更合适的行为。

If you have defined custom modules that include resource-root libraries or packages that contain classes that are duplicated in their module dependencies, you might see ClassCastException, LinkageError, class loading errors, or other changes in behavior when you migrate to JBoss EAP 7. To resolve these issues, you must configure your module.xml file to ensure only one version of a class is used. This can be accomplished by using either of the following approaches.

  • 您可以避免指定在模块依赖关系里重复类的 resource-root
  • 您可以使用 importsexportsincludeexclude 子元素来控制 module.xml 文件里的类加载。下面是使用 export 元素排除指定软件包里的类的例子。

    <exports>
      <exclude path="com/mycompany/duplicateclassespath/"/>
    </exports>

如果您希望保留现有的行为,你必须通过 filter 元素在过滤 module.xml 文件里 resource-root 的依赖关系软件包。这允许您保留现有的行为而不会看到 JBoss EAP 6 里看到的奇怪的循环。下面是通过 root-resource 过滤指定软件包里的类的例子。

<resource-root path="mycompany.jar">
  <filter>
    <exclude path="com/mycompany/duplicateclassespath"/>
  </filter>
</resource-root>

For more information about modules and class loading, see Class Loading and Modules in the JBoss EAP Development Guide.

5.18. 应用程序群集的修改

5.18.1. 新的群集功能概述

下面描述了从 JBoss EAP 6 迁移至 JBoss EAP 7 时要注意的新的群集功能。

  • JBoss EAP 7 introduces a new public API for building singleton services that significantly simplifies the process. For more information, see Implement an HA Singleton in Developing EJB Applications for JBoss EAP.
  • A singleton deployment can be configured to deploy and start on only a single node in the cluster at a time. For more information, see HA Singleton Deployments in the JBoss EAP Development Guide.
  • You can now define clustered singleton MDBs. For more information, see Clustered Singleton MDBs in Developing EJB Applications for JBoss EAP.
  • JBoss EAP 7 includes the Undertow mod_cluster implementation. This offers a pure Java load balancing solution that does not require an httpd web server. For more information, see Configuring JBoss EAP as a Front-end Load Balancer in the JBoss EAP Configuration Guide.

The remainder of this section describes how clustering changes might impact the migration of your applications to JBoss EAP 7.

5.18.2. Web 会话群集的修改

JBoss EAP 7 引入了新的 Web 会话群集实现。它替代了之前和旧的 JBoss Web 子系统紧耦合的实现。

新的 Web 会话群集实现影响了如何在 jboss-web.xml 描述符文件里配置应用程序。下面是这个文件里保留的群集配置元素。

<jboss-web>
  ...
  <max-active-sessions>...</max-active-sessions>
  ...
  <replication-config>
    <replication-granularity>...</replication-granularity>
    <cache-name>...</cache-name>
  </replication-config>
  ...
</jboss-web>

下表描述了如何实现和 jboss-web.xml 里现已舍弃的元素类似的行为。

配置元素对修改的描述

<max-active-sessions/>

以前,如果活动会话的数量超过了 <max-active-sessions/> 指定的值,创建会话将会失败。

在新的实现里,<max-active-sessions/> 用于启用会话钝化。如果创建会话可能导致活动会话数量超过 <max-active-sessions/>,那么会话管理者已知的最老的会话将会钝化,为新的会话留出空间。

<passivation-config/>

JBoss EAP 7 不再使用这个配置元素及其子元素。

<use-session-passivation/>

以前,钝化是用这个属性启用的。

在新的实现里,钝化是通过为 <max-active-sessions/> 指定非负的值来启用的。

<passivation-min-idle-time/>

以前,会话在成为钝化候选者之前,需要处于活动状态一段最短的时间。这可能导致创建会话失败,即使已启用了钝化。

新的实现不支持这个逻辑,所以避免了拒绝服务(Denial of Service,DoS)漏洞。

<passivation-max-idle-time/>

以前,会话将处于空闲状态一段时间后将被钝化。

新的实现只支持 lazy 钝化。它不支持 eager 钝化。会话只有在需要遵从 <max-active-sessions/> 时才被钝化。

<replication-config/>

新的实现舍弃了大量的子元素。

<replication-trigger/>

Previously, this element was used to determine when session replication was triggered. The new implementation replaces this configuration option with a single, robust strategy. For more information, see Immutable Session Attributes in the JBoss EAP Development Guide.

<use-jk/>

以前,处理给定请求的节点的 instance-id 被附加到 jsessionid,根据 <use-jk/> 所指定的值,它用于不同的负载平衡器,如 mod_jk、mod_proxy_balancer、mod_cluster。

在新的实现里,如果定义了 instance-id,它总是附加到 jsessionid

<max-unreplicated-interval/>

以前,这个配置选项的目的是防止没有修改会话属性时会话时间戳的重复。虽然这听起来不错,但事实上它没有防止任何 RPC,因为无论是否修改了任何会话属性,访问会话都要求缓存事务 RPC。

在新的实现里,会话的时间戳在每次请求时进行复制。这防止了失效切换后的过时的会话元数据。

<snapshot-mode/>

Previously, one could configure <snapshot-mode/> as INSTANT or INTERVAL. Infinispan’s asynchronous replication makes this configuration option obsolete.

<snapshot-interval/>

它只和 <snapshot-mode>INTERVAL</snapshot-mode> 相关。既然 <snapshot-mode/> 已被舍弃,这个选项也已被舍弃。

<session-notification-policy/>

以前,这个属性指定的值定义了触发会话事件的策略。

在新的实现里,这个行为是规格驱动的且是不可配置的。

This new implementation also supports write-through cache stores as well as passivation-only cache stores. Typically, a write-through cache store is used in conjunction with an invalidation cache. The web session clustering implementation in JBoss EAP 6 did not operate correctly when used with an invalidation cache.

5.18.3. Stateful Session EJB 群集的修改

在 JBoss EAP 6 里,您被要求以下列方式之一启用 stateful session beans (SFSBs) 的群集行为。

  • 您可以在 session bena 里添加 org.jboss.ejb3.annotation.Clustered 注解。

    @Stateful
    @Clustered
    public class MyBean implements MySessionInt {
    
       public void myMethod() {
          //
       }
    }
  • 您可以将 <clustered> 元素添加到 jboss-ejb3.xml 文件里。

    <c:clustering>
      <ejb-name>DDBasedClusteredSFSB</ejb-name>
      <c:clustered>true</c:clustered>
    </c:clustering>

JBoss EAP 7 不再要求您启用群集行为。在默认情况下,如果服务器用 HA 配置集启动,SFSB 的状态将自动复制。

您可以用下列方式之一禁用默认的行为。

  • 您可以使用 EJB 3.2 规格里新的 @Stateful(passivationCapable=false) 来禁用单个 stateful session bean 的默认行为。
  • 你也可以通过服务器配置的 ejb3 子系统来在全局禁用这个行为。
注意

如果没有从应用程序里删除 @Clustered 注解,它会被忽略且不会影响到应用程序的部署。

5.18.4. 群集服务的修改

在 JBoss EAP 6,用于群集服务的 API 位于私有模块且不被支持。

JBoss EAP 7 引入了公用群集 API。新的服务被设计为轻量级的、易于注入的且没有外部依赖关系。

  • 新的 org.wildfly.clustering.group.Group 接口提供了对当前群集状态的访问并允许侦听群集成员的变动。
  • 新的 org.wildfly.clustering.dispatcher.CommandDispatcher 接口允许在群集、所有或选择的节点子集里运行代码。

这些服务替代了之前版本里类似的 API,也就是 JBoss EAP 5 的 HAPartition,JBoss EAP 6 里的 GroupCommunicationServiceGroupMembershipNotifierGroupRpcDispatcher

For more information, see Public API for Clustering Services in the JBoss EAP Development Guide.

5.18.5. 迁移群集 HA 单点登录

在 JBoss EAP 6 里,群集范围的 HA 单点登录服务没有可用的公用 API。如果您使用了私有 org.jboss.as.clustering.singleton.* 类,在迁移应用程序至 JBoss EAP 7 时,您必须修改代码以使用新的公用 org.wildfly.clustering.singleton.* 软件包。

For more information about how to implement an HA singleton, see HA Singleton Service in the Development Guide for JBoss EAP.