[MOXy] setting bi-directional references during unmarshalling

View: New views
7 Messages — Rating Filter:   Alert me  

[MOXy] setting bi-directional references during unmarshalling

by polly.c.chang :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I have a bi-directional relationship between Parent and Child classes like this:

public class Parent {
    private List<Child> children;

    public List<Child> getChildren()
    public void setChildren(List<Child> children)
    public void addChild(final Child child) {
        this.getChildren().add(child);
        child.setParent(this);
    }
    public void removeChild(final Child child) {
        this.getChildren().remove(child);
        child.setParent(null);
    }
}

public class Child {
    private Parent parent;

    public void setParent(Parent parent)
    public Parent getParent()
}

When I unmarshal the Parent object, I find that the "children" collection contains Child objects that do not have the back-reference to the Parent.  This is probably because the Child objects were unmarshalled and set directly into the "children" collection.  How do I change the behavior so that EclipseLink MOXy calls the addChild() method for each Child object?  I looked around EclipseLink Workbench and the schema, but I can't find any mappings that look suitable.  Does MOXy support adding objects into a collection by calling an add() method?  

If MOXy does not support calling an add() method for unmarshalling collections, then the only workaround that I can think of is to turn on "method accessing" for each bi-directional collection so that MOXy uses the getter and setter methods for the list.  Then the setter needs to go through the collection and fix up the back references to the Parent.  Usually my setter is private/protected, so I assume that I'd have to make it public too for EclipseLink to use it.

What do you recommend?

Thanks!
--Polly

Re: [MOXy] setting bi-directional references during unmarshalling

by Matt MacIvor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey Polly,

We're currently working on better support for handling bi-directional relationship mappings in EclipseLink. Currently in EclipseLink 1.2 (which is available today) for containment relationships, you can configure the mapping to automatically set the back-reference when it's populating the collection. This functionality isn't currently exposed in the MappingWorkbench but is available through the mapping APIs, Project XML and in JAXB through a custom annotation.

Using the mapping APIs you would do something like:
XMLCompositeCollectionMapping childMapping = new XMLCompositeCollectionMapping();
childMapping.setXPath("children/child");
childMapping.setReferenceClass(Child.class);
//Specify the name of the attribute on the reference class that points back to the container object
childMapping.setContainerAttributeName("parent");
childMapping.setContainerGetMethodName("getParent");
childMapping.setContainerSetMethodName("setParent");
parentDescriptor.addMapping(childMapping);

If you're using Project XML,  this can also be specified in the xml version of the project using the <container-attribute> element on the composite mapping.

In EclipseLink 1.2 this support is only availabe for Containment based mappings (XMLCompositeObjectMapping and XMLCompositeCollectionMapping), but EclipseLink 2.0 will have expanded support for bi-directional relationships to also include reference mappings.

Hope this helps,

-Matt

polly.c.chang wrote:
Hi,

I have a bi-directional relationship between Parent and Child classes like
this:

public class Parent {
    private List<Child> children;

    public List<Child> getChildren()
    public void setChildren(List<Child> children)
    public void addChild(final Child child) {
        this.getChildren().add(child);
	child.setParent(this);
    }
    public void removeChild(final Child child) {
        this.getChildren().remove(child);
	child.setParent(null);
    }
}

public class Child {
    private Parent parent;

    public void setParent(Parent parent)
    public Parent getParent()
}

When I unmarshal the Parent object, I find that the "children" collection
contains Child objects that do not have the back-reference to the Parent. 
This is probably because the Child objects were unmarshalled and set
directly into the "children" collection.  How do I change the behavior so
that EclipseLink MOXy calls the addChild() method for each Child object?  I
looked around EclipseLink Workbench and the schema, but I can't find any
mappings that look suitable.  Does MOXy support adding objects into a
collection by calling an add() method?  

If MOXy does not support calling an add() method for unmarshalling
collections, then the only workaround that I can think of is to turn on
"method accessing" for each bi-directional collection so that MOXy uses the
getter and setter methods for the list.  Then the setter needs to go through
the collection and fix up the back references to the Parent.  Usually my
setter is private/protected, so I assume that I'd have to make it public too
for EclipseLink to use it. 

What do you recommend?

Thanks!
--Polly
  

_______________________________________________
eclipselink-users mailing list
eclipselink-users@...
https://dev.eclipse.org/mailman/listinfo/eclipselink-users

