4

我正在尝试将 JSP / Hibernate 项目迁移到 GWT / Hibernate。简而言之,问题似乎是来自 jetty-env.xml 的 MysqlConnectionPoolDataSource 类显然没有被实例化,导致来自 web.xml 的资源引用失败。

我们的 Hibernate 设置在非 GWT 项目中运行良好。我正在使用 Eclipse Indigo、Google Suite 插件 2.5、Google GWT Designer 2.4.2。

以下是我采取的步骤以及我认为重要的文件摘录。(提前道歉 - 这有点冗长,但想确保我的问题是完整和清晰的。)

我的 war/WEB-INF/classes/hibernate.cfg.xml 包括:

<property name="hibernate.connection.datasource">
    java:comp/env/jdbc/nndb
</property>

web.xml 包括:

<resource-ref>
    <description>NN Database Connection Pooling</description>
    <res-ref-name>jdbc/nndb</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

我还按照此处所述创建了 CustomJettyLauncher并添加了 Eclipse 运行配置以使用它(运行配置参数 -server com....CustomJettyLauncher)这导致:

jetty-6.1.x [WARN] NN 数据库连接池中的配置问题 jdbc/nndbjavax.sql.DataSourceContainerShareable java.lang.IllegalStateException:没有绑定名称 javax.sql.DataSource/default

大概在这一点上,我需要在 jetty-env.xml 中定义资源的条目:

<?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
    <New id="nndb" class="org.mortbay.jetty.plus.naming.Resource">
        <Arg>jdbc/nndb</Arg>
        <Arg> 
            <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
               <Set name="Url">jdbc:mysql://dbserver/dbname</Set>
               <Set name="User">dbuser</Set>
               <Set name="Password">dbpasswd</Set>
            </New>
        </Arg>
   </New>
</Configure>

但是上面的错误(Nothing to bind for name javax.sql.DataSource/default)仍然存在。有趣的是,如果我故意在 jetty-env.xml 中篡改数据源类名(例如 NOSUCH.com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource),则没有任何问题,因此它甚至可能不会尝试实例化该类。(WebAppContext 和 Resource 的类似“跟踪器”错误确实会产生抱怨,因此只有 ConnectionPoolDataSource 没有尝试实例化。)

哇!

有谁知道出了什么问题?任何建议将不胜感激。

提前致谢!

4

3 回答 3

2

在玩过您的项目代码后,我不得不完全改变我的答案。这是一个新的:

您碰巧从早期版本的 GWT 中获取了 Jetty Launcher 代码(我相信)。一旦我用我CustomJettyLauncher拥有的版本替换了您的版本(根据相同的建议进行了修改,但在 GWT 2.4 代码库的版本之上),所有这些都结合在一起了。java:comp/env初始上下文、等的正确初始化

如果您将其添加java:comp/env到名称中,您实际上也可以使您的版本与 6.1.11 一起使用,jetty-env.xml但我认为走这条路没有意义。我无法使其与 6.1.26 一起使用,这并不重要,因为使用正确的 Jetty Launcher 代码库使其可以与任一版本一起使用

这是有效的启动器代码(包和类名就是您拥有它的方式,因此它是“插入式”替代品):https ://gist.github.com/2854726


为以后可能偶然发现这篇文章的人留下痕迹。通过启动具有日志级别的 GWT,您可以让 JettyDEBUG在 GWT 托管(开发)模式下显示其日志。SPAM

于 2012-06-01T20:54:49.437 回答
1

在我们在评论中进行对话之后,我决定继续在本地构建一个简单的“hello world”,看看我是否可以重现这个问题。我不得不经历一些箍,但不是你描述的那个。我现在想知道您的类路径中是否有任何冲突版本的码头库。例如,请看这里的这个问题。为了以防万一,我不得不处理与 GWT 托管模式、类加载和 Hibernate 相关的其他一些问题(这里更多更多)。现在一切都清楚了,我的简单示例正在运行

