[ 
https://issues.apache.org/jira/browse/OPENJPA-1141?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12733526#action_12733526
 ] 

Martin Dirichs commented on OPENJPA-1141:
-----------------------------------------

There seems to be no problem with the mapping of the supplied testcase as such. 
The reported exception is caused while OpenJPA resolves the primary key fields 
of NotepadEntity. Since one of the primary key fields of NotepadEntity is the 
id of another entity, namely TypeEntity, the primary key fields of 
NotepadEntity may only be completely resolved after TypeEntity has been 
resolved. However, the mapping data resolution algorithm of OpenJPA doesn't 
take into account this type of dependency between entities.

See org.apache.openjpa.jdbc.meta.ClassMapping, methods 
resolveNonRelationMappings() and resolveMapping(). Inside the latter, there 
already seems to be a workaround for this deficiency of OpenJPAs resolution 
strategy. Here is says in line 838 (I'm referencing to the 2.0.0-M2 source):
  // set resolve mode to force this field mapping to be 
  // resolved again. The need to resolve again occurs when 
  // a primary key is a relation field with the foreign key
  // annotation. In this situation, this primary key field
  // mapping is resolved during the call to 
  // resolveNonRelationMapping. Since it is a relation
  // field, the foreign key will be constructed. However, 
  // the primary key of the parent entity may not have been 
  // resolved yet, resulting in missing information in the fk

Unfortunately, there are situations such as in the reported test case that 
cause an exception before the code following the above comment runs. A more 
promising strategy would be to resolve the entities in the correct order taking 
into account the dependencies of their primary key fields. Then this workaround 
would not be needed at all and the reported exception would no longer happen.

Of course, the code responsible for determining the correct order of entity 
resolution would have to deal with cycles, which may occur as the result of 
incorrect mappings. However, I can't think of any situation where cyclic 
references of primary key fields between entities would make any sense, so this 
case can probably reported as an error and remain unhandled.

Oh, btw. I would be glad to help testing any fix for this.

> NPE  at 
> org.apache.openjpa.jdbc.meta.MappingInfo.mergeJoinColumn(MappingInfo.java:1400)
> ---------------------------------------------------------------------------------------
>
>                 Key: OPENJPA-1141
>                 URL: https://issues.apache.org/jira/browse/OPENJPA-1141
>             Project: OpenJPA
>          Issue Type: Bug
>          Components: jdbc
>    Affects Versions: 1.2.0
>            Reporter: Yann
>             Fix For: 1.2.2
>
>         Attachments: TestMappingProblem.zip
>
>
> We have the NPE shown below in a reproducible testcase (ZIP attached to JIRA 
> ...).
> We've reduced our complex intended target domain model (about 200+ Entities) 
> to a simpler model with only 3 classes which illustrate the problem: You'll 
> find attached a test project with a first entity which has a a OneToMany 
> (with an ElementJoinColumns, but that shouldn't matter?) to a second entity 
> has a ManyToOne to a third entity. The middle entity has a Composite ID Class 
> including a ManyToOne as a key, which according to 
> http://openjpa.apache.org/builds/1.2.0/apache-openjpa-1.2.0/docs/manual/ref_guide_pc_oid.html#ref_guide_pc_oid_entitypk
>  is supported, so this seems a bug in OpenJPA's mapping algos, somehow?
> <openjpa-1.2.1-r752877:753278 nonfatal general error> 
> org.apache.openjpa.persistence.PersistenceException: null
>         at 
> org.apache.openjpa.kernel.QueryImpl.compileForCompilation(QueryImpl.java:610)
>         at 
> org.apache.openjpa.kernel.QueryImpl.compileForExecutor(QueryImpl.java:667)
>         at 
> org.apache.openjpa.kernel.QueryImpl.getOperation(QueryImpl.java:1492)
>         at 
> org.apache.openjpa.kernel.DelegatingQuery.getOperation(DelegatingQuery.java:123)
>         at 
> org.apache.openjpa.persistence.QueryImpl.execute(QueryImpl.java:243)
>         at 
> org.apache.openjpa.persistence.QueryImpl.getResultList(QueryImpl.java:294)
>         at testcase.TestMappingProblem.doTest(TestMappingProblem.java:42)
>         at testcase.TestMappingProblem.testIt(TestMappingProblem.java:20)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>         at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>         at java.lang.reflect.Method.invoke(Method.java:597)
>         at junit.framework.TestCase.runTest(TestCase.java:154)
>         at junit.framework.TestCase.runBare(TestCase.java:127)
>         at junit.framework.TestResult$1.protect(TestResult.java:106)
>         at junit.framework.TestResult.runProtected(TestResult.java:124)
>         at junit.framework.TestResult.run(TestResult.java:109)
>         at junit.framework.TestCase.run(TestCase.java:118)
>         at junit.framework.TestSuite.runTest(TestSuite.java:208)
>         at junit.framework.TestSuite.run(TestSuite.java:203)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>         at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>         at java.lang.reflect.Method.invoke(Method.java:597)
>         at 
> org.apache.maven.surefire.junit.JUnitTestSet.execute(JUnitTestSet.java:213)
>         at 
> org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
>         at 
> org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
>         at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
>         at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         at 
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>         at 
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>         at java.lang.reflect.Method.invoke(Method.java:597)
>         at 
> org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
>         at 
> org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)
> Caused by: java.lang.NullPointerException
>         at 
> org.apache.openjpa.jdbc.meta.MappingInfo.mergeJoinColumn(MappingInfo.java:1400)
>         at 
> org.apache.openjpa.jdbc.meta.MappingInfo.createJoins(MappingInfo.java:1206)
>         at 
> org.apache.openjpa.jdbc.meta.MappingInfo.createForeignKey(MappingInfo.java:968)
>         at 
> org.apache.openjpa.jdbc.meta.ValueMappingInfo.getTypeJoin(ValueMappingInfo.java:104)
>         at 
> org.apache.openjpa.jdbc.meta.strats.RelationFieldStrategy.map(RelationFieldStrategy.java:157)
>         at 
> org.apache.openjpa.jdbc.meta.FieldMapping.setStrategy(FieldMapping.java:121)
>         at 
> org.apache.openjpa.jdbc.meta.RuntimeStrategyInstaller.installStrategy(RuntimeStrategyInstaller.java:80)
>         at 
> org.apache.openjpa.jdbc.meta.FieldMapping.resolveMapping(FieldMapping.java:454)
>         at 
> org.apache.openjpa.jdbc.meta.FieldMapping.resolve(FieldMapping.java:419)
>         at 
> org.apache.openjpa.jdbc.meta.ClassMapping.resolveNonRelationMappings(ClassMapping.java:869)
>         at 
> org.apache.openjpa.jdbc.meta.MappingRepository.prepareMapping(MappingRepository.java:339)
>         at 
> org.apache.openjpa.meta.MetaDataRepository.preMapping(MetaDataRepository.java:662)
>         at 
> org.apache.openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:549)
>         at 
> org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:308)
>         at 
> org.apache.openjpa.meta.MetaDataRepository.getMetaData(MetaDataRepository.java:363)
>         at 
> org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getClassMetaData(JPQLExpressionBuilder.java:159)
>         at 
> org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.resolveClassMetaData(JPQLExpressionBuilder.java:139)
>         at 
> org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateMetaData(JPQLExpressionBuilder.java:225)
>         at 
> org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateMetaData(JPQLExpressionBuilder.java:195)
>         at 
> org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.getCandidateType(JPQLExpressionBuilder.java:188)
>         at 
> org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder.access$600(JPQLExpressionBuilder.java:69)
>         at 
> org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder$ParsedJPQL.populate(JPQLExpressionBuilder.java:1756)
>         at 
> org.apache.openjpa.kernel.jpql.JPQLParser.populate(JPQLParser.java:56)
>         at 
> org.apache.openjpa.kernel.ExpressionStoreQuery.populateFromCompilation(ExpressionStoreQuery.java:153)
>         at 
> org.apache.openjpa.kernel.QueryImpl.newCompilation(QueryImpl.java:658)
>         at 
> org.apache.openjpa.kernel.QueryImpl.compilationFromCache(QueryImpl.java:639)
>         at 
> org.apache.openjpa.kernel.QueryImpl.compileForCompilation(QueryImpl.java:605)
>         ... 33 more

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to