Re: [MOXy] setting bi-directional references during unmarshalling

by polly.c.chang :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Matt,

Thank you for the quick and informative response!  :)  I am currently using EL 1.1.2.  It sounds like there's a good reason to upgrade to 1.2.  I do have a few more questions though:

1.  The example that you described below would work well for 1:many bi-directional relationships.  But what about many:many bi-directional relationships?  For example, if class "A" has a collection of B's, and "B" has a collection of A's, the code to set the back-reference then looks like:

        public void addB(B b) {
                        this.getBs().add(b);
                        b.getAs().add(this);
                }
        }

EL 1.2 can take care of this too?

2.  Would the workaround that I have described work?  Does EclipseLink need public getters and setters if I turn on "method access"?  Or would private/protected methods be ok?

Thanks!
--Polly


Matt MacIvor wrote:
Hey Polly,

We're currently working on better support for handling bi-directional
relationship mappings in EclipseLink. Currently in EclipseLink 1.2
(which is available today) for containment relationships, you can
configure the mapping to automatically set the back-reference when it's
populating the collection. This functionality isn't currently exposed
in the MappingWorkbench but is available through the mapping APIs,
Project XML and in JAXB through a custom annotation.

Using the mapping APIs you would do something like:
XMLCompositeCollectionMapping childMapping = new
XMLCompositeCollectionMapping();
childMapping.setXPath("children/child");
childMapping.setReferenceClass(Child.class);
//Specify the name of the attribute on the reference class that points
back to the container object
childMapping.setContainerAttributeName("parent");
childMapping.setContainerGetMethodName("getParent");
childMapping.setContainerSetMethodName("setParent");
parentDescriptor.addMapping(childMapping);

If you're using Project XML,  this can also be specified in the xml
version of the project using the <container-attribute> element on
the composite mapping.

In EclipseLink 1.2 this support is only availabe for Containment based
mappings (XMLCompositeObjectMapping and XMLCompositeCollectionMapping),
but EclipseLink 2.0 will have expanded support for bi-directional
relationships to also include reference mappings.

Hope this helps,

-Matt

polly.c.chang wrote:

  Hi,

I have a bi-directional relationship between Parent and Child classes like
this:

public class Parent {
    private List<Child> children;

    public List<Child> getChildren()
    public void setChildren(List<Child> children)
    public void addChild(final Child child) {
        this.getChildren().add(child);
        child.setParent(this);
    }
    public void removeChild(final Child child) {
        this.getChildren().remove(child);
        child.setParent(null);
    }
}

public class Child {
    private Parent parent;

    public void setParent(Parent parent)
    public Parent getParent()
}

When I unmarshal the Parent object, I find that the "children" collection
contains Child objects that do not have the back-reference to the Parent.
This is probably because the Child objects were unmarshalled and set
directly into the "children" collection.  How do I change the behavior so
that EclipseLink MOXy calls the addChild() method for each Child object?  I
looked around EclipseLink Workbench and the schema, but I can't find any
mappings that look suitable.  Does MOXy support adding objects into a
collection by calling an add() method?  

If MOXy does not support calling an add() method for unmarshalling
collections, then the only workaround that I can think of is to turn on
"method accessing" for each bi-directional collection so that MOXy uses the
getter and setter methods for the list.  Then the setter needs to go through
the collection and fix up the back references to the Parent.  Usually my
setter is private/protected, so I assume that I'd have to make it public too
for EclipseLink to use it.

What do you recommend?

Thanks!
--Polly
 




_______________________________________________
eclipselink-users mailing list
eclipselink-users@eclipse.org
https://dev.eclipse.org/mailman/listinfo/eclipselink-users

Re: [MOXy] setting bi-directional references during unmarshalling

by Matt MacIvor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Polly,

The current support in EclipseLink 1.2 wouldn't handle the case of a many-to-many backpointer. EclipseLink 1.2 only handles backpointers on composite mappings, and since composite mappings are privately-owned, the many to many case isn't handled here. The updated support going into EclipseLink 2.0 includes support for Reference mappings which allows for the many-to-many case. This support will be available in the nightly EclipseLink 2.0 builds this week if you'd like to try it out. I'll let you know once the code is available.

