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

Reply via email to