4.3.7. 调试和解决 Seam 2.2 Booking 例程的运行时错误和异常

在前面的步骤 第 4.3.6 节 “调试和解决 Seam 2.2 Booking 例程的部署错误和异常” 里,您学习了如何调试部署错误,在这个步骤里,您会调试和解决您遇到的运行时错误。

重要

直接使用 Hibernate 的 Seam 2.2 应用程序可以使用包裹在应用程序里的一个 Hibernate 3 版本。而通过 JBoss EAP 6 的 org.hibernate 模块提供的 Hibernate 4,不被 Seam 2.2 支持。这个例子将帮助您在 JBoss EAp 6 运行应用程序。请注意,将 Hibernate 3 包裹在 Seam 2.2 应用程序不是被支持的配置。

过程 4.11. 调试和解决运行时错误和异常

目前,当您部署这个应用程序时,您没有在日志里看到任何错误。但是,当您访问这个程序的 URL 是,日志里就出现了错误。
  1. 问题 - javax.naming.NameNotFoundException: Name 'jboss-seam-booking' not found in context ''
    当您通过浏览器访问 URL http://localhost:8080/seam-booking/ 时,您会看到 "The page isn't redirecting properly" 且日志会包含下列错误:
    SEVERE [org.jboss.seam.jsf.SeamPhaseListener] (http--127.0.0.1-8080-1) swallowing exception: java.lang.IllegalStateException: Could not start transaction
      at org.jboss.seam.jsf.SeamPhaseListener.begin(SeamPhaseListener.java:598) [jboss-seam.jar:]
      (... log messages removed ...)
    Caused by: org.jboss.seam.InstantiationException: Could not instantiate Seam component: org.jboss.seam.transaction.synchronizations
      at org.jboss.seam.Component.newInstance(Component.java:2170) [jboss-seam.jar:]
      (... log messages removed ...)
    Caused by: javax.naming.NameNotFoundException: Name 'jboss-seam-booking' not found in context ''
      at org.jboss.as.naming.util.NamingUtils.nameNotFoundException(NamingUtils.java:109)
      (... log messages removed ...)
    
    它表示:

    NameNotFoundException 表示了 JNDI 命名问题。JNDI 命名规则在 JBoss EAP 6 里已经进行了修改,所以您需要修改查找名称以遵循新的规则。

    如何解决这个问题:

    为了调集试,

    15:01:16,138 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named RegisterAction in deployment unit subdeployment "jboss-seam-booking.jar" of deployment "jboss-seam-booking.ear" are as follows:
      java:global/jboss-seam-booking/jboss-seam-booking.jar/RegisterAction!org.jboss.seam.example.booking.Register
      java:app/jboss-seam-booking.jar/RegisterAction!org.jboss.seam.example.booking.Register
      java:module/RegisterAction!org.jboss.seam.example.booking.Register
      java:global/jboss-seam-booking/jboss-seam-booking.jar/RegisterAction
      java:app/jboss-seam-booking.jar/RegisterAction
      java:module/RegisterAction
      [JNDI bindings continue ...]
    
    日志里一共列出了 8 个 INFO JNDI 绑定,每个都对应一个会话 bean:RegisterAction、BookingListAction、HotelBookingAction、AuthenticatorAction、ChangePasswordAction、HotelSearchingAction、EjbSynchronizations 和 TimerServiceDispatcher。您需要修改 WAR 的 lib/components.xml 文件来使用新的 JNDI 绑定。在日志里,注意 EJB JNDI 绑定都以 "java:app/jboss-seam-booking.jar" 开始。请替换 core:init 元素:
    <!--     <core:init jndi-pattern="jboss-seam-booking/#{ejbName}/local" debug="true" distributable="false"/> -->
    <core:init jndi-pattern="java:app/jboss-seam-booking.jar/#{ejbName}" debug="true" distributable="false"/>
    
    
    然后,您需要添加 EjbSynchronizations 和 TimerServiceDispatcher JNDI 绑定。请添加下列 component 元素到这个文件里:
    <component class="org.jboss.seam.transaction.EjbSynchronizations" jndi-name="java:app/jboss-seam/EjbSynchronizations"/>
    <component class="org.jboss.seam.async.TimerServiceDispatcher" jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/>
    
    
    components.xml 文件应该类似于:
    <?xml version="1.0" encoding="UTF-8"?>
    <components xmlns="http://jboss.com/products/seam/components"
      xmlns:core="http://jboss.com/products/seam/core"
      xmlns:security="http://jboss.com/products/seam/security"
      xmlns:transaction="http://jboss.com/products/seam/transaction"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation=
        "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.2.xsd
         http://jboss.com/products/seam/transaction http://jboss.com/products/seam/transaction-2.2.xsd
         http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.2.xsd
         http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.2.xsd">
    
        <!-- <core:init jndi-pattern="jboss-seam-booking/#{ejbName}/local" debug="true" distributable="false"/> -->
        <core:init jndi-pattern="java:app/jboss-seam-booking.jar/#{ejbName}" debug="true" distributable="false"/>
        <core:manager conversation-timeout="120000"
                      concurrent-request-timeout="500"
                      conversation-id-parameter="cid"/>
        <transaction:ejb-transaction/>
        <security:identity authenticate-method="#{authenticator.authenticate}"/>
        <component class="org.jboss.seam.transaction.EjbSynchronizations"
                jndi-name="java:app/jboss-seam/EjbSynchronizations"/>
        <component class="org.jboss.seam.async.TimerServiceDispatcher"
                jndi-name="java:app/jboss-seam/TimerServiceDispatcher"/>
    </components>
    
    

    通过删除 standalone/deployments/jboss-seam-booking.ear.failed 文件并在相同目录里创建一个空白的 jboss-seam-booking.ear.dodeploy 文件来重新部署应用程序。
  2. 问题 - 应用程序部署和运行无误。当您访问 http://localhost:8080/seam-booking/ 并试图登陆时失败,错误消息为 "Login failed. Transaction failed."。您应该在服务器日志里看到如下异常跟踪信息:
    13:36:04,631 WARN  [org.jboss.modules] (http-/127.0.0.1:8080-1) Failed to define class org.jboss.seam.persistence.HibernateSessionProxy in Module "deployment.jboss-seam-booking.ear.jboss-seam.jar:main" from Service Module Loader: java.lang.LinkageError: Failed to link org/jboss/seam/persistence/HibernateSessionProxy (Module "deployment.jboss-seam-booking.ear.jboss-seam.jar:main" from Service Module Loader)
    ....
    Caused by: java.lang.LinkageError: Failed to link org/jboss/seam/persistence/HibernateSessionProxy (Module "deployment.jboss-seam-booking.ear.jboss-seam.jar:main" from Service Module Loader)
    ...
    Caused by: java.lang.NoClassDefFoundError: org/hibernate/engine/SessionImplementor
    	at java.lang.ClassLoader.defineClass1(Native Method) [rt.jar:1.7.0_45]
    ...
    Caused by: java.lang.ClassNotFoundException: org.hibernate.engine.SessionImplementor from [Module "deployment.jboss-seam-booking.ear.jboss-seam.jar:main" from Service Module Loader]
    ...
    
    它表示:

    ClassNotFoundException 表示缺失的 Hibernate 库。在这个例子里是 hibernate-core.jar

    如何解决这个问题:

    EAP5_HOME/seam/lib/ 目录复制 hibernate-core.jar JAR 到 jboss-seam-booking.ear/lib 目录。

    通过删除 standalone/deployments/jboss-seam-booking.ear.failed 文件并在相同目录里创建一个空白的 jboss-seam-booking.ear.dodeploy 文件来重新部署应用程序。
  3. 问题 - 应用程序部署和运行无误。当您访问 http://localhost:8080/seam-booking/,您可以成功登录。然而,当您试图预订酒店时,您会看到如下异常跟踪信息:
    为了进行调试,您必须首先删除 jboss-seam-booking.ear/jboss-seam-booking.war/WEB-INF/lib/jboss-seam-debug.jar,因为它标记了真正的错误。此时,您应该看到如下错误:
    java.lang.NoClassDefFoundError: org/hibernate/annotations/common/reflection/ReflectionManager
    它表示:

    ClassNotFoundException 表示有缺失的 Hibernate 库。

    如何解决这个问题:

    EAP5_HOME/seam/lib/ 目录复制 hibernate-annotations.jarhibernate-commons-annotations.jarjboss-seam-booking.ear/lib 目录。

    通过删除 standalone/deployments/jboss-seam-booking.ear.failed 文件并在相同目录里创建一个空白的 jboss-seam-booking.ear.dodeploy 文件来重新部署应用程序。
  4. 运行时和应用程序错误应该被解决
    此时,应用程序已部署且运行无误。