Using method access on your mapping to set the backpointer yourself as you described would be a good workaround. I did a quick test and found that private and protected getters/setters will work for method access if you don't want to make the methods public.

polly.c.chang wrote:
Hi Matt,

Thank you for the quick and informative response!  :)  I am currently using
EL 1.1.2.  It sounds like there's a good reason to upgrade to 1.2.  I do
have a few more questions though:

1.  The example that you described below would work well for 1:many
bi-directional relationships.  But what about many:many bi-directional
relationships?  For example, if class "A" has a collection of B's, and "B"
has a collection of A's, the code to set the back-reference then looks like:

	public void addB(B b) {
			this.getBs().add(b);
			b.getAs().add(this);
		}
	}

EL 1.2 can take care of this too?

2.  Would the workaround that I have described work?  Does EclipseLink need
public getters and setters if I turn on "method access"?  Or would
private/protected methods be ok?

Thanks!
--Polly



Matt MacIvor wrote:
  
Hey Polly, 

We're currently working on better support for handling bi-directional
relationship mappings in EclipseLink. Currently in EclipseLink 1.2
(which is available today) for containment relationships, you can
configure the mapping to automatically set the back-reference when it's
populating the collection. This functionality isn't currently exposed
in the MappingWorkbench but is available through the mapping APIs,
Project XML and in JAXB through a custom annotation. 

Using the mapping APIs you would do something like: 
XMLCompositeCollectionMapping childMapping = new
XMLCompositeCollectionMapping(); 
childMapping.setXPath("children/child"); 
childMapping.setReferenceClass(Child.class); 
//Specify the name of the attribute on the reference class that points
back to the container object 
childMapping.setContainerAttributeName("parent"); 
childMapping.setContainerGetMethodName("getParent"); 
childMapping.setContainerSetMethodName("setParent"); 
parentDescriptor.addMapping(childMapping); 

If you're using Project XML,&nbsp; this can also be specified in the xml
version of the project using the &lt;container-attribute&gt; element on
the composite mapping. 

In EclipseLink 1.2 this support is only availabe for Containment based
mappings (XMLCompositeObjectMapping and XMLCompositeCollectionMapping),
but EclipseLink 2.0 will have expanded support for bi-directional
relationships to also include reference mappings. 

Hope this helps, 

-Matt 

polly.c.chang wrote:

  Hi,

I have a bi-directional relationship between Parent and Child classes like
this:

public class Parent {
    private List&lt;Child&gt; children;

    public List&lt;Child&gt; getChildren()
    public void setChildren(List&lt;Child&gt; children)
    public void addChild(final Child child) {
        this.getChildren().add(child);
	child.setParent(this);
    }
    public void removeChild(final Child child) {
        this.getChildren().remove(child);
	child.setParent(null);
    }
}

public class Child {
    private Parent parent;

    public void setParent(Parent parent)
    public Parent getParent()
}

When I unmarshal the Parent object, I find that the "children" collection
contains Child objects that do not have the back-reference to the Parent. 
This is probably because the Child objects were unmarshalled and set
directly into the "children" collection.  How do I change the behavior so
that EclipseLink MOXy calls the addChild() method for each Child object? 
I
looked around EclipseLink Workbench and the schema, but I can't find any
mappings that look suitable.  Does MOXy support adding objects into a
collection by calling an add() method?  

If MOXy does not support calling an add() method for unmarshalling
collections, then the only workaround that I can think of is to turn on
"method accessing" for each bi-directional collection so that MOXy uses
the
getter and setter methods for the list.  Then the setter needs to go
through
the collection and fix up the back references to the Parent.  Usually my
setter is private/protected, so I assume that I'd have to make it public
too
for EclipseLink to use it. 

What do you recommend?

Thanks!
--Polly
  




_______________________________________________
eclipselink-users mailing list
eclipselink-users@...
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


    

  

_______________________________________________
eclipselink-users mailing list
eclipselink-users@...
https://dev.eclipse.org/mailman/listinfo/eclipselink-users

Re: [MOXy] setting bi-directional references during unmarshalling

by polly.c.chang :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Matt,

We use Composite mappings on many-to-many bidirectional associations also.  We do not use the Reference mappings at all.  Would it be possible to have a future version of Eclipse 1.2 or 2.0 to support setting the back-reference on many-to-many Composite mappings?

