Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 348766

Summary: NPE in EntityManagerFactoryImpl#createEntityManagerImpl
Product: z_Archived Reporter: Andrei Ilitchev <andrei.ilitchev>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: CLOSED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: eclipselink.orm-inbox, tom.ware
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
Suggested patch.
none
proposed fix none

Description Andrei Ilitchev CLA 2011-06-08 11:28:42 EDT
Caused by: java.lang.NullPointerException
                at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManagerImpl(EntityManagerFactoryImpl.java:280)
                at org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:268)
...

EntityManagerFactoryImpl has been created without entityManagerSetupImpl:
    public EntityManagerFactoryImpl(DatabaseSessionImpl session) {
        delegate = new EntityManagerFactoryDelegate(session, this);
    }


setupImpl == null causing the exception: setupImpl == null
    protected EntityManagerImpl createEntityManagerImpl(Map properties) {
        EntityManagerSetupImpl setupImpl = delegate.getSetupImpl();
        if (setupImpl.isMetadataExpired()){
...

Suggested fix:
EntityManagerFactoryImpl uses setupImpl in just two places:
1. In createEntityManagerImpl method just check for null:
    protected EntityManagerImpl createEntityManagerImpl(Map properties) {
        EntityManagerSetupImpl setupImpl = delegate.getSetupImpl();
        if (setupImpl != null && setupImpl.isMetadataExpired()){
...

2. In refreshMetadata probably an exception should be thrown explaining that metadata can't be refreshed if the factory was created without setupImpl.

Workaround.
Derive a new class from EntityManagerSetupImpl wrapped around the user-supplied session, something like:

public class MyEntityManagerSetupImpl extends org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl {
  MyEntityManagerSetupImpl(DatabaseSessionImpl session) {
    super();
    this.session = session;
    this.persistenceUnitInfo = new org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo();
  }
  public DatabaseSessionImpl deploy(ClassLoader realClassLoader, Map additionalProperties) {
    return this.session;  
}
}

Pass the session wrapped into MyEntityManagerSetupImpl to EntityManagerFactoryImpl constructor:

new EntityManagerFactoryImpl(new MyEntityManagerSetupImpl(session), new hashMap(0));
Comment 1 Andrei Ilitchev CLA 2011-07-13 16:59:33 EDT
Created attachment 199620 [details]
Suggested patch.
Comment 2 Andrei Ilitchev CLA 2011-07-13 17:07:20 EDT
The patch makes sure that postLogin event is risen after descriptors have been initialized. In SessionBroker case it happens after all the member sessions are logged in and SessionBroker has initialized all descriptors.

preLogin event for member sessions used to be risen twice - that's fixed, too.

Here's the order in which events are risen:
  brokerListener(preLogin(broker))
  
  for each member session:
    memberListener(preLogin(member))
    brokerListener(preLogin(broker))


  for each member session:
    memberListener(postLogin(member))
    brokerListener(postLogin(broker))
  
  brokerListener(postLogin(broker))

The patch is tested in composite.advanced.EntityManagerJUnitTestSuite.testSetup by verifyPrePostLoginEvents method.
Comment 3 Andrei Ilitchev CLA 2011-07-13 17:48:00 EDT
Please disregard the patch - checked here by mistake, should go into bug 348759.
Comment 4 Tom Ware CLA 2011-08-23 11:54:57 EDT
Created attachment 202011 [details]
proposed fix
Comment 5 Tom Ware CLA 2011-08-23 13:53:32 EDT
Fixed as suggested above.

Reviewed by Andrei Ilitchev

Added test to EntityManagerJUnitTestSuite

Tested with JPA LRG
Comment 6 Eclipse Webmaster CLA 2022-06-09 10:30:34 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink