Bonjour,

Je suis en train d'intégrer JPA (utilisation d'eclipselink comme provider) à mon application web. Mon application s'appuie sur la solution GWT + GIN + GUICE. Et j'essaie donc d'intégrer JPA par le biais de Guice-Persist. Pour faire cela, je me suis appuyé sur la doc de Guice (http://code.google.com/p/google-guice/wiki/JPA).
Lors du lancement de l'application, j'obtiens l'exception suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
sept. 19, 2012 5:30:09 PM com.google.apphosting.utils.jetty.JettyLogger info
Infos: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
sept. 19, 2012 5:30:09 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
Infos: Successfully processed /home/nicolas/workspace/java/Aquamoni/war/WEB-INF/appengine-web.xml
sept. 19, 2012 5:30:09 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
Infos: Successfully processed /home/nicolas/workspace/java/Aquamoni/war/WEB-INF/web.xml
sept. 19, 2012 5:30:13 PM com.google.apphosting.utils.jetty.JettyLogger warn
Avertissement: Failed startup of context com.google.appengine.tools.development.DevAppEngineWebAppContext@5abc5c2c{/,/home/nicolas/workspace/java/Aquamoni/war}
com.google.inject.ProvisionException: Guice provision errors:
 
1) Error injecting constructor, java.lang.NullPointerException
  at com.aquamoni.webmonitor.server.injection.PersistenceInitializer.<init>(PersistenceInitializer.java:9)
  at com.aquamoni.webmonitor.server.injection.PersistenceInitializer.class(PersistenceInitializer.java:9)
  while locating com.aquamoni.webmonitor.server.injection.PersistenceInitializer
 
1 error
	at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:987)
	at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1013)
	at com.aquamoni.webmonitor.server.injection.GuiceServletConfig.getInjector(GuiceServletConfig.java:25)
	at com.google.inject.servlet.GuiceServletContextListener.contextInitialized(GuiceServletContextListener.java:45)
	at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
	at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
	at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
	at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
	at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
	at org.mortbay.jetty.Server.doStart(Server.java:224)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:197)
	at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:241)
	at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:148)
	at com.google.appengine.tools.development.gwt.AppEngineLauncher.start(AppEngineLauncher.java:97)
	at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:509)
	at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:1068)
	at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:811)
	at com.google.gwt.dev.DevMode.main(DevMode.java:311)
Caused by: java.lang.NullPointerException
	at org.datanucleus.api.jpa.JPAEntityManagerFactory.<init>(JPAEntityManagerFactory.java:330)
	at org.datanucleus.api.jpa.PersistenceProviderImpl.createEntityManagerFactory(PersistenceProviderImpl.java:91)
	at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source)
	at javax.persistence.Persistence.createEntityManagerFactory(Unknown Source)
	at com.google.inject.persist.jpa.JpaPersistService.start(JpaPersistService.java:94)
	at com.aquamoni.webmonitor.server.injection.PersistenceInitializer.<init>(PersistenceInitializer.java:10)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
	at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance_(Runtime.java:127)
	at com.google.appengine.tools.development.agent.runtime.Runtime.newInstance(Runtime.java:135)
	at com.google.inject.internal.DefaultConstructionProxyFactory$2.newInstance(DefaultConstructionProxyFactory.java:85)
	at com.google.inject.internal.ConstructorInjector.construct(ConstructorInjector.java:85)
	at com.google.inject.internal.ConstructorBindingImpl$Factory.get(ConstructorBindingImpl.java:254)
	at com.google.inject.internal.ProviderToInternalFactoryAdapter$1.call(ProviderToInternalFactoryAdapter.java:46)
	at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1031)
	at com.google.inject.internal.ProviderToInternalFactoryAdapter.get(ProviderToInternalFactoryAdapter.java:40)
	at com.google.inject.Scopes$1$1.get(Scopes.java:65)
	at com.google.inject.internal.InternalFactoryToProviderAdapter.get(InternalFactoryToProviderAdapter.java:40)
	at com.google.inject.internal.InjectorImpl$4$1.call(InjectorImpl.java:978)
	at com.google.inject.internal.InjectorImpl.callInContext(InjectorImpl.java:1024)
	at com.google.inject.internal.InjectorImpl$4.get(InjectorImpl.java:974)
	... 22 more
Voici la vue Explorer d'Eclipse qui permettra de voir comment mon projet est structuré :


J'ai donc ma classe GuiceServletConfig avec une classe Binder et une classe Mapping :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class GuiceServletConfig extends GuiceServletContextListener {
 
	@Override
	protected Injector getInjector() {	
		Injector injector = Guice.createInjector(new AbstractModule[]{
				// register the service binder
				new ServicesBinder(),
 
				// register db persistence
				new JpaPersistModule("aquamoni"),
 
				// register the url mapping
				new ServletMapping()
		});
 
		injector.getInstance(PersistenceInitializer.class);
 
		return injector;
	}
}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
public class ServicesBinder extends AbstractModule {
 
 
	  protected void configure() {
		  bind(TemperaturesService.Iface.class).to(TemperaturesServiceImpl.class).in(Scopes.SINGLETON);
 
		  bind(AquariumDAO.class);
	  }
 
}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
public class ServletMapping extends ServletModule {
 
 
	  @Override
	  protected void configureServlets() {
		  serve("/aquamoni/Temperatures").with(TemperaturesServiceImpl.class);
	  }
 
}
PersistenceInitializer, une classe permettant de démarrer service de persistence :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
@Singleton
public class PersistenceInitializer { 
    @Inject PersistenceInitializer(PersistService service) {
            service.start(); 
 
            // At this point JPA is started and ready.
    } 
}
Mon fichier persistence.xml situé dans src/META-INF/
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
	version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
	<persistence-unit name="aquamoni" transaction-type="RESOURCE_LOCAL">
 				<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
 
                <!-- JPA entities must be registered here -->
                <class>com.aquamoni.webmonitor.server.dao.entities.Aquarium</class>
 
                <properties>
		            <property name="javax.persistence.jdbc.password" value="" />
		            <property name="javax.persistence.jdbc.user" value="root" />
		            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
		            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/aquamoni" />
                </properties>
        </persistence-unit>
 
</persistence>
Voici la liste des JARs dans WEB-INF/lib


En mode Debug, je me suis rendu compte que l'exception était catché dans la classe PersistenceInitializer au moment service.start().
En effet, les propriétés de service sont null et l'objet service n'a pas les paramètres de connexion à la base de données. J'ai donc pensé au fichier persistence.xml qui n'est pas chargé. Mais, je me suis rendu compte que quand le fichier persistence n'est pas présent, un warning apparait des les logs d'erreurs.

J'ai aussi testé la solution GUICE + JPA dans une application J2SE et ça fonctionne correctement. Il semblerait qu'il y ait une configuration particulière à faire pour les applications J2EE.

Si quelqu'un a une idée d'où vient mon problème, n'hésitez pas à m'en faire part.