You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@roller.apache.org by Denis Balazuc <de...@balazuc.net> on 2007/06/17 16:24:38 UTC

Troubles with JPA

Hi all

I'm having troubles running the current 4.0 trunk with JPA. I have a 
NullPointerException that happens during  JPAPersistenceStrategy 
initialisation. Although I see where that comes from, I do not know how 
to fix it. It's probably some configuration that I'm missing and you've 
probably already seen this.

Here's the details (that's for Roller - I'm not trying to run Planet yet)

-- Opening the homepage on Roller, or any task trying to instantiate 
Roller through the RollerFactory using JPA as the persistence layer, 
produces this ->

java.lang.NullPointerException
	at 
org.apache.roller.weblogger.business.jpa.JPAPersistenceStrategy.getThreadLocalEntityManager(JPAPersistenceStrategy.java:273)
	at 
org.apache.roller.weblogger.business.jpa.JPAPersistenceStrategy.getEntityManager(JPAPersistenceStrategy.java:260)
	at 
org.apache.roller.weblogger.business.jpa.JPAPersistenceStrategy.getNamedQuery(JPAPersistenceStrategy.java:294)
	at 
org.apache.roller.weblogger.business.jpa.JPAPropertiesManagerImpl.getProperties(JPAPropertiesManagerImpl.java:87)
	at 
org.apache.roller.weblogger.business.jpa.JPAPropertiesManagerImpl.init(JPAPropertiesManagerImpl.java:130)
	at 
org.apache.roller.weblogger.business.jpa.JPAPropertiesManagerImpl.<init>(JPAPropertiesManagerImpl.java:65)


-- The real reason why the NPE happens is because in the constructors of 
JPAPersistenceStrategy, the call

  this.emf = Persistence.createEntityManagerFactory(puName, emfProperties);

returns an expected NULL value, which produces the NPE later when the 
member variable "emf" is accessed.

Since the hibernate persistence layer works just fine, I am guessing 
that I am missing some JPA configuration but can't really find what (I 
know close to nothing about JPA) and there's nothing in the logs that 
looks mighty wrong. I reckon I've digged deeper in the code than in the 
documentation, but any further pointer (not null!) would help.


Thanks a lot
Denis Balazuc


PS

The following JPAPersistenceStrategy.java patch does NOT fix the issue 
but avoids the NPE by providing a clearer error message in the Roller 
log file when NULL is returned by 
Persistence.createEntityManagerFactory(puName, emfProperties), then 
throws an expected WebloggerException indicating the issue and 
preventing further initialisation (rather than Roller bombing out later 
with a NPE).


------------------------ PATCH -------------------------------------


Index:
apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPAPersistenceStrategy.java
===================================================================
---
apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPAPersistenceStrategy.java 
(revision 547933)
+++
apps/weblogger/src/java/org/apache/roller/weblogger/business/jpa/JPAPersistenceStrategy.java 
(working copy)
@@ -19,26 +19,29 @@

  package org.apache.roller.weblogger.business.jpa;

+import java.io.IOException;
+import java.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
  import java.util.Collection;
-import java.util.Properties;
+import java.util.Enumeration;
  import java.util.Iterator;
-import java.util.Enumeration;
  import java.util.Properties;
-import java.io.InputStream;
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.roller.weblogger.WebloggerException;
+
+import javax.persistence.EntityManager;
  import javax.persistence.EntityManagerFactory;
-import javax.persistence.EntityManager;
  import javax.persistence.FlushModeType;
  import javax.persistence.Persistence;
  import javax.persistence.PersistenceException;
  import javax.persistence.Query;

+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.Validate;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.WebloggerException;