回到你的情况。查看修补过的 Jetty 启动器,我发现 GWT 对 Jetty 的日志记录子系统做了什么。看看JettyTreeLogger内部类。它将所有INFO及以下发送到SPAM. 除非您使用日志级别运行 GWT 应用程序,否则您SPAM不会看到诊断案例所需的“宝贵”Jetty 输出。因此,在运行配置(GWT 选项卡)中打开垃圾邮件日志级别,或者进一步修补已经修补的启动器,以免吞下 Jetty 日志消息

按照步骤设置我自己的 Jetty Launcher 并使用日志级别 SPAM 运行 GWT,我可以在控制台中看到以下内容:

...
Created java:comp/env for webapp /
Finding global env entries
...
parse: file:/.../JettyHibernateExample/war/WEB-INF/jetty-env.xml
...
loaded class com.mysql.jdbc.jdbc2.optional.MysqlDataSource from ContextLoader@null
XML new class com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource
...
XML new class org.mortbay.jetty.plus.naming.Resource
...
Looking up name="jdbc"
Looking up binding for jdbc for context=env
...
Subcontext jdbc created
Adding binding with key=nndb obj=Reference Class Name: com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource

它成功解析出配置并正确绑定创建的对象。在日志中进一步:

May 30, 2012 5:27:33 PM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: /hibernate.cfg.xml
...
DEBUG org.hibernate.cfg.Configuration -
hibernate.connection.datasource=java:comp/env/jdbc/nndb
...
DEBUG org.hibernate.internal.SessionImpl - Opened session at timestamp
DEBUG org.hibernate.internal.SessionImpl - Disconnecting session
DEBUG o.h.e.j.i.LogicalConnectionImpl - Releasing JDBC connection

ASessionFactory已成功实例化、Session打开并随后断开连接。我没有进一步测试它,假设从这里开始一切都会好起来的。

这是我的依赖项列表WEB-INF/lib

antlr-2.7.7.jar
dom4j-1.6.1.jar
gwt-servlet.jar
hibernate-commons-annotations-4.0.1.Final.jar
hibernate-core-4.1.3.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
hibernate-validator-4.1.0.Final.jar
javassist-3.15.0-GA.jar
jboss-logging-3.1.0.GA.jar
jboss-transaction-api_1.1_spec-1.0.0.Final.jar
jetty-naming-6.1.11.jar
jetty-plus-6.1.11.jar
logback-classic-1.0.1.jar
logback-core-1.0.1.jar
mysql-connector-java-5.1.20-bin.jar
report
slf4j-api-1.6.4.jar
validation-api-1.0.0.GA.jar

我希望在打开日志的情况下,您最终会看到有什么阻碍。如果您需要进一步的帮助,请随时在某个地方分享它以供我们查看。

更新现在要检查您的日志文件,我将开始提出更多建议。我注意到的第一件事是您web.xml似乎没有遵循元素的 DTD 顺序。你resource-ref应该追求servlet,servlet-mappingwelcome-file-list. 不过这似乎无关紧要。

你能告诉我你说的到底是什么意思吗

@ 不同版本:项目类路径:WEB-INF/lib 中的 6.1.26 但 6.1.11

我想确保类路径不是问题,并且我们在运行时没有多个码头 JAR 冲突。请分享您的.classpath项目文件以及WEB-INF/lib.

更新 2我发现您的日志文件中的事件顺序与我的不同。我会切入正题。

在码头 6.1.11 中:

public void configureWebApp() throws Exception
{
    //create a java:comp/env
    createEnvContext();

    //add java:comp/env entries for any globally defined EnvEntries
    bindGlobalEnvEntries();

    //set up java:comp/env as the Context in which to bind directly
    //the entries in jetty-env.xml
    NamingEntry.setScope(NamingEntry.SCOPE_LOCAL);

    //check to see if an explicit file has been set, if not,
    //look in WEB-INF/jetty-env.xml
    ....
}

在 Jetty 6.1.26 中:

public void configureWebApp() throws Exception
{
    //check to see if an explicit file has been set, if not,
    //look in WEB-INF/jetty-env.xml
    ...
}

并将创建上下文移至:

public void configureDefaults() throws Exception
{        
    //create a java:comp/env
    createEnvContext();
}

