Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [eclipselink-users] Application Developer Responsibilities whenoverriding java.lang.Object.clone() in EclipseLink JPA mapped classes?

Hi Tom,

I have some further refinements on topic to discuss. My hypothesis is
that one of our clone() methods does not provide the opportunity for the
EclipseLink weaving to execute, and thus yields undesired results. So, I
am hoping you can review the following and let me know if you think this
clone() method is incorrect, or if there is some possible defect in
EclipseLink (we are using 1.0.1).

Suppose we have a OneToMany from Department to Employee, and a back
pointing ManyToOne from Employee to Department, and EclipseLink weaving
is enabled for both of these JPA mapped classes. Lets also assume that
both Department and Employee extend Object (but in my test case they are
a level or two subclassed from Object). Consider the following
overriding clone() methods on Department and Employee:

Department.java
---------------
@OneToMany
private List<Employee> employees;

@Override
public Object clone()
{
    Department clonedDepartment = (Department) super.clone();

    clonedDepartment.employees = new ArrayList<Employee>();

    for (Employee sourceEmployee : this.employees)
    {
        Employee clonedEmployee = (Employee) sourceEmployee.clone();
        clonedDepartment.addEmployee(clonedEmployee);
        clonedEmployee.setDepartment(result);
    }

    return clonedDepartment;
}

Employee.java
-------------
@ManyToOne
private Department department;

@Override
public Object clone()
{
    Employee clonedEmployee = (Employee) super.clone();

    // Cannot include the following line due to infinite recursion
    // but it seems we need a way to allow the underlying ValueHolder
    // that supports the department instance to be cloned. How to do
    // that without calling clone() against the Department instance?
    //clonedEmployee.department = (Department) this.department.clone();

    return clonedEmployee;
}

When a Department (D) with three Employees (E1,E2,E3) is cloned, the
cloned Department (D') instance has three Employee clone instances
(E1',E2',E3'), but the original three Employee instances all now point
to the Department clone (D') instead of the original Department instance
(D). The original Department instance should be treated as read only.

This would make sense if the ValueHolder for the Department in each
Employee instance is in fact the same ValueHolder reference due to the
shallow copy results of super.clone() in Employee.clone(). Changing the
department reference in one (e.g. E1, E1') would change the reference
for both.

Clearly if the Employee clone() method were implemented to construct a
new Employee instance via an Employee constructor for instance, this
problem would not be possible due to the different ValueHolder instances
held in the newly constructed Employee instance. We have some investment
in the clone() framework though, so we are attempting to not disturb
that if possible.

Let me know your thoughts. It feels to me that the ValueHolder on the
Employee class for the Department needs to be copied (but not its
contents as we will be resetting the Department reference immediately
after Employee.clone() returns control to Department.clone()), but not
sure how to get there.

Thanks,

Doug

-----Original Message-----
From: eclipselink-users-bounces@xxxxxxxxxxx
[mailto:eclipselink-users-bounces@xxxxxxxxxxx] On Behalf Of Tom Ware
Sent: Thursday, November 13, 2008 10:57 AM
To: EclipseLink User Discussions
Subject: Re: [eclipselink-users] Application Developer Responsibilities
whenoverriding java.lang.Object.clone() in EclipseLink JPA mapped
classes?

Hi Doug,

   As long as the clone methods on the targets of your relationships are

implemented correctly, you should be fine with cloning the way you
suggest.

   When weaving is enabled, EclipseLink does weave in a 
_persistence_post_clone() method.  That code is added after the call to 
super.clone() and does some clean-up of the weaved code.

Are you seeing problems?

-Tom

Gschwind, Doug wrote:
> Hello everyone,
> 
>  
> 
> I didn't find any information on the wiki on this topic, and that may 
> simply be due to no change in the contract regarding how overriding 
> implementations of clone() should be implemented in EclipseLink JPA 
> mapped classes. However, I am looking for confirmation of that.
> 
>  
> 
> Suppose I have a JPA mapped class, with relationships to other JPA 
> mapped classes as follows:
> 
>  
> 
> @Entity
> 
> public class Container extends Object
> 
> {
> 
>     @OneToOne
> 
>     private A a;
> 
>  
> 
>     @ManyToOne
> 
>     private B b;
> 
>  
> 
>     @OneToMany
> 
>     private List<C> cs;
> 
>  
> 
>     @ManyToMany
> 
>     private List<D> ds;
> 
> }
> 
>  
> 
> Now suppose I wish to create instances of Container by cloning 
> persistent instances. What I am looking for are any differences in the

> overriding clone() implementation if the Container class were defined
as 
> above, or if the Container class was not JPA mapped and had none of
the 
> above annotations. Would the following method suffice within the JPA 
> mapped Container class, assuming the overriding implementation of 
> clone() on the JPA mapped A, B, C, and D classes were equally
appropriate:
> 
>  
> 
> @Override
> 
> public Object clone()
> 
> {
> 
>     Container result = (Container) super.clone();
> 
>  
> 
>     result.a = (A) this.a.clone();
> 
>     result.b = (B) this.b.clone();
> 
>  
> 
>     result.cs = new ArrayList<C>(this.cs.size());
> 
>     for (C sourceC : this.cs)
> 
>     {
> 
>         C cloneC = (C) sourceC.clone();
> 
>         result.cs.add(cloneC);
> 
>         cloneC.setContainer(result);
> 
>     }
> 
>  
> 
>     result.ds = new ArrayList<D>(this.ds.size());
> 
>     for (D sourceD : this.ds)
> 
>     {
> 
>         D cloneD = (D) sourceD.clone();
> 
>         result.ds.add(cloneD);
> 
>         cloneD.setContainer(result);
> 
>     }
> 
> }
> 
>  
> 
> If not, what differences in the above implementation would be 
> recommended for use in the JPA mapped Container class?
> 
>  
> 
> Thanks,
> 
>  
> 
> Doug
> 
>  
> 
> 
> 
> 
> 
> 
> The contents of this electronic mail message and any attachments are
confidential, possibly privileged and intended
> for the addressee(s) only. Only the addressee(s) may read,
disseminate, retain or otherwise use this message. If
> received in error, please immediately inform the sender and then
delete this message without disclosing its contents
> to anyone.
> 
> 
>
------------------------------------------------------------------------
> 
> _______________________________________________
> eclipselink-users mailing list
> eclipselink-users@xxxxxxxxxxx
> https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


Back to the top