Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » NullPointerException in QueryKeyExpression.getQueryKeyOrNull (occurs only in multithreaded environment)
NullPointerException in QueryKeyExpression.getQueryKeyOrNull [message #551953] Tue, 10 August 2010 05:31 Go to previous message
Ana Oleski is currently offline Ana Oleski
Messages: 22
Registered: July 2009
Junior Member
We have this NullPointerException that only happens when several threads execute some batchjob on an AIX with 16 processors.

java.lang.NullPointerException
        at
org.eclipse.persistence.internal.expressions.QueryKeyExpression.getQueryKeyOrNull(QueryKeyExpression.java:472)

Full stacktrace below. Happens when we execute a ReadAllQuery with a simple selection criteria, expressionbuilder.get(attributeName).equal(value)

I stress this, it only happens in production when lots of threads start doing the same thing for all objects of class A. For instance all accounts are updated with interest rates.

Our application uses eclipselink native API. The ServerSession is instantiated
based on an project.xml, for each transaction we acquire a ClientSession and subsequently a UnitOfWork, execute the readAllQuery on the uow, do stuff, commit the transaction. Everything works fine except for the batchjobs

I've looked at the code and I think it can only be a weird threadrace

public QueryKey getQueryKeyOrNull() {
if (!hasQueryKey) {
return null;
}

// Oct 19, 2000 JED
// Added try/catch. This was throwing a NPE in the following case
// expresssionBuilder.get("firstName").get("bob")
//moved by Gordon Yorke to cover validate and normalize
if (getContainingDescriptor() == null) {
throw QueryException.invalidQueryKeyInExpression(getName());
}
if (queryKey == null) {

// //NPE here
queryKey = getContainingDescriptor().getQueryKeyNamed(getName());

if (queryKey == null) {
hasQueryKey = false;
}
}
return queryKey;

}
getContainingDescriptor() calls getDescriptor() either on ObjectExpression, on ExpressionBuilder or on MapEntryExpression. ObjectExpression is the superclass and the method looks like this

public ClassDescriptor getDescriptor() {
        if (isAttribute()) {
            return null;
        }
        if (descriptor == null) {
            // Look first for query keys, then mappings. Ultimately we should have query keys
            // for everything and can dispense with the mapping part.
            ForeignReferenceQueryKey queryKey = (ForeignReferenceQueryKey)getQueryKeyOrNull();
            if (queryKey != null) {
                descriptor = getSession().getDescriptor(queryKey.getReferenceClass());
                return convertToCastDescriptor(descriptor, getSession());
            }
            if (getMapping() == null) {
                throw QueryException.invalidQueryKeyInExpression(this);
            }

            // We assume this is either a foreign reference or an aggregate mapping
            descriptor = getMapping().getReferenceDescriptor();
            if (getMapping().isVariableOneToOneMapping()) {
                throw QueryException.cannotQueryAcrossAVariableOneToOneMapping(getMapping(), descriptor);
            }
            convertToCastDescriptor(descriptor, getSession());
        }
        return descriptor;

    }


descriptor is a transient member variable of the ObjectExpression class.
I think it might help to make it at least volatile. Or maybe the whole method should be synchronized.


Anyway, I've already filed about 5 months ago a bug for this problem: https://bugs.eclipse.org/bugs/show_bug.cgi?id=305112.
I'm writing in the forum because I would really like an workaround until the bug is hopefully fixed. Some way to trigger this method after login but before the threads start doing their work.

I'd be grateful for any suggestions,

Ana

java.lang.NullPointerException
        at org.eclipse.persistence.internal.expressions.QueryKeyExpression.getQueryKeyOrNull(QueryKeyExpression.java:472)

        at org.eclipse.persistence.internal.expressions.QueryKeyExpression.isAttribute(QueryKeyExpression.java:538)
        at org.eclipse.persistence.internal.expressions.RelationExpression.isObjectComparison(RelationExpression.java:449)

        at org.eclipse.persistence.internal.expressions.RelationExpression.doValuesConform(RelationExpression.java:160)
        at org.eclipse.persistence.internal.expressions.RelationExpression.doesConform(RelationExpression.java:134)
        at org.eclipse.persistence.expressions.Expression.doesConform(Expression.java:1314)
        at org.eclipse.persistence.internal.identitymaps.IdentityMapManager.getAllFromIdentityMap(IdentityMapManager.java:483)

        at org.eclipse.persistence.internal.sessions.IdentityMapAccessor.getAllFromIdentityMap(IdentityMapAccessor.java:305)

        at org.eclipse.persistence.internal.sessions.UnitOfWorkIdentityMapAccessor.getAllFromIdentityMap(UnitOfWorkIdentityMapAccessor.java:91)

        at org.eclipse.persistence.internal.sessions.IdentityMapAccessor.getAllFromIdentityMap(IdentityMapAccessor.java:281)

        at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.scanForConformingInstances(UnitOfWorkImpl.java:4682)

        at org.eclipse.persistence.queries.ReadAllQuery.conformResult(ReadAllQuery.java:252)
        at org.eclipse.persistence.queries.ReadAllQuery.registerResultInUnitOfWork(ReadAllQuery.java:706)
        at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:420)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1074)
        at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:736)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1034)
        at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:380)
        at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1112)
        at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2909)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1291)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1273)
        at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1233)
        at de.jdpe.bof.bes.query.pm.SimpleQueryManager.performComparisonQuery(SimpleQueryManager.java:336)

 selectionCriteria=
Relation operator [ = ]
   Query Key kontonummer
      Base de.bkm.bes.kontosystem.konto.hauptbuch.BoHauptbuchkonto
   Constant 101000

[Updated on: Tue, 10 August 2010 05:34]

Report message to a moderator

 
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Previous Topic:Lazy is not lazy
Next Topic:ObjectChangeSet always null
Goto Forum:
  


Current Time: Thu May 23 04:35:20 EDT 2013

Powered by FUDForum. Page generated in 0.01907 seconds