2012-05-23 21 views
4

我试图将一个JSP/Hibernate项目迁移到GWT/Hibernate。简而言之,问题似乎是来自jetty-env.xml的MysqlConnectionPoolDataSource类明显未获得实例化,导致web.xml中的资源引用失败。无法在GWT + Hibernate + MySQL项目中配置MySQL数据源

我们的Hibernate安装在非GWT项目中工作正常。我正在使用Eclipse Indigo,Google Suite Plugin 2.5,Google GWT Designer 2.4.2。

下面是我采取的步骤和我认为重要的文件摘录。 (道歉提前 - 这是一个有点冗长,但希望确保我的问题是完整的,明确的。)

我的战争/ WEB-INF /班/ 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运行配置使用它(运行配置参数-server COM .... CustomJettyLauncher)这导致:

码头-6.1.x [WARN]在NN数据库连接Poolingjdbc/nndbjavax.sql.DataSourceContainerShareable java.lang.IllegalStateException配置问题:在这个没有绑定的名称为javax.sql.DataSource /默认

想必点我需要在码头-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 /默认)保持。有趣的是,如果我故意在jetty-env.xml中(例如NOSUCH.com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource)查找数据源类名,就没有抱怨了,所以它甚至可能不会尝试实例化该类。 (对于WebAppContext和Resource DO类似的“tracer”错误会产生抱怨,因此它只是ConnectionPoolDataSource,它并不试图实例化。)

呜!

有人看到有什么问题吗?任何建议将不胜感激。

在此先感谢!

+0

你在哪里尝试实例化PoolDataSource?客户端或服务器端? – Johanna

+0

我不会尝试在我的代码中实例化MysqlConnectionPoolDataSource。据我了解这是如何工作的,我认为* Jetty应该在启动服务时实例化WebAppContext,Resource和MysqlConnectionPoolDataSource本身。我认为这是在服务器端完成的。 –

+0

假设你遵循了启动教程的信件,并且在你的'WEB-INF/lib'中有'jetty-naming'和'jetty-plus' jar我想知道你的'jetty-env.xml'是否得到了“内置“ - 你可以验证它被复制到你的'bin'目录当项目建成并准备启动? –

回答

2

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

你碰巧从早期版本的GWT(我相信)采取码头启动代码。一旦我用我的版本替换你的CustomJettyLauncher(根据相同的建议进行修改,但是在GWT 2.4代码库的版本之上修改),它们全部结合在一起。正确的初始化初始上下文中,java:comp/env

你实际上可以使与6.1.11过你的版本工作,如果你添加java:comp/env到名jetty-env.xml,但我不认为走这样一条路品牌感。我无法使它与6.1.26一起工作,因为使用正确的Jetty启动程序代码库使它可以与版本一起使用,所以它并不重要。

这里的启动代码,工程(包和类名是刚刚你怎么过它,因此它是一个“降”替代):https://gist.github.com/2854726


留下痕迹的人在这个谁可能绊倒稍后发布。通过以SPAM日志级别启动GWT,您可以让Jetty通过GWT托管(dev)模式显示其DEBUG日志。

1

在我们谈话后,我决定继续在本地建立一个简单的“你好世界”,看看我能否重现这个问题。我不得不经过一些环节,但不是你所描述的。 我现在想知道在你的类路径上是否有任何冲突版本的码头库。例如,看this question here。以防万一,我不得不处理与GWT托管模式,类加载和休眠相关的其他问题(here,more,some more)。 现在很清楚,我的简单例子是

回到你的情况。通过修补的Jetty发射器,我想到了GWT为Jetty的日志子系统做了什么。看看JettyTreeLogger内部类。它发送所有INFO及以下至SPAM。除非你运行的日志级别为SPAM的GWT应用程序,否则您将看不到需要诊断您的案例的“宝贵”Jetty输出。因此,在运行配置(GWT选项卡)中打开SPAM日志级别,或者替换已修补的启动程序以进一步不吞入Jetty日志消息

已经按照步骤来建立我自己的码头启动,并与日志级别的垃圾邮件,我能够在控制台看到以下运行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 [email protected] 
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 

希望与日志功能后,您会看到最终的方式是什么鬼。如果您需要进一步的帮助,请随时分享给我们。

UPDATE现在有您的日志文件来检查我会开始提出更多的建议。我注意到的第一件事是你的web.xml似乎没有遵循元素的DTD顺序。您的resource-ref应该跟在servlet,servlet-mappingwelcome-file-list之后。这似乎并不重要。

能否请你告诉我,究竟你的意思是,当你说

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

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

UPDATE 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 
    .... 
} 

而在码头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:[email protected] 
InitialContextFactory.getInitialContext() 
Created initial context delegate for local namespace:[email protected] 
Looking up name="[email protected]/__/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:[email protected] 
    >>> 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 

这就是说,挺直你的classpath并确保您运行的6.1.11的或6.1.26,而不是混合两个。它应该这样做。还有一件事。确保你不带WEB-INF/classes任何自定义的JNDI东西(如对象工厂)。

+0

部分进展! (至少有更多的信息)日志是[这里](https://www.dropbox.com/s/gfxr8e55ujqszbm/GwtLog.txt)。也许很重要:“查找__ for context = null的绑定”。我注意到我的jetty命名和码头加JAR @不同的版本:项目类路径:6.1.26但6.1.11在WEB-INF/lib中。但是,如果我使它们相同(无论哪种方式),我都会得到java.lang.ClassCastException:org.mortbay.jetty.plus.naming.Resource不能转换为org.mortbay.jetty.plus.naming.NamingEntry。非常奇怪...... –

+0

如果相关,我的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 –

+0

@BillCompton,以防万一,你有在Eclipse中设置的项目,你只需在Eclipse中运行它使用运行配置,正确?换句话说,没有任何maven可以通过查看'WEB-INF/lib'来获得更多的依赖关系,这并不是显而易见的。不会看看你的日志 –

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 /主/ web应用/ WEB-INF /码头-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