【问题标题】:Can't configure MySQL datasource in GWT + Hibernate + MySQL project无法在 GWT + Hibernate + MySQL 项目中配置 MySQL 数据源
【发布时间】:2012-05-29 13:17:49
【问题描述】:

我正在尝试将 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>

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

jetty-6.1.x [WARN] NN Database Connection Poolingjdbc/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 没有尝试实例化。)

哇!

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

提前致谢!

【问题讨论】:

  • 你在哪里尝试实例化 PoolDataSource?客户端还是服务器端?
  • 我根本不尝试在我的代码中实例化 MysqlConnectionPoolDataSource。据我了解这是如何工作的,我认为 Jetty 应该在启动服务时实例化 WebAppContext、Resource 和 MysqlConnectionPoolDataSource 本身。我认为这是在服务器端完成的。
  • 假设您完全按照启动器教程进行操作,并且您的 WEB-INF/lib 中有 jetty-namingjetty-plus 罐子,我想知道您的 jetty-env.xml 是否被“构建”了 - 你能当项目构建并准备好启动时,验证它是否被复制到您的bin 目录?
  • WEB-INF/lib 有 jetty-naming 和 jetty-plus jar,WEB-INF 有 jetty-env.xml。我知道码头正在尝试使用 jetty-env.xml,因为如果我故意弄错 WebAppContext 和 Resource 的类名,它会抱怨,但如果我为 MysqlConnectionPoolDataSource 这样做,它不会抱怨,例如NOSUCH.com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource。
  • 在这一点上我建议你走一下 Configuration#bindEntry() 的逻辑。在这里看一下:grepcode.com/file/repo1.maven.org/maven2/org.mortbay.jetty/…。它在默认为 /default 之前经过了几跳,显然失败了。你必须弄清楚为什么其他尝试绑定失败,一旦你这样做了,你可能会知道答案。

标签: hibernate gwt


【解决方案1】:

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

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

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

这里是运行的启动器代码(包和类名就是你拥有它的方式,所以它是一个“插入式”替换):https://gist.github.com/2854726


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

【讨论】:

    【解决方案2】:

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

    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。项目.App

    【讨论】:

      【解决方案3】:

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

      回到你的情况。查看修补过的 Jetty 启动器,我发现 GWT 对 Jetty 的日志记录子系统做了什么。查看JettyTreeLogger 内部类。它将所有INFO 及以下发送到SPAM。除非您使用日志级别 SPAM 运行 GWT 应用程序,否则您不会看到诊断案例所需的“宝贵”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
      

      SessionFactory 已成功实例化,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 应该在servletservlet-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,而不是两者的混合。它应该这样做。还有一件事。确保您没有使用 WEB-INF/classes 带来任何自定义 JNDI 内容(如对象工厂)。

      【讨论】:

      • 部分进展! (至少有更多信息。)日志是here。也许很重要:“为 __ 查找 context=null 的绑定”。我注意到我的码头命名和码头加罐@不同的版本:项目类路径:6.1.26 但 WEB-INF/lib 中的 6.1.11。但是,如果我使它们相同(无论哪种方式),我都会得到 java.lang.ClassCastException:org.mortbay.jetty.plus.naming.Resource 无法转换为 org.mortbay.jetty.plus.naming.NamingEntry。很奇怪……
      • 如果相关,我的 WEB-INF/lib 有: gwt-servlet.jar jetty-naming-6.1.11.jar jetty-plus-6.1.11.jar mysql-connector-java -5.1.17.jar slf4j-api-1.6.3.jar slf4j-jdk14-1.6.3.jar
      • @BillCompton,以防万一,您在 Eclipse 中设置了项目,然后使用运行配置在 Eclipse 中运行它,对吗?换句话说,没有任何 maven 可以为方程带来更多的依赖关系,而这些依赖关系仅通过查看 WEB-INF/lib 是不明显的?不会看你的日志
      • 抱歉,我的意思是我现在要看看你的日志。
      • @BillCompton,看看更新的答案。我想现在我已经用尽了所有的远程调试选项。看看我的发现是否可以帮助您理顺它。
      猜你喜欢
      • 2016-04-29
      • 1970-01-01
      • 2013-08-20
      • 2016-07-25
      • 1970-01-01
      • 2014-02-18
      • 2011-01-29
      • 2015-04-01
      • 2016-07-01
      相关资源
      最近更新 更多