无法在GWT + Hibernate + MySQL项目中配置MySQL数据源

时间:2012-05-23 01:32:46

标签: hibernate gwt

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

我们的Hibernate设置在非GWT项目中运行良好。我正在使用Eclipse Indigo,Google Suite Plugin 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,如here所述,并添加了Eclipse run config以使用它(Run Config Arguments -server com .... CustomJettyLauncher)这导致:

码头-6.1.x [WARN] NN数据库连接池配置问题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>

但是上面的错误(名称为javax.sql.DataSource / default的Nothing)仍然存在。有趣的是,如果我故意在jetty-env.xml中添加数据源类名(例如NOSUCH.com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource),那就没有抱怨了,所以它甚至可能都没有尝试实例化该类。 (WebAppContext和Resource DO的类似“tracer”错误会产生抱怨,因此它只是ConnectionPoolDataSource,它不会尝试实例化。)

呼!

有谁看到了什么问题?任何建议都将不胜感激。

提前致谢!

3 个答案:

答案 0 :(得分:2)

玩完项目代码后,我必须彻底改变我的回答。这是一个新的:

  

你碰巧从GWT的早期版本中获取Jetty Launcher代码(我相信)。一旦我将CustomJettyLauncher替换为我所拥有的版本(根据相同的建议进行修改,但在GWT 2.4代码库的版本之上),它们全部汇集在一起​​。正确初始化上下文,java:comp/env

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

这里有可用的启动器代码(包名和类名就是你如何拥有它所以&#39; sa&#34; drop-in&#34; replacement):https://gist.github.com/2854726


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

答案 1 :(得分:1)

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

回到你的案子。通过修补的Jetty发射器,我想到了GWT正在对Jetty的记录子系统做什么。看看JettyTreeLogger内部课程。它会将所有INFO及以下内容发送至SPAM。除非您使用日志级别SPAM运行GWT应用程序,否则您将无法看到诊断案例所需的“宝贵”Jetty输出。因此在运行配置(GWT选项卡)中打开SPAM日志级别,或者修补已修补的启动程序,以免吞下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。这似乎并不重要。

当你说

时,能告诉我你的意思吗?
  

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

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

更新2 我认为日志文件和我的事件序列之间存在差异。我会切入追逐。

在Jetty 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内容(如对象工厂)。

答案 2 :(得分: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;
    }
}

将其装为jar。

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