Thanks for testing and letting me know that EclipseLink can use private accessors for OXM!  

Thanks,
Polly

Matt MacIvor wrote:
>
> Hi Polly,
>
> The current support in EclipseLink 1.2 wouldn't handle the case of a
> many-to-many backpointer. EclipseLink 1.2 only handles backpointers on
> composite mappings, and since composite mappings are privately-owned,
> the many to many case isn't handled here. The updated support going
> into EclipseLink 2.0 includes support for Reference mappings which
> allows for the many-to-many case. This support will be available in the
> nightly EclipseLink 2.0 builds this week if you'd like to try it out.
> I'll let you know once the code is available.
>
> Using method access on your mapping to set the backpointer yourself as
> you described would be a good workaround. I did a quick test and found
> that private and protected getters/setters will work for method access
> if you don't want to make the methods public.
>

Re: [MOXy] setting bi-directional references during unmarshalling

by Matt MacIvor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Polly,

Would it be possible for you to send a usecase/example of using a Many-To-Many bidirectional relationship with a composite mapping? I'm not sure how an object that is the target of a composite mapping could ever have more than one owning object in an XML document.

I may be missing something obvious, but if you have a usecase for this, it's something that we could potentially support.

Thanks,

-Matt

polly.c.chang wrote:
Hi Matt,

We use Composite mappings on many-to-many bidirectional associations also. 
We do not use the Reference mappings at all.  Would it be possible to have a
future version of Eclipse 1.2 or 2.0 to support setting the back-reference
on many-to-many Composite mappings?

Thanks for testing and letting me know that EclipseLink can use private
accessors for OXM!  

Thanks,
Polly

Matt MacIvor wrote:
  
Hi Polly, 

The current support in EclipseLink 1.2 wouldn't handle the case of a
many-to-many backpointer. EclipseLink 1.2 only handles backpointers on
composite mappings, and since composite mappings are privately-owned,
the many to many case isn't handled here. The updated support going
into EclipseLink 2.0 includes support for Reference mappings which
allows for the many-to-many case. This support will be available in the
nightly EclipseLink 2.0 builds this week if you'd like to try it out.
I'll let you know once the code is available. 

Using method access on your mapping to set the backpointer yourself as
you described would be a good workaround. I did a quick test and found
that private and protected getters/setters will work for method access
if you don't want to make the methods public. 

    

  

_______________________________________________
eclipselink-users mailing list
eclipselink-users@...
https://dev.eclipse.org/mailman/listinfo/eclipselink-users

Re: [MOXy] setting bi-directional references during unmarshalling

by polly.c.chang :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Matt,

Sure, I'm putting some unit tests together right now.  I'll send you those when they are ready.

Thanks!
--Polly

Matt MacIvor wrote:
Hi Polly,

Would it be possible for you to send a usecase/example of using a
Many-To-Many bidirectional relationship with a composite mapping? I'm
not sure how an object that is the target of a composite mapping could
ever have more than one owning object in an XML document.

I may be missing something obvious, but if you have a usecase for this,
it's something that we could potentially support.

Thanks,

-Matt

polly.c.chang wrote:

  Hi Matt,

We use Composite mappings on many-to-many bidirectional associations also.
We do not use the Reference mappings at all.  Would it be possible to have a
future version of Eclipse 1.2 or 2.0 to support setting the back-reference
on many-to-many Composite mappings?

Thanks for testing and letting me know that EclipseLink can use private
accessors for OXM!  

Thanks,
Polly

Matt MacIvor wrote:
 
 
    Hi Polly,

The current support in EclipseLink 1.2 wouldn't handle the case of a
many-to-many backpointer. EclipseLink 1.2 only handles backpointers on
composite mappings, and since composite mappings are privately-owned,
the many to many case isn't handled here. The updated support going
into EclipseLink 2.0 includes support for Reference mappings which
allows for the many-to-many case. This support will be available in the
nightly EclipseLink 2.0 builds this week if you'd like to try it out.
I'll let you know once the code is available.

Using method access on your mapping to set the backpointer yourself as
you described would be a good workaround. I did a quick test and found
that private and protected getters/setters will work for method access
if you don't want to make the methods public.

   
 
 
 




_______________________________________________
eclipselink-users mailing list
eclipselink-users@eclipse.org
https://dev.eclipse.org/mailman/listinfo/eclipselink-users