+
  /**
   * JPAPersistenceStrategy is responsible for the lowest-level 
interaction with
   * the JPA API.
@@ -70,29 +73,8 @@
              String puName,
              String jndiName,
              Properties properties) throws WebloggerException {
-
-        // set strategy used by Datamapper
-        // You can configure JPA completely via the JPAEMF.properties file
-        Properties emfProps = loadPropertiesFromResourceName(
-           "JPAEMF.properties", getContextClassLoader());
-
-        // Add additional properties passed in
-        Enumeration keys = properties.keys();
-        while (keys.hasMoreElements()) {
-            String key = (String)keys.nextElement();
-            String value = properties.getProperty(key);
-            logger.info(key + ": " + value);
-            emfProps.setProperty(key, value);
-        }
-
-        emfProps.setProperty("openjpa.ConnectionFactoryName", jndiName);
-
-        try {
-            this.emf = Persistence.createEntityManagerFactory(puName, 
emfProps);
-        } catch (PersistenceException pe) {
-            logger.error("ERROR: creating entity manager", pe);
-            throw new WebloggerException(pe);
-        }
+    	this(puName,
+    			createJPAPersistenceStrategyProperties(jndiName, properties)); 

      }

      /**
@@ -106,49 +88,45 @@
              String username,
              String password,
              Properties properties) throws WebloggerException {
-
-        logger.info("driverClass:    " + driverClass);
-        logger.info("connectionURL:  " + connectonUrl);
-        logger.info("username:       " + username);
-
-        // set strategy used by Datamapper
-        // You can configure JPA completely via the JPAEMF.properties file
-        Properties emfProps = loadPropertiesFromResourceName(
-           "JPAEMF.properties", getContextClassLoader());
-
-        // Add additional properties passed in
-        Enumeration keys = properties.keys();
-        while (keys.hasMoreElements()) {
-            String key = (String)keys.nextElement();
-            String value = properties.getProperty(key);
-            logger.info(key + ": " + value);
-            emfProps.setProperty(key, value);
-        }
-
-        // Try to please all the players
-        emfProps.setProperty("openjpa.ConnectionDriverName", 
driverClass);
-        emfProps.setProperty("openjpa.ConnectionURL", 
connectonUrl);
-        emfProps.setProperty("openjpa.ConnectionUserName",       username);
-        emfProps.setProperty("openjpa.ConnectionPassword", 
password);
-
-        emfProps.setProperty("toplink.jdbc.driver", 
driverClass);
-        emfProps.setProperty("toplink.jdbc.url", 
connectonUrl);
-        emfProps.setProperty("toplink.jdbc.user",                username);
-        emfProps.setProperty("toplink.jdbc.password",            password);
-
- 
emfProps.setProperty("hibernate.connection.driver_class",driverClass);
-        emfProps.setProperty("hibernate.connection.url", 
connectonUrl);
-        emfProps.setProperty("hibernate.connection.username",    username);
-        emfProps.setProperty("hibernate.connection.password", 
password);
-
-        try {
-            this.emf = Persistence.createEntityManagerFactory(puName, 
emfProps);
-        } catch (PersistenceException pe) {
-            logger.error("ERROR: creating entity manager", pe);
-            throw new WebloggerException(pe);
-        }
+    	this(puName, createJPAPersistenceStrategyProperties(
+    				driverClass,
+    				connectonUrl,
+    				username,
+    				password,
+    				properties));
      }
-
+
+    protected JPAPersistenceStrategy(String puName, Properties 
emfProperties) throws WebloggerException {
+    	super();
+    	Validate.isTrue(
+    			StringUtils.isNotBlank(puName),
+    			"Null or blank puName parameter.");
+    	Validate.notNull(
+    			emfProperties,
+    			"Null or blank EMF properties parameter.");
+    	
+    	 try {
+             this.emf = Persistence.createEntityManagerFactory(puName, 
emfProperties);
+             if (null == emf) {
+             	logger.error(
+             			"ERROR: unable to create an EntityManagerFactory. " +
+             			"Persistence.createEntityManagerFactory returned a NULL 
value. " +
+             			"The current property set is probably incorrect for the 
persistence unit '" + puName + "'.");
+             	if (logger.isDebugEnabled()) {
+             		logger.debug(                			
+                 			"Persistence.createEntityManagerFactory properties 
for puName '" +
+                 			puName + "' (JPAEMF.properties):\n" +
+                 			emfProperties.toString());
+             	}
+             	throw new WebloggerException("ERROR: unable to create an 
EntityManagerFactory.");
+             }
+         } catch (PersistenceException pe) {
+             logger.error("ERROR: creating entity manager", pe);
+             throw new WebloggerException(pe);
+         }
+    }
+
+
      /**
       * Flush changes to the datastore, commit transaction, release em.
       * @throws org.apache.roller.WebloggerException on any error
@@ -325,6 +303,73 @@
          return q;
      }

+    private static Properties createJPAPersistenceStrategyProperties(
+            String jndiName,
+            Properties properties) throws WebloggerException {
+
+        // set strategy used by Datamapper
+        // You can configure JPA completely via the JPAEMF.properties file
+        Properties emfProps = loadPropertiesFromResourceName(
+           "JPAEMF.properties", getContextClassLoader());
+
+        // Add additional properties passed in
+        Enumeration keys = properties.keys();
+        while (keys.hasMoreElements()) {
+            String key = (String)keys.nextElement();
+            String value = properties.getProperty(key);
+            logger.info(key + ": " + value);
+            emfProps.setProperty(key, value);
+        }
+
+        emfProps.setProperty("openjpa.ConnectionFactoryName", jndiName);
+        return emfProps;
+    }
+
+    public static Properties createJPAPersistenceStrategyProperties(
+            String driverClass,
+            String connectonUrl,
+            String username,
+            String password,
+            Properties properties) throws WebloggerException {
+
+        logger.info("driverClass:    " + driverClass);
+        logger.info("connectionURL:  " + connectonUrl);
+        logger.info("username:       " + username);
+
+        // set strategy used by Datamapper
+        // You can configure JPA completely via the JPAEMF.properties file
+        Properties emfProps = loadPropertiesFromResourceName(
+           "JPAEMF.properties", getContextClassLoader());
+
+        // Add additional properties passed in
+        Enumeration keys = properties.keys();
+        while (keys.hasMoreElements()) {
+            String key = (String)keys.nextElement();
+            String value = properties.getProperty(key);
+            logger.info(key + ": " + value);
+            emfProps.setProperty(key, value);
+        }
+
+        // Try to please all the players
+        emfProps.setProperty("openjpa.ConnectionDriverName", 
driverClass);
+        emfProps.setProperty("openjpa.ConnectionURL", 
connectonUrl);
+        emfProps.setProperty("openjpa.ConnectionUserName",       username);
+        emfProps.setProperty("openjpa.ConnectionPassword", 
password);
+
+        emfProps.setProperty("toplink.jdbc.driver", 
driverClass);
+        emfProps.setProperty("toplink.jdbc.url", 
connectonUrl);
+        emfProps.setProperty("toplink.jdbc.user",                username);
+        emfProps.setProperty("toplink.jdbc.password",            password);
+
+ 
emfProps.setProperty("hibernate.connection.driver_class",driverClass);
+        emfProps.setProperty("hibernate.connection.url", 
connectonUrl);
+        emfProps.setProperty("hibernate.connection.username",    username);
+        emfProps.setProperty("hibernate.connection.password", 
password);
+
+       return emfProps;
+    }
+
+
      /**
       * Loads properties from given resourceName using given class loader
       * @param resourceName The name of the resource containing properties

Re: Troubles with JPA

Posted by Denis Balazuc <de...@balazuc.net>.
I have finally nailed it down. It came from a misconfiguration of my 
JNDI datasource (which basically had no config at all, starting with no 
connection URL....). This produces a lot of other NPEs in various places 
in Roller along the line.

It is interesting to see that in this case, the JPA implementation used 
apparently doesn't really honor its API doc since an exception was 
expected in the case of a misconfiguration rather than returning a null 
value from its factory (see my patch, which error message isn't really 
helping).

Regards
Denis


Dave wrote:
> On 6/17/07, Denis Balazuc <de...@balazuc.net> wrote:
>> I'm having troubles running the current 4.0 trunk with JPA. I have a
>> NullPointerException that happens during  JPAPersistenceStrategy
>> initialisation. Although I see where that comes from, I do not know how
>> to fix it. It's probably some configuration that I'm missing and you've
>> probably already seen this.
> 
> Denis,
> 
> I haven't seen that particular error before.
> 
> On a related note. I just deployed the latest code from the trunk to
> rollerweblogger.org and I'm using the JPA backend, everything seem to
> be working fine.
> 
> - Dave
> 

Re: Troubles with JPA

Posted by Dave <sn...@gmail.com>.
On 6/17/07, Denis Balazuc <de...@balazuc.net> wrote:
> I'm having troubles running the current 4.0 trunk with JPA. I have a
> NullPointerException that happens during  JPAPersistenceStrategy
> initialisation. Although I see where that comes from, I do not know how
> to fix it. It's probably some configuration that I'm missing and you've
> probably already seen this.

Denis,

I haven't seen that particular error before.

On a related note. I just deployed the latest code from the trunk to
rollerweblogger.org and I'm using the JPA backend, everything seem to
be working fine.

- Dave