4

I'm attempting to migrate a JSP / Hibernate project to GWT / Hibernate. Briefly, the issue appears to be that the MysqlConnectionPoolDataSource class from jetty-env.xml is evidently not getting instantiated, causing the resource reference from web.xml to fail.

Our Hibernate setup works fine in non-GWT projects. I'm using Eclipse Indigo, Google Suite Plugin 2.5, Google GWT Designer 2.4.2.

Here are the steps I took and excerpts of files that I think matter. (Apologies in advance - this is a little bit verbose but wanted to be sure my question is complete and clear.)

My war/WEB-INF/classes/hibernate.cfg.xml includes:

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

The web.xml includes:

<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>

I also created CustomJettyLauncher as described here and added Eclipse run config to use it (Run Config Arguments -server com....CustomJettyLauncher) This results in:

jetty-6.1.x [WARN] Configuration problem at NN Database Connection Poolingjdbc/nndbjavax.sql.DataSourceContainerShareable java.lang.IllegalStateException: Nothing to bind for name javax.sql.DataSource/default

Presumably at this point I need an entry in the jetty-env.xml defining the resource:

<?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>

But the above error (Nothing to bind for name javax.sql.DataSource/default) remains. Interestingly, if I intentionally bugger up the datasource classname in jetty-env.xml (e.g. NOSUCH.com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource) there's no gripe, so it may not even be trying to instantiate that class. (Similar "tracer" errors for WebAppContext and Resource DO produce gripes, so it's only ConnectionPoolDataSource that it's not trying to instantiate.)

Whew!

Does anyone see what's wrong? Any recommendations would be greatly appreciated.

Thanks in advance!

Bill Compton
  • 61
  • 1
  • 7
  • Where do you try to instantiate the PoolDataSource? Client side or server side? – Johanna May 23 '12 at 07:26
  • I don't try to instantiate the MysqlConnectionPoolDataSource in my code at all. As I understand how this works, I *think* Jetty is supposed to instantiate the WebAppContext, Resource, and MysqlConnectionPoolDataSource itself when starting up the service. I think this is done on the server side. – Bill Compton May 27 '12 at 16:01
  • assuming that you followed the launcher tutorial to the letter and you have the `jetty-naming` and the `jetty-plus` jars in your `WEB-INF/lib` I wonder if your `jetty-env.xml` gets "built" - can you verify it gets copied over to your `bin` directory when the project is built and is ready to launch? – Pavel Veller May 28 '12 at 13:32
  • WEB-INF/lib has jetty-naming and jetty-plus jars, and WEB-INF has jetty-env.xml. I know jetty is trying to use the jetty-env.xml because it gripes if I intentionally bugger up the class names for WebAppContext and Resource, but it does NOT gripe if I do that for MysqlConnectionPoolDataSource, e.g. NOSUCH.com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource. – Bill Compton May 28 '12 at 13:43
  • At this point I would recommend you walk the logic of Configuration#bindEntry(). Take a look at it here: http://grepcode.com/file/repo1.maven.org/maven2/org.mortbay.jetty/jetty-plus/7.0.0.pre5/org/mortbay/jetty/plus/webapp/Configuration.java#Configuration.bindEntry%28java.lang.String%2Cjava.lang.Class%29. It gets through a few hops before it defaults to `/default` that evidently fails. You will have to figure out why other attempts to bind failed and once you do you will likely know the answer. – Pavel Veller May 29 '12 at 01:17
  • Thanks, Pavel. I think you're right that this is where the exception is being thrown. Unfortunately I've looked carefully at this code before and concluded that it's failing because the context (WebAppContext) simply doesn't contain a binding with the name jdbc/nndb. I believe that this is because Jetty is never attempting to instantiate a MysqlConnectionPoolDataSource (otherwise, it would gripe when I intentionally bugger up that class name with NOSUCH.com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource). – Bill Compton May 29 '12 at 13:16
  • @BillCompton, when you put log level to `DEBUG`, do you see `Created java:comp/env for webapp`? do you then see `Binding env entries from the context scope`? this would be coming from `org.mortbay.jetty.plus.webapp.EnvConfiguration` that is responsible for the `jetty-env.xml`. I wish I had your project code to play with. maybe you can upload a stripped down version somewhere to Dropbox? – Pavel Veller May 29 '12 at 18:32
  • @BillCompton maybe at least post the log with the `DEBUG` output? for those `New` tags in the `jetty-env.xml` you would, for example, see `XML new `. Ideally you would run it in the IGNORED mode (http://docs.codehaus.org/display/JETTY/Debugging). – Pavel Veller May 29 '12 at 19:18
  • For my last comment I meant `VERBOSE` of course – Pavel Veller May 29 '12 at 19:34
  • @PavelVeller, two updates: 1) In the process of working on an extracted project, I noticed I had Jetty 6.1.26 but GWT 2.4.0 appears to be built with Jetty 6.1.11. After switching the jars in WEB-INF/lib to Jetty 6.1.11, Jetty now gripes with a bad path to NOSUCH.com...MysqlConnectionPoolDataSource, so it's now at least trying to instantiate that class. However with the right path, it still fails with Nothing to bind for name javax.sql.DataSource/default. 2) I tried following the JETTY/Debugging instructions (slf4j in WEB-INF/lib & path), added -DDEBUG vm arg, but no logging. Help? – Bill Compton May 30 '12 at 03:55

