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: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] 
Sent: Thursday, March 27, 2008 7:04 PM
To: [email protected]
Cc: [EMAIL PROTECTED]
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/
[EMAIL PROTECTED]
>>
>> 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 =  
>> [EMAIL PROTECTED](name = "contact_mech_id", referencedColumnName =  
>> "contact_mech_id")},
>>       inverseJoinColumns = [EMAIL PROTECTED](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 =  
>> [EMAIL PROTECTED](name = "contact_mech_id", referencedColumnName =  
>> "contact_mech_id")},
>>       inverseJoinColumns = [EMAIL PROTECTED](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 =  
>> [EMAIL PROTECTED](name = "contact_mech_id", referencedColumnName =  
>> "contact_mech_id")},
>>       inverseJoinColumns = [EMAIL PROTECTED](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:[EMAIL PROTECTED]
P.S. A good JDO? O, Gasp!

Reply via email to