openjpa-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From iain <iain.f...@westnet.com.au>
Subject Re: PCEnhancer and MappedSuperclass problem???
Date Sat, 29 Mar 2008 03:23:56 GMT
Hi Amit,

I think (not sure) we might have 2 different problems. The Jira you 
opened indicates a NPE, whereas my problem is an out-of-memory exception...

Cheers, Iain

Patel Amit wrote:
> Hi Craig,
>
> I posted the original issue Iain mentioned in his first post and have
> opened a JIRA (https://issues.apache.org/jira/browse/OPENJPA-524) with a
> test case attached to it that reproduces the problem.
>
> Hope this helps.
>
> Amit
>
> -----Original Message-----
> From: Craig.Russell@Sun.COM [mailto:Craig.Russell@Sun.COM] 
> Sent: Thursday, March 27, 2008 7:04 PM
> To: users@openjpa.apache.org
> Cc: iain.fogg@westnet.com.au
> Subject: Re: PCEnhancer and MappedSuperclass problem???
>
> Hi Iain,
>
> If you could file a JIRA with a (very) small test case attached  
> showing this problem, it will be easier to have some enterprising  
> community member take a closer look. And we can put the test case into  
> the regression suite.
>
>  From examination, I can't tell where the problem is.
>
> Thanks,
>
> Craig
>
> On Mar 26, 2008, at 8:04 PM, iain wrote:
>
>   
>> FWIW, if I remove the inheritance of the MappedSuperclass, the  
>> enhancer has no trouble with my application and things operate as  
>> they should. This seems to indicate that there is a problem with  
>> enhancing inheritance heirarchies, and certainly looks to have  
>> something to do with cycle detection, but I don't know the OpenJPA  
>> code so that is speculation at best
>>
>> At this stage, I'd recommend steering clear of inheritance...
>>
>> Cheers, Iain
>>
>> iain wrote:
>>     
>>> Last month another user posted the following message to the mailing  
>>> list but no-one
>>> was able to help:
>>>
>>>
>>>       
> http://mail-archives.apache.org/mod_mbox/openjpa-users/200802.mbox/ajax/
> %3c822DFF5CD1096F4AA656A0F90E903E910118E720@wbe41.phx.us.sopra%3e
>   
>>> I'm posting a follow-up because I'm experiencing the same symptom  
>>> with openjpa-1.0.2.
>>>
>>> My scenario is a little different to the previous post, and I'll  
>>> try to summarise here.
>>> If I need to post more detail, just let me know. There is something  
>>> strange happening here if
>>> you can make it through to the end where I describe a "work-around"  
>>> to the out-of-memory condition.
>>>
>>> First, here is the tail-end of the trace when I startup my  
>>> application.
>>> I'll reproduce the comment in the OpenJPA code for  
>>> MetaDataRepository.processBuffer - it sounds relevant:
>>>
>>>       // continually pop a metadata and process it until we run  
>>> out; note
>>>       // that each processing call might place more metas in the  
>>> buffer as
>>>       // one class tries to access metadata for another; also note  
>>> that the
>>>       // buffer orders itself from least to most derived
>>>
>>>
>>> Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError:  
>>> Java heap space
>>>       at java.util.ArrayList.ensureCapacity(ArrayList.java:169)
>>>       at java.util.ArrayList.add(ArrayList.java:351)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .meta.MetaDataRepository.processBuffer(MetaDataRepository.java:676)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .meta.MetaDataRepository.resolveMeta(MetaDataRepository.java:575)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa.meta.MetaDataRepository.resolve(MetaDataRepository.java:500)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .meta.MetaDataRepository.getMetaData(MetaDataRepository.java:302)
>>>       at  
>>> org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:241)
>>>       at  
>>> org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:212)
>>>       at  
>>> org.apache.openjpa.enhance.PCEnhancer.<init>(PCEnhancer.java:182)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .enhance 
>>> .ManagedClassSubclasser 
>>> .prepareUnenhancedClasses(ManagedClassSubclasser.java:119)
>>>       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:585)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .kernel 
>>> .AbstractBrokerFactory 
>>> .loadPersistentTypes(AbstractBrokerFactory.java:297)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .kernel.AbstractBrokerFactory.newBroker(AbstractBrokerFactory.java: 
>>> 199)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .kernel 
>>> .DelegatingBrokerFactory.newBroker(DelegatingBrokerFactory.java:142)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .persistence 
>>> .EntityManagerFactoryImpl 
>>> .createEntityManager(EntityManagerFactoryImpl.java:192)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .persistence 
>>> .EntityManagerFactoryImpl 
>>> .createEntityManager(EntityManagerFactoryImpl.java:145)
>>>       at  
>>> org 
>>> .apache 
>>> .openjpa 
>>> .persistence 
>>> .EntityManagerFactoryImpl 
>>> .createEntityManager(EntityManagerFactoryImpl.java:56)
>>>       at  
>>> au 
>>> .com.crabhill.hydrogeoreports.ORMHelper.openSession(ORMHelper.java: 
>>> 38)
>>>       at  
>>> au 
>>> .com 
>>> .crabhill 
>>> .hydrogeoreports.ClientModel.reloadClients(ClientModel.java:206)
>>>       at  
>>> au.com.crabhill.hydrogeoreports.ClientModel.<init>(ClientModel.java: 
>>> 31)
>>>       at  
>>> au 
>>> .com 
>>> .crabhill 
>>> .hydrogeoreports 
>>> .HydrogeoReportsView.<init>(HydrogeoReportsView.java:69)
>>>       at  
>>> au 
>>> .com 
>>> .crabhill 
>>> .hydrogeoreports.HydrogeoReportsApp.startup(HydrogeoReportsApp.java: 
>>> 19)
>>>       at org.jdesktop.application.Application 
>>> $1.run(Application.java:171)
>>>       at  
>>> java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
>>>       at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
>>>       at  
>>> java 
>>> .awt 
>>> .EventDispatchThread 
>>> .pumpOneEventForHierarchy(EventDispatchThread.java:242)
>>>       at  
>>> java 
>>> .awt 
>>> .EventDispatchThread 
>>> .pumpEventsForHierarchy(EventDispatchThread.java:163)
>>>       at  
>>> java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:157)
>>>       at  
>>> java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:149)
>>>
>>> OK, so I seem to have the PCEnhancer thrashing about trying to work  
>>> out my class metadata,
>>> so here are the relevant bits (at least I hope the relevant bits):
>>>
>>> @MappedSuperclass
>>> public abstract class ContactMech extends AbstractBean  implements  
>>> Serializable {
>>> // @Id field omitted for brevity
>>>
>>>   @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
>>>   @ForeignKey
>>>   @JoinColumn(name = "client_id", referencedColumnName =  
>>> "client_id", nullable=false)
>>>   protected Client clientId;
>>> // This is a bidirectional parent-child mapping and the parent  
>>> class (Client)
>>> // includes the required 'mappedBy' attribute in the corresponding
>>> // @OneToMany
>>>
>>>      @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH})
>>>   @ForeignKey
>>>   @JoinColumn(name = "contact_mech_type_id", referencedColumnName =  
>>> "type_id", nullable=false)
>>>   protected ContactMechType contactMechTypeId;
>>> // This is a unidirectional mapping, so no 'mappedBy' in TypeClass
>>> ...
>>> }
>>>
>>> @Entity
>>> @Table(name = "client")
>>> public class Client implements Serializable {
>>> // @Id field omitted for brevity
>>>
>>> // See below for the owning side of these bidirectional  
>>> relationships...
>>>   @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE,  
>>> CascadeType.REMOVE, CascadeType.REFRESH}, mappedBy = "clientId")
>>>   @OrderBy("emailAddress ASC")
>>>   private List<CMEmail> emails;
>>>      @OneToMany(fetch = FetchType.LAZY, cascade =  
>>> {CascadeType.MERGE, CascadeType.REMOVE, CascadeType.REFRESH},  
>>> mappedBy = "clientId")
>>>   @OrderBy("areaCode ASC, phoneNum ASC")
>>>   private List<CMTelecom> telecoms;
>>>      @OneToMany(fetch = FetchType.LAZY, cascade =  
>>> {CascadeType.MERGE, CascadeType.REMOVE, CascadeType.REFRESH},  
>>> mappedBy = "clientId")
>>>   private List<CMAddress> addresses;
>>> ...
>>> }
>>>   Note in the following there is a self-referencing mapping  
>>> (implementing a type hierarchy).
>>> @Entity
>>> @Table(name = "contact_mech_type")
>>> public class ContactMechType implements Serializable {
>>>   @Id
>>>   @Column(name = "type_id", nullable = false)
>>>   private String typeId;
>>>      @ManyToOne(fetch = FetchType.EAGER)
>>>   @ForeignKey
>>>   @JoinColumn(name = "parent_type_id", referencedColumnName =  
>>> "type_id", nullable = true)
>>>   private ContactMechType parentType;
>>>    // This is the inverse of the above
>>>   @OneToMany(fetch = FetchType.EAGER, mappedBy = "parentType")
>>>   private List<ContactMechType> subTypes;
>>> ...
>>> }
>>>
>>> Then I have three (3) subclasses of ContactMech which add an extra  
>>> few fields, one of
>>> which is a JoinTable mapping:
>>>
>>> @Entity
>>> @Table(name = "email")
>>> // Do I need the following if I don't plan to inherit from THIS  
>>> class. Obviously I inherit from the MappedSuperclass above,
>>> // but not sure what effect the @Inheritance annotation has on this  
>>> class.
>>> @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
>>> public class CMEmail extends ContactMech implements Serializable {
>>> // Simple @Column fields ommitted for brevity
>>>
>>> // More on this one in a minute       @ManyToMany(fetch =  
>>> FetchType.EAGER)
>>>   @JoinTable(
>>>       name = "email_purpose",        joinColumns =  
>>> {@JoinColumn(name = "contact_mech_id", referencedColumnName =  
>>> "contact_mech_id")},
>>>       inverseJoinColumns = {@JoinColumn(name = "purpose_type_id",  
>>> referencedColumnName = "purpose_id")}
>>>   )
>>>   private List<ContactMechPurposeType> purposes;
>>> ...
>>> }
>>>
>>> @Entity
>>> @Table(name = "telecom")
>>> @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
>>> public class CMTelecom extends ContactMech implements Serializable {
>>>
>>> // As above, but we use a different JoinTable...
>>>   @ManyToMany(fetch = FetchType.EAGER)
>>>   @JoinTable(
>>>       name = "telecom_purpose",        joinColumns =  
>>> {@JoinColumn(name = "contact_mech_id", referencedColumnName =  
>>> "contact_mech_id")},
>>>       inverseJoinColumns = {@JoinColumn(name = "purpose_type_id",  
>>> referencedColumnName = "purpose_id")}
>>>   )
>>>   private List<ContactMechPurposeType> purposes;
>>> ...
>>> }
>>>
>>> @Entity
>>> @Table(name = "address")
>>> @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
>>> public class CMAddress extends ContactMech implements Serializable {
>>>
>>> // Ditto    @ManyToMany(fetch = FetchType.EAGER)
>>>   @JoinTable(
>>>       name = "address_purpose",        joinColumns =  
>>> {@JoinColumn(name = "contact_mech_id", referencedColumnName =  
>>> "contact_mech_id")},
>>>       inverseJoinColumns = {@JoinColumn(name = "purpose_type_id",  
>>> referencedColumnName = "purpose_id")}
>>>   )
>>>   private List<ContactMechPurposeType> purposes;
>>> ...
>>> }
>>>
>>> Last but not least...
>>>
>>> @Entity
>>> @Table(name = "contact_mech_purpose_type")
>>> public class ContactMechPurposeType implements Serializable {
>>> // Omitted @Id field and various @Column fields for brevity
>>>
>>>   @ManyToOne
>>>   @ForeignKey
>>>   @JoinColumn(name = "type_id", referencedColumnName = "type_id",  
>>> nullable=false)
>>>   private ContactMechType typeId;
>>> ...
>>> }
>>>
>>> What concerns me about my class network is circular references and  
>>> what PCEnhancer is doing to
>>> them (given the comment I pasted from the OpenJPA source, above).
>>>
>>> To summarise, here's the reference table for all the classes above  
>>> (and which classes they references):
>>>
>>> Client:                 CMEmail, CMTelecom, CMAddress
>>> - these references are all backpointers in bidirectionals
>>> CMEmail:                Client, ContactMechType,  
>>> ContactMechPurposeType
>>> CMTelecom:              Client, ContactMechType,  
>>> ContactMechPurposeType
>>> CMAddress:              Client, ContactMechType,  
>>> ContactMechPurposeType
>>> - In the above 3, Client and ContactMechType references are via  
>>> inheritance of ContactMechType
>>> ContactMechType:        ContactMechType (self-reference)
>>> ContactMechPurposeType: ContactMechType
>>>
>>> NOW FOR THE WIERD BIT...
>>>
>>> If I change my Client class (above) to temporarily "disable" any  
>>> one of the mappings 'emails',
>>> 'addresses', 'telecoms', by tagging the field as @Transient instead  
>>> of a backpointer to the
>>> bidirectional mapping, this makes the mapping unidirectional at the  
>>> other end, obviously.
>>>
>>> When I do this, I don't get the PCEnhancer memory-slurp problem,  
>>> and the application runs!?!?!
>>> (except for the bits that rely on the disable field). Note I only  
>>> have to disable ONE of these
>>> backpointers for things get past the memory slurp.
>>>
>>> Help!!!
>>>
>>> And thanks for your patience if got this far...
>>>
>>> Cheers, Iain
>>>
>>>
>>>
>>>       
>>
>> -- 
>> No virus found in this outgoing message.
>> Checked by AVG. Version: 7.5.519 / Virus Database: 269.22.0 -  
>> Release Date: 24/03/2008 12:00 AM
>>
>>     
>
> Craig Russell
> Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
> 408 276-5638 mailto:Craig.Russell@sun.com
> P.S. A good JDO? O, Gasp!
>
>
>
>   



-- 
No virus found in this outgoing message.
Checked by AVG. 
Version: 7.5.519 / Virus Database: 269.22.1/1348 - Release Date: 28/03/2008 10:58 AM


Mime
View raw message