3 Answers3

2

I had to completely change my answer after having played with your project code. Here's a new one:

You happened to take a Jetty Launcher code from earlier versions of GWT (I believe). Once I replaced your CustomJettyLauncher with the the version that I had (modified as per the same recommendations but on top of a version from the GWT 2.4 codebase) it all came together. Proper initialization of initial context, the java:comp/env, etc.

You can actually make your version work with the 6.1.11 too if you add the java:comp/env into the name in jetty-env.xml but I don't think going that route makes sense. I couldn't make it work with 6.1.26 and it doesn't really matter since using proper Jetty Launcher codebase makes it work with either version.

Here's the launcher code that works (package and class name is just how you had it so it's a "drop-in" replacement): https://gist.github.com/2854726


Leaving a trail for someone who might stumble upon this post later. You get Jetty to show its DEBUG logs in GWT hosted (dev) mode by launching GWT with SPAM log level.

Pavel Veller
  • 6,085
  • 1
  • 26
  • 24
1

After the conversation we had in the comments I decided to go ahead and build a simple "hello world" locally to see if I can reproduce the issue. I had to go through some hoops but not the one you described. I now wonder if you have any conflicting version of jetty libraries on your classpath. Look at this question here, for example. And just in case, I had to deal with some other issues related to GWT hosted mode, class loading, and Hibernate (here, more, some more). It's all clear now and my simple example is working.

Back to your case. Looking through the patched Jetty launcher I figured what GWT was doing to Jetty's logging subsystem. Look at the JettyTreeLogger inner class. It sends all INFO and below to SPAM. Unless you run the GWT app with the log level SPAM you won't see the "precious" Jetty output you need to diagnose your case. So turn on SPAM log level in the run configuration (GWT tab) or alternatively patch the already patched launcher further not to swallow Jetty log messages.

Having followed the steps to set up my own Jetty Launcher and running GWT with log level SPAM I am able to see the following in the console:

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

It successfully parses out the configuration and properly binds created objects. Further in the log:

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

A SessionFactory was successfully instantiated, Session opened and subsequently disconnected. I didn't test it further assuming it would be all good from here.

Here's the list of dependencies I have in my 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

I hope with logs turned on you will finally see what gets in the way. Feel free to share it somewhere for us to look at it if you need further assistance.

UPDATE Now having your log file to inspect I will start making more recommendations. First thing I noticed is that your web.xml doesn't seem to be following the DTD order of elements. Your resource-ref should go after servlet, servlet-mapping, and welcome-file-list. This doesn't seem to matter though.

Can you please tell me what exactly you mean when you say

@ different versions: project classpath: 6.1.26 but 6.1.11 in WEB-INF/lib

I want to make sure the classpath is not an issue and we don't have multiple jetty JARs conflicting in runtime. Please share your .classpath project file along with the full listing of things in WEB-INF/lib.