它没有设置SCOPE_LOCAL。没有SCOPE_LOCAL根上下文是不java:comp/env应该的。运行 6.1.26 (plusnaming) 我现在可以看到“有问题的”:

Looking up binding for __ for context=null

尽管如此,它仍然可以正常工作。现在,“范围”逻辑必须存在于其他地方,只要您拥有 6.1.26(并且早期版本中没有任何冲突的类),它应该可以正常工作。你在哪里:

Looking up name="__/jdbc/nndb"
Looking up binding for __ for context=null
InitialContextFactory.getInitialContext()
Created initial context delegate for local namespace:org.mortbay.naming.local.localContextRoot@237c8a9c
InitialContextFactory.getInitialContext()
Created initial context delegate for local namespace:org.mortbay.naming.local.localContextRoot@457019f7
Looking up name="Server@1c9e8392/__/javax.sql.DataSource/default"

我有:

   Looking up name="__/jdbc/nndb"
   Looking up binding for __ for context=null
   Looking up name="jdbc/nndb"
   Looking up binding for jdbc for context=__
   Looking up name="nndb"
   Looking up binding for nndb for context=jdbc
   InitialContextFactory.getInitialContext()
   Created initial context delegate for local namespace:org.mortbay.naming.local.localContextRoot@1830f66
   >>> new root context requested 
   Looking up name="comp/env"
   Looking up binding for comp for context=null
   Using classloader of current org.mortbay.jetty.handler.ContextHandler
   Looking up name="env"
   Looking up binding for env for context=comp
   Binding java:comp/env/jdbc/nndb to jdbc/nndb

也就是说,理顺您的类路径并确保您正在运行 6.1.11 或 6.1.26 而不是两者的混合。它应该这样做。还有一件事情。确保您没有将任何自定义 JNDI 东西(如对象工厂)与WEB-INF/classes.

于 2012-05-30T22:04:31.033 回答
1

我将向您展示在许多项目中适用于我们的配置。

1.) 使用 gwt-dev 依赖创建 XJettyLauncher:

package ru.minogin;

import java.io.File;

import org.mortbay.jetty.webapp.WebAppContext;

import com.google.gwt.core.ext.TreeLogger;

public class XJettyLauncher extends com.google.gwt.dev.shell.jetty.JettyLauncher {
    @SuppressWarnings("unchecked")
    @Override
    protected WebAppContext createWebAppContext(TreeLogger logger, File appRootDir) {
        WebAppContext context = new WebAppContext(appRootDir.getAbsolutePath(), "/");
        context.getInitParams().put("org.mortbay.jetty.servlet.Default.useFileMappedBuffer", "false");
        return context;
    }
}

把它包装成罐子。

2.) 创建用户库 Jetty 并在其中包含:XJettyLauncher、jetty-naming-6.1.21.jar、jetty-plus-6.1.21.jar(或您的 Jetty 版本)。将此库添加到项目中。

3.) src/main/webapp/WEB-INF/jetty-web.xml:

   <?xml version="1.0"?>
    <!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">

<Configure class="org.mortbay.jetty.webapp.WebAppContext">
    <New id="DB" class="org.mortbay.jetty.plus.naming.Resource">
        <Arg>java:comp/env/jdbc/DS</Arg>
        <Arg>
            <New class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
                <Set name="Url">jdbc:mysql://localhost:3306/database?autoReconnect=true&amp;zeroDateTimeBehavior=convertToNull&amp;characterEncoding=utf8
                </Set>
                <Set name="User">user</Set>
                <Set name="Password">passwd</Set>
            </New>
        </Arg>
    </New>
</Configure>

4.) pom.xml:

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.19</version>
  <scope>runtime</scope>
</dependency>

5.) 运行配置:

-remoteUI "${gwt_remote_ui_server_port}:${unique_id}" -logLevel INFO -port auto -war D:\var\ws\PROJECT\src\main\webapp -codeServerPort 9997 -server ru.minogin.XJettyLauncher ru.project.App

于 2012-06-01T06:59:56.977 回答