UPDATE 2 I figured a difference between the sequence of events in your log file and mine. I will cut to the chase.

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

while in 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
    ...
}

and creating context is moved to:

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

and it doesn't set SCOPE_LOCAL. Without SCOPE_LOCAL the root context is not java:comp/env like it should be. Running with 6.1.26 (plus and naming) I can now see the "problematic":

Looking up binding for __ for context=null

That said, however, it works fine anyway. That "scope" logic has got to live in some other place now and as long as you have 6.1.26 (and no conflicting classes anywhere from earlier versions) it should work just fine. Where you have:

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"

I have:

   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

That said, straighten up your classpath and ensure you are running the 6.1.11 or 6.1.26 and not a mixture of the two. It should do it. And one more thing. Make sure you don't bring any custom JNDI stuff (like object factories) with the WEB-INF/classes.

Community
  • 1
  • 1
Pavel Veller
  • 6,085
  • 1
  • 26
  • 24
  • Partial progress! (At least more info.) The log is [here](https://www.dropbox.com/s/gfxr8e55ujqszbm/GwtLog.txt). Maybe important: "Looking up binding for __ for context=null". I noticed my jetty-naming & jetty-plus jars @ different versions: project classpath: 6.1.26 but 6.1.11 in WEB-INF/lib. However, if I make them the same (either way) I get java.lang.ClassCastException: org.mortbay.jetty.plus.naming.Resource cannot be cast to org.mortbay.jetty.plus.naming.NamingEntry. Very odd... – Bill Compton May 31 '12 at 02:58
  • And in case it's relevant, my WEB-INF/lib has: 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 – Bill Compton May 31 '12 at 03:02
  • @BillCompton, just in case, you have the project set up in Eclipse and you just run it within Eclipse using Run configuration, correct? In other words there's no maven that can bring in more dependencies to the equation that are not apparent by just looking at `WEB-INF/lib`? will not take a look at your log – Pavel Veller May 31 '12 at 03:07
  • sorry, I meant I will NOW take a look at your log. – Pavel Veller May 31 '12 at 03:17
  • @BillCompton, take a look at the updated answer. I guess by now I have exhausted all remote debugging options I had. See if my findings can help you straighten it up. – Pavel Veller May 31 '12 at 15:52
  • I moved the resource-ref web.xml entries after servlet etc; as you expected, this didn't matter. I'm only using eclipse at this point. No maven yet. Re Jetty versions, if BOTH WEB-INF/lib and Eclipse BuildPath use 6.1.26 OR both use 6.1.11: ClassCastException: o.m.j.p.n.R cannot be cast to o.m.j.p.n.NamingEntry If WEB-INF @ 6.1.26 & BuildPath 6.1.11: No resource to bind matching name=jdbc/nndb If WEB-INF @ 6.1.11 & BuildPath 6.1.26: Nothing to bind for name javax.sql.DataSource/default Key project files [here](https://www.dropbox.com/s/qn6favkbjtcxoo4/NovoNoteGwt.zip). Thanks so much, Pavel!! – Bill Compton Jun 01 '12 at 02:31
  • @BillCompton, I believe I figured it out, finally. please read my updated answer – Pavel Veller Jun 01 '12 at 19:52
  • Pavel!! I think you did it!! I need to do some more testing for sure, and need to look carefully at the differences between the older version of the Launcher and your new one, but at first glance, IT WORKS! Again, can't say "thank you" enough! – Bill Compton Jun 01 '12 at 22:46
  • @MrLister I'm not very experienced with how the StackOverflow process works, but I owe some gratitude to you, as well, for putting up the bounty to help draw attention to my question. Thanks!! – Bill Compton Jun 01 '12 at 22:48
1

I would show you the configuration that works for us in many projects.

1.) Create XJettyLauncher using gwt-dev dependency:

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;
    }
}

Pack it as jar.

2.) Create user library Jetty and include in it: XJettyLauncher, jetty-naming-6.1.21.jar, jetty-plus-6.1.21.jar (or your Jetty version). Add this library to the project.

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.) Run configuration:

-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

Andrey Minogin
  • 4,521
  • 6
  • 38
  • 60