Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Persisting an EMF model in a non-EMF persistance model
Persisting an EMF model in a non-EMF persistance model [message #421120] Fri, 25 July 2008 15:29 Go to next message
Eclipse UserFriend
Originally posted by: swt.magellium.fr

Hello all,

I'm looking for a way to persist my EMF model using Hibernate, but I
think I cannot use Teneo in my case :
I have a "generic" database, that is to say, a DB that is designed to
work with multiple client applications.
Access to this DB is handled by a server java application which uses
Hibernate.
Client applications have access to the persistent model classes, and
they can send requests to the server via WebServices.
For instance, a client application can ask for model objects, modify
them, then send back the modifications to the server...

Now, I have to develop a new client application which will have it's own
EMF model. This EMF model is not the same as the persistence model of
the server application (so I will need to map the model objects of the
two models).
I can add new server WebServices, but I cannot change the server model
contents (I can add annotations or such things, but I cannot add a
dependency to EMF or change contents...).

So my client application must roughly manage the following actions :
- load persistent objects through webServices, then load them in the
local EMF model.
- work transparently with the EMF model
- save the EMF model modifications into the persistent model, and send
the updated persistent objects to the server to update the database

But many problems arise, that's why I'm asking the specialists ;-)

- How can I map the EMF model with the persistence model ?

- How to load objects from the persistent model in the EMF model ?
For instance, if my models (both the server persistence model and the
local EMF model) contain a class A, with a 1..1 reference to another
class B :
### Persistent Model :
public interface PersistentA {
long getId();
void setId(long id);
PersistentB getB();
void setB(PersistentB b);
}
public interface PersistentB {
long getId();
void setId(long id);
}
### EMF Model :
public interface A {
long getId();
void setId(long id);
B getB();
void setB(B b);
}
public interface B {
long getId();
void setId(long id);
}

I can ask the server for a specific instance of persistent class A
through web services. Then, I may manage to create the corresponding
instance of EMF class A, for example :

public A createA(PersistantA pa) {
A a = AFactory.eINSTANCE.createA();
a.setId(pa.getId());
a.setB(createB(pa.getB()));
}

public B createB(PersistantB pb) {
...
}

But if I use this kind of implementation, when loading any object in the
model, I will recursively load every dependencies to other objects, and
I will end up with "all" the database loaded on the client side...
A solution would be something like :

public A createA(PersistantA pa) {
A a = AFactory.eINSTANCE.createA();
a.setId(pa.getId());
a.setB(createBProxy(pa, ...));
}

I won't continue with other implementations details, but I hope you will
understand the problems and that you'll be able to give me some pointers
on how to achieve all this...


Thanks a lot in advance !
Stephane
Re: Persisting an EMF model in a non-EMF persistance model [message #421133 is a reply to message #421120] Mon, 28 July 2008 04:52 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
Hi Stephane,
As you say this is not something for which you can use Teneo.

What you need is some kind of model-to-model transformation. I would transform the xml from the
webservice to xml which can be read by EMF. Afaik this is more or less a manual task but others know
more about this then I do (for example: http://www.eclipse.org/m2m/ but if your situation is simpler
you can use any other templating language, free-marker, xslt, straight java, also of interest is
probably what the open architectureware people are doing: www.openarchitectureware.org).
Regarding the proxying issue you mention. EMF has a nice proxying mechanism which you can use. What
you need to add is that you for EMF proxy resolving use the webservice. What I would do is use your
own resource implementation (extending XMLResourceImpl), load the converted xml from the webservice
into this resource and override the getEObject or getEObjectByID methods to use the webservice for
proxy resolving.

gr. Martin

SWT wrote:
> Hello all,
>
> I'm looking for a way to persist my EMF model using Hibernate, but I
> think I cannot use Teneo in my case :
> I have a "generic" database, that is to say, a DB that is designed to
> work with multiple client applications.
> Access to this DB is handled by a server java application which uses
> Hibernate.
> Client applications have access to the persistent model classes, and
> they can send requests to the server via WebServices.
> For instance, a client application can ask for model objects, modify
> them, then send back the modifications to the server...
>
> Now, I have to develop a new client application which will have it's own
> EMF model. This EMF model is not the same as the persistence model of
> the server application (so I will need to map the model objects of the
> two models).
> I can add new server WebServices, but I cannot change the server model
> contents (I can add annotations or such things, but I cannot add a
> dependency to EMF or change contents...).
>
> So my client application must roughly manage the following actions :
> - load persistent objects through webServices, then load them in the
> local EMF model.
> - work transparently with the EMF model
> - save the EMF model modifications into the persistent model, and send
> the updated persistent objects to the server to update the database
>
> But many problems arise, that's why I'm asking the specialists ;-)
>
> - How can I map the EMF model with the persistence model ?
>
> - How to load objects from the persistent model in the EMF model ?
> For instance, if my models (both the server persistence model and the
> local EMF model) contain a class A, with a 1..1 reference to another
> class B :
> ### Persistent Model :
> public interface PersistentA {
> long getId();
> void setId(long id);
> PersistentB getB();
> void setB(PersistentB b);
> }
> public interface PersistentB {
> long getId();
> void setId(long id);
> }
> ### EMF Model :
> public interface A {
> long getId();
> void setId(long id);
> B getB();
> void setB(B b);
> }
> public interface B {
> long getId();
> void setId(long id);
> }
>
> I can ask the server for a specific instance of persistent class A
> through web services. Then, I may manage to create the corresponding
> instance of EMF class A, for example :
>
> public A createA(PersistantA pa) {
> A a = AFactory.eINSTANCE.createA();
> a.setId(pa.getId());
> a.setB(createB(pa.getB()));
> }
>
> public B createB(PersistantB pb) {
> ...
> }
>
> But if I use this kind of implementation, when loading any object in the
> model, I will recursively load every dependencies to other objects, and
> I will end up with "all" the database loaded on the client side...
> A solution would be something like :
>
> public A createA(PersistantA pa) {
> A a = AFactory.eINSTANCE.createA();
> a.setId(pa.getId());
> a.setB(createBProxy(pa, ...));
> }
>
> I won't continue with other implementations details, but I hope you will
> understand the problems and that you'll be able to give me some pointers
> on how to achieve all this...
>
>
> Thanks a lot in advance !
> Stephane


--

With Regards, Martin Taal

Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
Re: Persisting an EMF model in a non-EMF persistance model [message #421134 is a reply to message #421133] Mon, 28 July 2008 09:33 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: swt.magellium.fr

Hi Martin,

Model-to-model transformation is exactly what I need.
I knew about ATL, but OAW seems even better. I'll definitely have a look
at these solutions. Thank you.

Regarding the proxies, I tried to "copy" Hibernate's mechanism :
I have a global object (equivalent of Hibernate's session) where I can
attach or detach objects found via web services.
To attach an object, I load a persistent object through webservices,
then transform it into local model objects (via mapping). These
resulting objects are attached to the session (reference counted).
Then for each EReference in the newly created local model objects, I
create a proxy. Whenever a method is called on one of these proxy
objects, I load the real referenced object via webservices, and I
replace the proxy by the loaded object (and I count the reference to the
object in the session).

Should I rework this mechanism using EMF Resources ?
I'm not used to Resources (and ResourceSet...) but I think this may be
better : if I understand well, I should use my own ResourceImpl instead
of the "session" object I was talking about...
Are there any documentation on EMF proxies / Resources ?
I think I can find by myself, but with an example or something, it's
often faster :-)

Thank you Martin !
Stephane

Martin Taal wrote :
> Hi Stephane,
> As you say this is not something for which you can use Teneo.
>
> What you need is some kind of model-to-model transformation. I would
> transform the xml from the webservice to xml which can be read by EMF.
> Afaik this is more or less a manual task but others know more about this
> then I do (for example: http://www.eclipse.org/m2m/ but if your
> situation is simpler you can use any other templating language,
> free-marker, xslt, straight java, also of interest is probably what the
> open architectureware people are doing: www.openarchitectureware.org).
> Regarding the proxying issue you mention. EMF has a nice proxying
> mechanism which you can use. What you need to add is that you for EMF
> proxy resolving use the webservice. What I would do is use your own
> resource implementation (extending XMLResourceImpl), load the converted
> xml from the webservice into this resource and override the getEObject
> or getEObjectByID methods to use the webservice for proxy resolving.
>
> gr. Martin
>
> SWT wrote:
>> Hello all,
>>
>> I'm looking for a way to persist my EMF model using Hibernate, but I
>> think I cannot use Teneo in my case :
>> I have a "generic" database, that is to say, a DB that is designed to
>> work with multiple client applications.
>> Access to this DB is handled by a server java application which uses
>> Hibernate.
>> Client applications have access to the persistent model classes, and
>> they can send requests to the server via WebServices.
>> For instance, a client application can ask for model objects, modify
>> them, then send back the modifications to the server...
>>
>> Now, I have to develop a new client application which will have it's own
>> EMF model. This EMF model is not the same as the persistence model of
>> the server application (so I will need to map the model objects of the
>> two models).
>> I can add new server WebServices, but I cannot change the server model
>> contents (I can add annotations or such things, but I cannot add a
>> dependency to EMF or change contents...).
>>
>> So my client application must roughly manage the following actions :
>> - load persistent objects through webServices, then load them in the
>> local EMF model.
>> - work transparently with the EMF model
>> - save the EMF model modifications into the persistent model, and send
>> the updated persistent objects to the server to update the database
>>
>> But many problems arise, that's why I'm asking the specialists ;-)
>>
>> - How can I map the EMF model with the persistence model ?
>>
>> - How to load objects from the persistent model in the EMF model ?
>> For instance, if my models (both the server persistence model and the
>> local EMF model) contain a class A, with a 1..1 reference to another
>> class B :
>> ### Persistent Model :
>> public interface PersistentA {
>> long getId();
>> void setId(long id);
>> PersistentB getB();
>> void setB(PersistentB b);
>> }
>> public interface PersistentB {
>> long getId();
>> void setId(long id);
>> }
>> ### EMF Model :
>> public interface A {
>> long getId();
>> void setId(long id);
>> B getB();
>> void setB(B b);
>> }
>> public interface B {
>> long getId();
>> void setId(long id);
>> }
>>
>> I can ask the server for a specific instance of persistent class A
>> through web services. Then, I may manage to create the corresponding
>> instance of EMF class A, for example :
>>
>> public A createA(PersistantA pa) {
>> A a = AFactory.eINSTANCE.createA();
>> a.setId(pa.getId());
>> a.setB(createB(pa.getB()));
>> }
>>
>> public B createB(PersistantB pb) {
>> ...
>> }
>>
>> But if I use this kind of implementation, when loading any object in
>> the model, I will recursively load every dependencies to other
>> objects, and I will end up with "all" the database loaded on the
>> client side...
>> A solution would be something like :
>>
>> public A createA(PersistantA pa) {
>> A a = AFactory.eINSTANCE.createA();
>> a.setId(pa.getId());
>> a.setB(createBProxy(pa, ...));
>> }
>>
>> I won't continue with other implementations details, but I hope you
>> will understand the problems and that you'll be able to give me some
>> pointers on how to achieve all this...
>>
>>
>> Thanks a lot in advance !
>> Stephane
>
>
Re: Persisting an EMF model in a non-EMF persistance model [message #421135 is a reply to message #421134] Mon, 28 July 2008 10:13 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
Hi Stephane,
There is a difference between EMF and hibernate proxies which you should know although I am not sure
if it makes a difference for you.
The main difference between EMF and Hibernate proxies is that with Hibernate the object itself is
de-proxied while with EMF the reference is de-proxied. Here is an example of how de-proxying is done
for the Book referencing an EMF-proxied Writer (from the EMF library example):
public Writer getAuthor() {
if (author != null && ((EObject)author).eIsProxy()) {
InternalEObject oldAuthor = (InternalEObject)author;
author = (Writer)eResolveProxy(oldAuthor);
if (author != oldAuthor) {
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.RESOLVE, LibraryPackage.BOOK__AUTHOR,
oldAuthor, author));
}
}
return author;
}

What you can see is that the eResolveProxy replaces the Writer instance in the author member. This
is different than the hibernate proxy approach which would would not replace the Writer (==the cglib
wrapped object) but would instead initialize the Writer/cglib object with the real object from the
webservice.

The advantage of EMF over the hibernate proxy approach is that with EMF you don't need to do the
proxying of each object yourselve, and you don't need cglib.

To explain a bit more what happens. The eResolveProxy method is implemented in the base class
BasicEObjectImpl, this eventually does this call: return EcoreUtil.resolve(proxy, this);
The EcoreUtil.resolveProxy gets the Resource from the EObject and from the Resource it gets the
ResourceSet, and then this call is done: resourceSet.getEObject(proxyURI, true)
which is implemented like this:
public EObject getEObject(URI uri, boolean loadOnDemand)
{
Resource resource = getResource(uri.trimFragment(), loadOnDemand);
if (resource != null)
{
return resource.getEObject(uri.fragment());
}
else
{
return null;
}
}

To get this working you should create your own ResourceImpl (which can replace your Session
concept). This resource only needs to implement the getEObject(String uriFragment) method which
calls the webservice to get the object. The uriFragment should map to something which you can use in
the webservice.

At runtime you create your resource through a ResourceSet (do new ResourceSetImpl() to get one). Now
the thing to watch here is that the url you use to create your resource with should match the url
used in the proxies. Otherwise the resourceset can't find your resource again. For example:
resource ur: mgr://my.great.resource
proxy uri: mgr://my.great.resource#object_identifier

Where object_identifier is passed to the getEObject(String uriFragment) in your resource.

Note the protocol mgr, you can tell EMF which resource to create based on the protocol:
Resource.Factory.Registry.INSTANCE.getProtocolToFactoryMap() .put( "mgr", new MyGreatResourceFactory());
MyGreatResourceFactory implements Resource.Factory which has one method createResource(uri).
(I am not sure if this is currently the preferred way of doing this, but it works for me...)

To make live simpler at first you can also just override ResourceSetImpl with your own
implementation which always calls your one Resource to get the EObject. Then if this works fine move
back to the standard EMF way (as this allows more flexibility and is more standard).

gr. Martin

SWT wrote:
> Hi Martin,
>
> Model-to-model transformation is exactly what I need.
> I knew about ATL, but OAW seems even better. I'll definitely have a look
> at these solutions. Thank you.
>
> Regarding the proxies, I tried to "copy" Hibernate's mechanism :
> I have a global object (equivalent of Hibernate's session) where I can
> attach or detach objects found via web services.
> To attach an object, I load a persistent object through webservices,
> then transform it into local model objects (via mapping). These
> resulting objects are attached to the session (reference counted).
> Then for each EReference in the newly created local model objects, I
> create a proxy. Whenever a method is called on one of these proxy
> objects, I load the real referenced object via webservices, and I
> replace the proxy by the loaded object (and I count the reference to the
> object in the session).
>
> Should I rework this mechanism using EMF Resources ?
> I'm not used to Resources (and ResourceSet...) but I think this may be
> better : if I understand well, I should use my own ResourceImpl instead
> of the "session" object I was talking about...
> Are there any documentation on EMF proxies / Resources ?
> I think I can find by myself, but with an example or something, it's
> often faster :-)
>
> Thank you Martin !
> Stephane
>
> Martin Taal wrote :
>> Hi Stephane,
>> As you say this is not something for which you can use Teneo.
>>
>> What you need is some kind of model-to-model transformation. I would
>> transform the xml from the webservice to xml which can be read by EMF.
>> Afaik this is more or less a manual task but others know more about
>> this then I do (for example: http://www.eclipse.org/m2m/ but if your
>> situation is simpler you can use any other templating language,
>> free-marker, xslt, straight java, also of interest is probably what
>> the open architectureware people are doing:
>> www.openarchitectureware.org).
>> Regarding the proxying issue you mention. EMF has a nice proxying
>> mechanism which you can use. What you need to add is that you for EMF
>> proxy resolving use the webservice. What I would do is use your own
>> resource implementation (extending XMLResourceImpl), load the
>> converted xml from the webservice into this resource and override the
>> getEObject or getEObjectByID methods to use the webservice for proxy
>> resolving.
>>
>> gr. Martin
>>
>> SWT wrote:
>>> Hello all,
>>>
>>> I'm looking for a way to persist my EMF model using Hibernate, but I
>>> think I cannot use Teneo in my case :
>>> I have a "generic" database, that is to say, a DB that is designed to
>>> work with multiple client applications.
>>> Access to this DB is handled by a server java application which uses
>>> Hibernate.
>>> Client applications have access to the persistent model classes, and
>>> they can send requests to the server via WebServices.
>>> For instance, a client application can ask for model objects, modify
>>> them, then send back the modifications to the server...
>>>
>>> Now, I have to develop a new client application which will have it's own
>>> EMF model. This EMF model is not the same as the persistence model of
>>> the server application (so I will need to map the model objects of
>>> the two models).
>>> I can add new server WebServices, but I cannot change the server
>>> model contents (I can add annotations or such things, but I cannot
>>> add a dependency to EMF or change contents...).
>>>
>>> So my client application must roughly manage the following actions :
>>> - load persistent objects through webServices, then load them in the
>>> local EMF model.
>>> - work transparently with the EMF model
>>> - save the EMF model modifications into the persistent model, and send
>>> the updated persistent objects to the server to update the database
>>>
>>> But many problems arise, that's why I'm asking the specialists ;-)
>>>
>>> - How can I map the EMF model with the persistence model ?
>>>
>>> - How to load objects from the persistent model in the EMF model ?
>>> For instance, if my models (both the server persistence model and the
>>> local EMF model) contain a class A, with a 1..1 reference to another
>>> class B :
>>> ### Persistent Model :
>>> public interface PersistentA {
>>> long getId();
>>> void setId(long id);
>>> PersistentB getB();
>>> void setB(PersistentB b);
>>> }
>>> public interface PersistentB {
>>> long getId();
>>> void setId(long id);
>>> }
>>> ### EMF Model :
>>> public interface A {
>>> long getId();
>>> void setId(long id);
>>> B getB();
>>> void setB(B b);
>>> }
>>> public interface B {
>>> long getId();
>>> void setId(long id);
>>> }
>>>
>>> I can ask the server for a specific instance of persistent class A
>>> through web services. Then, I may manage to create the corresponding
>>> instance of EMF class A, for example :
>>>
>>> public A createA(PersistantA pa) {
>>> A a = AFactory.eINSTANCE.createA();
>>> a.setId(pa.getId());
>>> a.setB(createB(pa.getB()));
>>> }
>>>
>>> public B createB(PersistantB pb) {
>>> ...
>>> }
>>>
>>> But if I use this kind of implementation, when loading any object in
>>> the model, I will recursively load every dependencies to other
>>> objects, and I will end up with "all" the database loaded on the
>>> client side...
>>> A solution would be something like :
>>>
>>> public A createA(PersistantA pa) {
>>> A a = AFactory.eINSTANCE.createA();
>>> a.setId(pa.getId());
>>> a.setB(createBProxy(pa, ...));
>>> }
>>>
>>> I won't continue with other implementations details, but I hope you
>>> will understand the problems and that you'll be able to give me some
>>> pointers on how to achieve all this...
>>>
>>>
>>> Thanks a lot in advance !
>>> Stephane
>>
>>


--

With Regards, Martin Taal

Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
Re: Persisting an EMF model in a non-EMF persistance model [message #421138 is a reply to message #421135] Mon, 28 July 2008 12:13 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: swt.magellium.fr

Martin,

Thank you a lot, you explained every little things that were still not
clear for me :)
I managed to use my own ResourceFactory (and my own Resource
implementation) last week, but I was using
"resourceSet.getResourceFactoryRegistry()
.getContentTypeToFactoryMap()
.put(Resource.Factory.Registry.DEFAULT_CONTENT_TYPE_IDENTIFI ER,
new CommResourceFactoryImpl());"
Now you've explained the details about URIs, all seems clear. Your
solution is way better! And with your explanation on EMF proxies,
everything becomes simpler :-D
I'll give it a try right now!

Stephane

Martin Taal wrote :
> Hi Stephane,
> There is a difference between EMF and hibernate proxies which you should
> know although I am not sure if it makes a difference for you.
> The main difference between EMF and Hibernate proxies is that with
> Hibernate the object itself is de-proxied while with EMF the reference
> is de-proxied. Here is an example of how de-proxying is done for the
> Book referencing an EMF-proxied Writer (from the EMF library example):
> public Writer getAuthor() {
> if (author != null && ((EObject)author).eIsProxy()) {
> InternalEObject oldAuthor = (InternalEObject)author;
> author = (Writer)eResolveProxy(oldAuthor);
> if (author != oldAuthor) {
> if (eNotificationRequired())
> eNotify(new ENotificationImpl(this,
> Notification.RESOLVE, LibraryPackage.BOOK__AUTHOR, oldAuthor, author));
> }
> }
> return author;
> }
>
> What you can see is that the eResolveProxy replaces the Writer instance
> in the author member. This is different than the hibernate proxy
> approach which would would not replace the Writer (==the cglib wrapped
> object) but would instead initialize the Writer/cglib object with the
> real object from the webservice.
>
> The advantage of EMF over the hibernate proxy approach is that with EMF
> you don't need to do the proxying of each object yourselve, and you
> don't need cglib.
>
> To explain a bit more what happens. The eResolveProxy method is
> implemented in the base class BasicEObjectImpl, this eventually does
> this call: return EcoreUtil.resolve(proxy, this);
> The EcoreUtil.resolveProxy gets the Resource from the EObject and from
> the Resource it gets the ResourceSet, and then this call is done:
> resourceSet.getEObject(proxyURI, true)
> which is implemented like this:
> public EObject getEObject(URI uri, boolean loadOnDemand)
> {
> Resource resource = getResource(uri.trimFragment(), loadOnDemand);
> if (resource != null)
> {
> return resource.getEObject(uri.fragment());
> }
> else
> {
> return null;
> }
> }
>
> To get this working you should create your own ResourceImpl (which can
> replace your Session concept). This resource only needs to implement the
> getEObject(String uriFragment) method which calls the webservice to get
> the object. The uriFragment should map to something which you can use in
> the webservice.
>
> At runtime you create your resource through a ResourceSet (do new
> ResourceSetImpl() to get one). Now the thing to watch here is that the
> url you use to create your resource with should match the url used in
> the proxies. Otherwise the resourceset can't find your resource again.
> For example:
> resource ur: mgr://my.great.resource
> proxy uri: mgr://my.great.resource#object_identifier
>
> Where object_identifier is passed to the getEObject(String uriFragment)
> in your resource.
>
> Note the protocol mgr, you can tell EMF which resource to create based
> on the protocol:
> Resource.Factory.Registry.INSTANCE.getProtocolToFactoryMap() .put( "mgr",
> new MyGreatResourceFactory());
> MyGreatResourceFactory implements Resource.Factory which has one method
> createResource(uri).
> (I am not sure if this is currently the preferred way of doing this, but
> it works for me...)
>
> To make live simpler at first you can also just override ResourceSetImpl
> with your own implementation which always calls your one Resource to get
> the EObject. Then if this works fine move back to the standard EMF way
> (as this allows more flexibility and is more standard).
>
> gr. Martin
>
> SWT wrote:
>> Hi Martin,
>>
>> Model-to-model transformation is exactly what I need.
>> I knew about ATL, but OAW seems even better. I'll definitely have a
>> look at these solutions. Thank you.
>>
>> Regarding the proxies, I tried to "copy" Hibernate's mechanism :
>> I have a global object (equivalent of Hibernate's session) where I can
>> attach or detach objects found via web services.
>> To attach an object, I load a persistent object through webservices,
>> then transform it into local model objects (via mapping). These
>> resulting objects are attached to the session (reference counted).
>> Then for each EReference in the newly created local model objects, I
>> create a proxy. Whenever a method is called on one of these proxy
>> objects, I load the real referenced object via webservices, and I
>> replace the proxy by the loaded object (and I count the reference to
>> the object in the session).
>>
>> Should I rework this mechanism using EMF Resources ?
>> I'm not used to Resources (and ResourceSet...) but I think this may be
>> better : if I understand well, I should use my own ResourceImpl
>> instead of the "session" object I was talking about...
>> Are there any documentation on EMF proxies / Resources ?
>> I think I can find by myself, but with an example or something, it's
>> often faster :-)
>>
>> Thank you Martin !
>> Stephane
>>
>> Martin Taal wrote :
>>> Hi Stephane,
>>> As you say this is not something for which you can use Teneo.
>>>
>>> What you need is some kind of model-to-model transformation. I would
>>> transform the xml from the webservice to xml which can be read by
>>> EMF. Afaik this is more or less a manual task but others know more
>>> about this then I do (for example: http://www.eclipse.org/m2m/ but if
>>> your situation is simpler you can use any other templating language,
>>> free-marker, xslt, straight java, also of interest is probably what
>>> the open architectureware people are doing:
>>> www.openarchitectureware.org).
>>> Regarding the proxying issue you mention. EMF has a nice proxying
>>> mechanism which you can use. What you need to add is that you for EMF
>>> proxy resolving use the webservice. What I would do is use your own
>>> resource implementation (extending XMLResourceImpl), load the
>>> converted xml from the webservice into this resource and override the
>>> getEObject or getEObjectByID methods to use the webservice for proxy
>>> resolving.
>>>
>>> gr. Martin
>>>
>>> SWT wrote:
>>>> Hello all,
>>>>
>>>> I'm looking for a way to persist my EMF model using Hibernate, but I
>>>> think I cannot use Teneo in my case :
>>>> I have a "generic" database, that is to say, a DB that is designed to
>>>> work with multiple client applications.
>>>> Access to this DB is handled by a server java application which uses
>>>> Hibernate.
>>>> Client applications have access to the persistent model classes, and
>>>> they can send requests to the server via WebServices.
>>>> For instance, a client application can ask for model objects, modify
>>>> them, then send back the modifications to the server...
>>>>
>>>> Now, I have to develop a new client application which will have it's
>>>> own
>>>> EMF model. This EMF model is not the same as the persistence model
>>>> of the server application (so I will need to map the model objects
>>>> of the two models).
>>>> I can add new server WebServices, but I cannot change the server
>>>> model contents (I can add annotations or such things, but I cannot
>>>> add a dependency to EMF or change contents...).
>>>>
>>>> So my client application must roughly manage the following actions :
>>>> - load persistent objects through webServices, then load them in the
>>>> local EMF model.
>>>> - work transparently with the EMF model
>>>> - save the EMF model modifications into the persistent model, and send
>>>> the updated persistent objects to the server to update the database
>>>>
>>>> But many problems arise, that's why I'm asking the specialists ;-)
>>>>
>>>> - How can I map the EMF model with the persistence model ?
>>>>
>>>> - How to load objects from the persistent model in the EMF model ?
>>>> For instance, if my models (both the server persistence model and
>>>> the local EMF model) contain a class A, with a 1..1 reference to
>>>> another class B :
>>>> ### Persistent Model :
>>>> public interface PersistentA {
>>>> long getId();
>>>> void setId(long id);
>>>> PersistentB getB();
>>>> void setB(PersistentB b);
>>>> }
>>>> public interface PersistentB {
>>>> long getId();
>>>> void setId(long id);
>>>> }
>>>> ### EMF Model :
>>>> public interface A {
>>>> long getId();
>>>> void setId(long id);
>>>> B getB();
>>>> void setB(B b);
>>>> }
>>>> public interface B {
>>>> long getId();
>>>> void setId(long id);
>>>> }
>>>>
>>>> I can ask the server for a specific instance of persistent class A
>>>> through web services. Then, I may manage to create the corresponding
>>>> instance of EMF class A, for example :
>>>>
>>>> public A createA(PersistantA pa) {
>>>> A a = AFactory.eINSTANCE.createA();
>>>> a.setId(pa.getId());
>>>> a.setB(createB(pa.getB()));
>>>> }
>>>>
>>>> public B createB(PersistantB pb) {
>>>> ...
>>>> }
>>>>
>>>> But if I use this kind of implementation, when loading any object in
>>>> the model, I will recursively load every dependencies to other
>>>> objects, and I will end up with "all" the database loaded on the
>>>> client side...
>>>> A solution would be something like :
>>>>
>>>> public A createA(PersistantA pa) {
>>>> A a = AFactory.eINSTANCE.createA();
>>>> a.setId(pa.getId());
>>>> a.setB(createBProxy(pa, ...));
>>>> }
>>>>
>>>> I won't continue with other implementations details, but I hope you
>>>> will understand the problems and that you'll be able to give me some
>>>> pointers on how to achieve all this...
>>>>
>>>>
>>>> Thanks a lot in advance !
>>>> Stephane
>>>
>>>
>
>
Re: Persisting an EMF model in a non-EMF persistance model [message #421144 is a reply to message #421135] Mon, 28 July 2008 15:02 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: swt.magellium.fr

Martin,

I have some more questions about EMF proxies :
When I implement the getEObject(String uriFragment) method, I can get
the persistent object via webservices, and I can create a new
corresponding model object.
In this case, all references of the new model object are null.
But I need them to be proxies, not null values !
Here is an example implementation :
public EObject getEObject(String uriFragment) {
if (/*...uriFragment...*/) {
// TODO specific cases...
} else {
return getNewEObject(uriFragment);
}
// ...
}
public EObject getNewEObject(uriFragment) {
// Retrieve the corresponding object in database
PersistentObject po = getByURI(uriFragment);
// Convert it to client model object
EObject modelObject = createFromPersistent(po);
return modelObject;
}
public EObject createFromPersistent(PersistentObject po) {
// It's an example, so let's keep it simple :
MyModelObject result =
MyFactory.eINSTANCE.createMyModelObject();
result.setAttr1(po.getAttr1());
result.setAttr2(po.getAttr2());
// etc. for all attributes
// Now the references :
result.setReferenceToOther(?????);
}
In this example, I don't know what to use for "?????".
My idea would be to create a new proxy instance of the referenced object
as follows :

OtherModelObject proxyToOther =
MyFactory.eINSTANCE.createOtherModelObject();
((BasicEObjectImpl) proxyToOther).eSetProxyURI(URI.createURI(getURI()
+ "/"
+ getURIFragment(po)
+ "/"
+ MyPackage.MyModelObject__OtherModelObject ));
result.setReferenceToOther(proxyToOther);

But it seems that if I continue this way, I will re-implement a lot of
the proxying mechanism... I don't even know if the cast
"(BasicEObjectImpl) proxyToOther" is legal / safe, and if it's the good
way for creating proxies...
Maybe I'm missing something ? Maybe there's a facility to handle proxies...

Thank you a lot in advance !

Stephane


Martin Taal wrote :
> Hi Stephane,
> There is a difference between EMF and hibernate proxies which you should
> know although I am not sure if it makes a difference for you.
> The main difference between EMF and Hibernate proxies is that with
> Hibernate the object itself is de-proxied while with EMF the reference
> is de-proxied. Here is an example of how de-proxying is done for the
> Book referencing an EMF-proxied Writer (from the EMF library example):
> public Writer getAuthor() {
> if (author != null && ((EObject)author).eIsProxy()) {
> InternalEObject oldAuthor = (InternalEObject)author;
> author = (Writer)eResolveProxy(oldAuthor);
> if (author != oldAuthor) {
> if (eNotificationRequired())
> eNotify(new ENotificationImpl(this,
> Notification.RESOLVE, LibraryPackage.BOOK__AUTHOR, oldAuthor, author));
> }
> }
> return author;
> }
>
> What you can see is that the eResolveProxy replaces the Writer instance
> in the author member. This is different than the hibernate proxy
> approach which would would not replace the Writer (==the cglib wrapped
> object) but would instead initialize the Writer/cglib object with the
> real object from the webservice.
>
> The advantage of EMF over the hibernate proxy approach is that with EMF
> you don't need to do the proxying of each object yourselve, and you
> don't need cglib.
>
> To explain a bit more what happens. The eResolveProxy method is
> implemented in the base class BasicEObjectImpl, this eventually does
> this call: return EcoreUtil.resolve(proxy, this);
> The EcoreUtil.resolveProxy gets the Resource from the EObject and from
> the Resource it gets the ResourceSet, and then this call is done:
> resourceSet.getEObject(proxyURI, true)
> which is implemented like this:
> public EObject getEObject(URI uri, boolean loadOnDemand)
> {
> Resource resource = getResource(uri.trimFragment(), loadOnDemand);
> if (resource != null)
> {
> return resource.getEObject(uri.fragment());
> }
> else
> {
> return null;
> }
> }
>
> To get this working you should create your own ResourceImpl (which can
> replace your Session concept). This resource only needs to implement the
> getEObject(String uriFragment) method which calls the webservice to get
> the object. The uriFragment should map to something which you can use in
> the webservice.
>
> At runtime you create your resource through a ResourceSet (do new
> ResourceSetImpl() to get one). Now the thing to watch here is that the
> url you use to create your resource with should match the url used in
> the proxies. Otherwise the resourceset can't find your resource again.
> For example:
> resource ur: mgr://my.great.resource
> proxy uri: mgr://my.great.resource#object_identifier
>
> Where object_identifier is passed to the getEObject(String uriFragment)
> in your resource.
>
> Note the protocol mgr, you can tell EMF which resource to create based
> on the protocol:
> Resource.Factory.Registry.INSTANCE.getProtocolToFactoryMap() .put( "mgr",
> new MyGreatResourceFactory());
> MyGreatResourceFactory implements Resource.Factory which has one method
> createResource(uri).
> (I am not sure if this is currently the preferred way of doing this, but
> it works for me...)
>
> To make live simpler at first you can also just override ResourceSetImpl
> with your own implementation which always calls your one Resource to get
> the EObject. Then if this works fine move back to the standard EMF way
> (as this allows more flexibility and is more standard).
>
> gr. Martin
>
> SWT wrote:
>> Hi Martin,
>>
>> Model-to-model transformation is exactly what I need.
>> I knew about ATL, but OAW seems even better. I'll definitely have a
>> look at these solutions. Thank you.
>>
>> Regarding the proxies, I tried to "copy" Hibernate's mechanism :
>> I have a global object (equivalent of Hibernate's session) where I can
>> attach or detach objects found via web services.
>> To attach an object, I load a persistent object through webservices,
>> then transform it into local model objects (via mapping). These
>> resulting objects are attached to the session (reference counted).
>> Then for each EReference in the newly created local model objects, I
>> create a proxy. Whenever a method is called on one of these proxy
>> objects, I load the real referenced object via webservices, and I
>> replace the proxy by the loaded object (and I count the reference to
>> the object in the session).
>>
>> Should I rework this mechanism using EMF Resources ?
>> I'm not used to Resources (and ResourceSet...) but I think this may be
>> better : if I understand well, I should use my own ResourceImpl
>> instead of the "session" object I was talking about...
>> Are there any documentation on EMF proxies / Resources ?
>> I think I can find by myself, but with an example or something, it's
>> often faster :-)
>>
>> Thank you Martin !
>> Stephane
>>
>> Martin Taal wrote :
>>> Hi Stephane,
>>> As you say this is not something for which you can use Teneo.
>>>
>>> What you need is some kind of model-to-model transformation. I would
>>> transform the xml from the webservice to xml which can be read by
>>> EMF. Afaik this is more or less a manual task but others know more
>>> about this then I do (for example: http://www.eclipse.org/m2m/ but if
>>> your situation is simpler you can use any other templating language,
>>> free-marker, xslt, straight java, also of interest is probably what
>>> the open architectureware people are doing:
>>> www.openarchitectureware.org).
>>> Regarding the proxying issue you mention. EMF has a nice proxying
>>> mechanism which you can use. What you need to add is that you for EMF
>>> proxy resolving use the webservice. What I would do is use your own
>>> resource implementation (extending XMLResourceImpl), load the
>>> converted xml from the webservice into this resource and override the
>>> getEObject or getEObjectByID methods to use the webservice for proxy
>>> resolving.
>>>
>>> gr. Martin
>>>
>>> SWT wrote:
>>>> Hello all,
>>>>
>>>> I'm looking for a way to persist my EMF model using Hibernate, but I
>>>> think I cannot use Teneo in my case :
>>>> I have a "generic" database, that is to say, a DB that is designed to
>>>> work with multiple client applications.
>>>> Access to this DB is handled by a server java application which uses
>>>> Hibernate.
>>>> Client applications have access to the persistent model classes, and
>>>> they can send requests to the server via WebServices.
>>>> For instance, a client application can ask for model objects, modify
>>>> them, then send back the modifications to the server...
>>>>
>>>> Now, I have to develop a new client application which will have it's
>>>> own
>>>> EMF model. This EMF model is not the same as the persistence model
>>>> of the server application (so I will need to map the model objects
>>>> of the two models).
>>>> I can add new server WebServices, but I cannot change the server
>>>> model contents (I can add annotations or such things, but I cannot
>>>> add a dependency to EMF or change contents...).
>>>>
>>>> So my client application must roughly manage the following actions :
>>>> - load persistent objects through webServices, then load them in the
>>>> local EMF model.
>>>> - work transparently with the EMF model
>>>> - save the EMF model modifications into the persistent model, and send
>>>> the updated persistent objects to the server to update the database
>>>>
>>>> But many problems arise, that's why I'm asking the specialists ;-)
>>>>
>>>> - How can I map the EMF model with the persistence model ?
>>>>
>>>> - How to load objects from the persistent model in the EMF model ?
>>>> For instance, if my models (both the server persistence model and
>>>> the local EMF model) contain a class A, with a 1..1 reference to
>>>> another class B :
>>>> ### Persistent Model :
>>>> public interface PersistentA {
>>>> long getId();
>>>> void setId(long id);
>>>> PersistentB getB();
>>>> void setB(PersistentB b);
>>>> }
>>>> public interface PersistentB {
>>>> long getId();
>>>> void setId(long id);
>>>> }
>>>> ### EMF Model :
>>>> public interface A {
>>>> long getId();
>>>> void setId(long id);
>>>> B getB();
>>>> void setB(B b);
>>>> }
>>>> public interface B {
>>>> long getId();
>>>> void setId(long id);
>>>> }
>>>>
>>>> I can ask the server for a specific instance of persistent class A
>>>> through web services. Then, I may manage to create the corresponding
>>>> instance of EMF class A, for example :
>>>>
>>>> public A createA(PersistantA pa) {
>>>> A a = AFactory.eINSTANCE.createA();
>>>> a.setId(pa.getId());
>>>> a.setB(createB(pa.getB()));
>>>> }
>>>>
>>>> public B createB(PersistantB pb) {
>>>> ...
>>>> }
>>>>
>>>> But if I use this kind of implementation, when loading any object in
>>>> the model, I will recursively load every dependencies to other
>>>> objects, and I will end up with "all" the database loaded on the
>>>> client side...
>>>> A solution would be something like :
>>>>
>>>> public A createA(PersistantA pa) {
>>>> A a = AFactory.eINSTANCE.createA();
>>>> a.setId(pa.getId());
>>>> a.setB(createBProxy(pa, ...));
>>>> }
>>>>
>>>> I won't continue with other implementations details, but I hope you
>>>> will understand the problems and that you'll be able to give me some
>>>> pointers on how to achieve all this...
>>>>
>>>>
>>>> Thanks a lot in advance !
>>>> Stephane
>>>
>>>
>
>
Re: Persisting an EMF model in a non-EMF persistance model [message #421146 is a reply to message #421144] Mon, 28 July 2008 15:37 Go to previous messageGo to next message
Martin Taal is currently offline Martin TaalFriend
Messages: 5468
Registered: July 2009
Senior Member
Hi Stephane,
Afaics your approach is fine. I am not sure what you get from the webservice call is that xml or is
instances of the PersistenceObject? If it is xml then you can write a transformation from the
webservice xml to emf xml which also handles proxies (you need to check how EMF stores proxy
information in xml).

If you get PersistenceObjects then you can maybe write a more generic java transformation by using
the EClass and EFeatures of the model. It depends if there is an easy match to make from the
classname of the PersistenceObject and the membernames of the PersistenceObject to the
eclass/efeature names of the EMF model.

Maybe one of the core EMF developers can add some more information about creating proxies.

gr. Martin

SWT wrote:
> Martin,
>
> I have some more questions about EMF proxies :
> When I implement the getEObject(String uriFragment) method, I can get
> the persistent object via webservices, and I can create a new
> corresponding model object.
> In this case, all references of the new model object are null.
> But I need them to be proxies, not null values !
> Here is an example implementation :
> public EObject getEObject(String uriFragment) {
> if (/*...uriFragment...*/) {
> // TODO specific cases...
> } else {
> return getNewEObject(uriFragment);
> }
> // ...
> }
> public EObject getNewEObject(uriFragment) {
> // Retrieve the corresponding object in database
> PersistentObject po = getByURI(uriFragment);
> // Convert it to client model object
> EObject modelObject = createFromPersistent(po);
> return modelObject;
> }
> public EObject createFromPersistent(PersistentObject po) {
> // It's an example, so let's keep it simple :
> MyModelObject result =
> MyFactory.eINSTANCE.createMyModelObject();
> result.setAttr1(po.getAttr1());
> result.setAttr2(po.getAttr2());
> // etc. for all attributes
> // Now the references :
> result.setReferenceToOther(?????);
> }
> In this example, I don't know what to use for "?????".
> My idea would be to create a new proxy instance of the referenced object
> as follows :
>
> OtherModelObject proxyToOther =
> MyFactory.eINSTANCE.createOtherModelObject();
> ((BasicEObjectImpl) proxyToOther).eSetProxyURI(URI.createURI(getURI()
> + "/"
> + getURIFragment(po)
> + "/"
> + MyPackage.MyModelObject__OtherModelObject ));
> result.setReferenceToOther(proxyToOther);
>
> But it seems that if I continue this way, I will re-implement a lot of
> the proxying mechanism... I don't even know if the cast
> "(BasicEObjectImpl) proxyToOther" is legal / safe, and if it's the good
> way for creating proxies...
> Maybe I'm missing something ? Maybe there's a facility to handle proxies...
>
> Thank you a lot in advance !
>
> Stephane
>
>
> Martin Taal wrote :
>> Hi Stephane,
>> There is a difference between EMF and hibernate proxies which you
>> should know although I am not sure if it makes a difference for you.
>> The main difference between EMF and Hibernate proxies is that with
>> Hibernate the object itself is de-proxied while with EMF the reference
>> is de-proxied. Here is an example of how de-proxying is done for the
>> Book referencing an EMF-proxied Writer (from the EMF library example):
>> public Writer getAuthor() {
>> if (author != null && ((EObject)author).eIsProxy()) {
>> InternalEObject oldAuthor = (InternalEObject)author;
>> author = (Writer)eResolveProxy(oldAuthor);
>> if (author != oldAuthor) {
>> if (eNotificationRequired())
>> eNotify(new ENotificationImpl(this,
>> Notification.RESOLVE, LibraryPackage.BOOK__AUTHOR, oldAuthor, author));
>> }
>> }
>> return author;
>> }
>>
>> What you can see is that the eResolveProxy replaces the Writer
>> instance in the author member. This is different than the hibernate
>> proxy approach which would would not replace the Writer (==the cglib
>> wrapped object) but would instead initialize the Writer/cglib object
>> with the real object from the webservice.
>>
>> The advantage of EMF over the hibernate proxy approach is that with
>> EMF you don't need to do the proxying of each object yourselve, and
>> you don't need cglib.
>>
>> To explain a bit more what happens. The eResolveProxy method is
>> implemented in the base class BasicEObjectImpl, this eventually does
>> this call: return EcoreUtil.resolve(proxy, this);
>> The EcoreUtil.resolveProxy gets the Resource from the EObject and from
>> the Resource it gets the ResourceSet, and then this call is done:
>> resourceSet.getEObject(proxyURI, true)
>> which is implemented like this:
>> public EObject getEObject(URI uri, boolean loadOnDemand)
>> {
>> Resource resource = getResource(uri.trimFragment(), loadOnDemand);
>> if (resource != null)
>> {
>> return resource.getEObject(uri.fragment());
>> }
>> else
>> {
>> return null;
>> }
>> }
>>
>> To get this working you should create your own ResourceImpl (which can
>> replace your Session concept). This resource only needs to implement
>> the getEObject(String uriFragment) method which calls the webservice
>> to get the object. The uriFragment should map to something which you
>> can use in the webservice.
>>
>> At runtime you create your resource through a ResourceSet (do new
>> ResourceSetImpl() to get one). Now the thing to watch here is that the
>> url you use to create your resource with should match the url used in
>> the proxies. Otherwise the resourceset can't find your resource again.
>> For example:
>> resource ur: mgr://my.great.resource
>> proxy uri: mgr://my.great.resource#object_identifier
>>
>> Where object_identifier is passed to the getEObject(String
>> uriFragment) in your resource.
>>
>> Note the protocol mgr, you can tell EMF which resource to create based
>> on the protocol:
>> Resource.Factory.Registry.INSTANCE.getProtocolToFactoryMap() .put( "mgr",
>> new MyGreatResourceFactory());
>> MyGreatResourceFactory implements Resource.Factory which has one
>> method createResource(uri).
>> (I am not sure if this is currently the preferred way of doing this,
>> but it works for me...)
>>
>> To make live simpler at first you can also just override
>> ResourceSetImpl with your own implementation which always calls your
>> one Resource to get the EObject. Then if this works fine move back to
>> the standard EMF way (as this allows more flexibility and is more
>> standard).
>>
>> gr. Martin
>>
>> SWT wrote:
>>> Hi Martin,
>>>
>>> Model-to-model transformation is exactly what I need.
>>> I knew about ATL, but OAW seems even better. I'll definitely have a
>>> look at these solutions. Thank you.
>>>
>>> Regarding the proxies, I tried to "copy" Hibernate's mechanism :
>>> I have a global object (equivalent of Hibernate's session) where I
>>> can attach or detach objects found via web services.
>>> To attach an object, I load a persistent object through webservices,
>>> then transform it into local model objects (via mapping). These
>>> resulting objects are attached to the session (reference counted).
>>> Then for each EReference in the newly created local model objects, I
>>> create a proxy. Whenever a method is called on one of these proxy
>>> objects, I load the real referenced object via webservices, and I
>>> replace the proxy by the loaded object (and I count the reference to
>>> the object in the session).
>>>
>>> Should I rework this mechanism using EMF Resources ?
>>> I'm not used to Resources (and ResourceSet...) but I think this may
>>> be better : if I understand well, I should use my own ResourceImpl
>>> instead of the "session" object I was talking about...
>>> Are there any documentation on EMF proxies / Resources ?
>>> I think I can find by myself, but with an example or something, it's
>>> often faster :-)
>>>
>>> Thank you Martin !
>>> Stephane
>>>
>>> Martin Taal wrote :
>>>> Hi Stephane,
>>>> As you say this is not something for which you can use Teneo.
>>>>
>>>> What you need is some kind of model-to-model transformation. I would
>>>> transform the xml from the webservice to xml which can be read by
>>>> EMF. Afaik this is more or less a manual task but others know more
>>>> about this then I do (for example: http://www.eclipse.org/m2m/ but
>>>> if your situation is simpler you can use any other templating
>>>> language, free-marker, xslt, straight java, also of interest is
>>>> probably what the open architectureware people are doing:
>>>> www.openarchitectureware.org).
>>>> Regarding the proxying issue you mention. EMF has a nice proxying
>>>> mechanism which you can use. What you need to add is that you for
>>>> EMF proxy resolving use the webservice. What I would do is use your
>>>> own resource implementation (extending XMLResourceImpl), load the
>>>> converted xml from the webservice into this resource and override
>>>> the getEObject or getEObjectByID methods to use the webservice for
>>>> proxy resolving.
>>>>
>>>> gr. Martin
>>>>
>>>> SWT wrote:
>>>>> Hello all,
>>>>>
>>>>> I'm looking for a way to persist my EMF model using Hibernate, but I
>>>>> think I cannot use Teneo in my case :
>>>>> I have a "generic" database, that is to say, a DB that is designed to
>>>>> work with multiple client applications.
>>>>> Access to this DB is handled by a server java application which uses
>>>>> Hibernate.
>>>>> Client applications have access to the persistent model classes, and
>>>>> they can send requests to the server via WebServices.
>>>>> For instance, a client application can ask for model objects, modify
>>>>> them, then send back the modifications to the server...
>>>>>
>>>>> Now, I have to develop a new client application which will have
>>>>> it's own
>>>>> EMF model. This EMF model is not the same as the persistence model
>>>>> of the server application (so I will need to map the model objects
>>>>> of the two models).
>>>>> I can add new server WebServices, but I cannot change the server
>>>>> model contents (I can add annotations or such things, but I cannot
>>>>> add a dependency to EMF or change contents...).
>>>>>
>>>>> So my client application must roughly manage the following actions :
>>>>> - load persistent objects through webServices, then load them in the
>>>>> local EMF model.
>>>>> - work transparently with the EMF model
>>>>> - save the EMF model modifications into the persistent model, and send
>>>>> the updated persistent objects to the server to update the database
>>>>>
>>>>> But many problems arise, that's why I'm asking the specialists ;-)
>>>>>
>>>>> - How can I map the EMF model with the persistence model ?
>>>>>
>>>>> - How to load objects from the persistent model in the EMF model ?
>>>>> For instance, if my models (both the server persistence model and
>>>>> the local EMF model) contain a class A, with a 1..1 reference to
>>>>> another class B :
>>>>> ### Persistent Model :
>>>>> public interface PersistentA {
>>>>> long getId();
>>>>> void setId(long id);
>>>>> PersistentB getB();
>>>>> void setB(PersistentB b);
>>>>> }
>>>>> public interface PersistentB {
>>>>> long getId();
>>>>> void setId(long id);
>>>>> }
>>>>> ### EMF Model :
>>>>> public interface A {
>>>>> long getId();
>>>>> void setId(long id);
>>>>> B getB();
>>>>> void setB(B b);
>>>>> }
>>>>> public interface B {
>>>>> long getId();
>>>>> void setId(long id);
>>>>> }
>>>>>
>>>>> I can ask the server for a specific instance of persistent class A
>>>>> through web services. Then, I may manage to create the
>>>>> corresponding instance of EMF class A, for example :
>>>>>
>>>>> public A createA(PersistantA pa) {
>>>>> A a = AFactory.eINSTANCE.createA();
>>>>> a.setId(pa.getId());
>>>>> a.setB(createB(pa.getB()));
>>>>> }
>>>>>
>>>>> public B createB(PersistantB pb) {
>>>>> ...
>>>>> }
>>>>>
>>>>> But if I use this kind of implementation, when loading any object
>>>>> in the model, I will recursively load every dependencies to other
>>>>> objects, and I will end up with "all" the database loaded on the
>>>>> client side...
>>>>> A solution would be something like :
>>>>>
>>>>> public A createA(PersistantA pa) {
>>>>> A a = AFactory.eINSTANCE.createA();
>>>>> a.setId(pa.getId());
>>>>> a.setB(createBProxy(pa, ...));
>>>>> }
>>>>>
>>>>> I won't continue with other implementations details, but I hope you
>>>>> will understand the problems and that you'll be able to give me
>>>>> some pointers on how to achieve all this...
>>>>>
>>>>>
>>>>> Thanks a lot in advance !
>>>>> Stephane
>>>>
>>>>
>>
>>


--

With Regards, Martin Taal

Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Cell: +31 (0)6 288 48 943
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
Re: Persisting an EMF model in a non-EMF persistance model [message #421150 is a reply to message #421146] Mon, 28 July 2008 16:22 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: swt.magellium.fr

Martin,

The webservices can provide xml, but it'll be a xml generated with JAXB
(to be confirmed with the server-side developers), not an XMI conforming
to an Ecore model (that's why I think the XML approach would be
difficult). Webservices can also directly provide "PersistentObjects"
through the XFire library.
Anyway, if I want to try "webservice xml to EMF xml transform". Could
you please give me some starting point (url or so...) ?

The match between "PersistentObjects" and the EMF model is generally
easy (mainly 1..1 relationships) but there are some special cases which
can hopefully be managed "by hand" (that is to say, I think I'll be able
to first use an hard-coded transform before using ATL/oAW in order to be
generic...)

So, using this approach, I just need to know how to properly create EMF
proxies... I'll search some more today, and maybe create an new
discussion focusing on EMF proxy creation tomorrow...

Thank you again !
Stephane

Martin Taal wrote :
> Hi Stephane,
> Afaics your approach is fine. I am not sure what you get from the
> webservice call is that xml or is instances of the PersistenceObject? If
> it is xml then you can write a transformation from the webservice xml to
> emf xml which also handles proxies (you need to check how EMF stores
> proxy information in xml).
>
> If you get PersistenceObjects then you can maybe write a more generic
> java transformation by using the EClass and EFeatures of the model. It
> depends if there is an easy match to make from the classname of the
> PersistenceObject and the membernames of the PersistenceObject to the
> eclass/efeature names of the EMF model.
>
> Maybe one of the core EMF developers can add some more information about
> creating proxies.
>
> gr. Martin
>
> SWT wrote:
>> Martin,
>>
>> I have some more questions about EMF proxies :
>> When I implement the getEObject(String uriFragment) method, I can get
>> the persistent object via webservices, and I can create a new
>> corresponding model object.
>> In this case, all references of the new model object are null.
>> But I need them to be proxies, not null values !
>> Here is an example implementation :
>> public EObject getEObject(String uriFragment) {
>> if (/*...uriFragment...*/) {
>> // TODO specific cases...
>> } else {
>> return getNewEObject(uriFragment);
>> }
>> // ...
>> }
>> public EObject getNewEObject(uriFragment) {
>> // Retrieve the corresponding object in database
>> PersistentObject po = getByURI(uriFragment);
>> // Convert it to client model object
>> EObject modelObject = createFromPersistent(po);
>> return modelObject;
>> }
>> public EObject createFromPersistent(PersistentObject po) {
>> // It's an example, so let's keep it simple :
>> MyModelObject result =
>> MyFactory.eINSTANCE.createMyModelObject();
>> result.setAttr1(po.getAttr1());
>> result.setAttr2(po.getAttr2());
>> // etc. for all attributes
>> // Now the references :
>> result.setReferenceToOther(?????);
>> }
>> In this example, I don't know what to use for "?????".
>> My idea would be to create a new proxy instance of the referenced
>> object as follows :
>>
>> OtherModelObject proxyToOther =
>> MyFactory.eINSTANCE.createOtherModelObject();
>> ((BasicEObjectImpl) proxyToOther).eSetProxyURI(URI.createURI(getURI()
>> + "/"
>> + getURIFragment(po)
>> + "/"
>> + MyPackage.MyModelObject__OtherModelObject ));
>> result.setReferenceToOther(proxyToOther);
>>
>> But it seems that if I continue this way, I will re-implement a lot of
>> the proxying mechanism... I don't even know if the cast
>> "(BasicEObjectImpl) proxyToOther" is legal / safe, and if it's the
>> good way for creating proxies...
>> Maybe I'm missing something ? Maybe there's a facility to handle
>> proxies...
>>
>> Thank you a lot in advance !
>>
>> Stephane
>>
>>
>> Martin Taal wrote :
>>> Hi Stephane,
>>> There is a difference between EMF and hibernate proxies which you
>>> should know although I am not sure if it makes a difference for you.
>>> The main difference between EMF and Hibernate proxies is that with
>>> Hibernate the object itself is de-proxied while with EMF the
>>> reference is de-proxied. Here is an example of how de-proxying is
>>> done for the Book referencing an EMF-proxied Writer (from the EMF
>>> library example):
>>> public Writer getAuthor() {
>>> if (author != null && ((EObject)author).eIsProxy()) {
>>> InternalEObject oldAuthor = (InternalEObject)author;
>>> author = (Writer)eResolveProxy(oldAuthor);
>>> if (author != oldAuthor) {
>>> if (eNotificationRequired())
>>> eNotify(new ENotificationImpl(this,
>>> Notification.RESOLVE, LibraryPackage.BOOK__AUTHOR, oldAuthor, author));
>>> }
>>> }
>>> return author;
>>> }
>>>
>>> What you can see is that the eResolveProxy replaces the Writer
>>> instance in the author member. This is different than the hibernate
>>> proxy approach which would would not replace the Writer (==the cglib
>>> wrapped object) but would instead initialize the Writer/cglib object
>>> with the real object from the webservice.
>>>
>>> The advantage of EMF over the hibernate proxy approach is that with
>>> EMF you don't need to do the proxying of each object yourselve, and
>>> you don't need cglib.
>>>
>>> To explain a bit more what happens. The eResolveProxy method is
>>> implemented in the base class BasicEObjectImpl, this eventually does
>>> this call: return EcoreUtil.resolve(proxy, this);
>>> The EcoreUtil.resolveProxy gets the Resource from the EObject and
>>> from the Resource it gets the ResourceSet, and then this call is
>>> done: resourceSet.getEObject(proxyURI, true)
>>> which is implemented like this:
>>> public EObject getEObject(URI uri, boolean loadOnDemand)
>>> {
>>> Resource resource = getResource(uri.trimFragment(), loadOnDemand);
>>> if (resource != null)
>>> {
>>> return resource.getEObject(uri.fragment());
>>> }
>>> else
>>> {
>>> return null;
>>> }
>>> }
>>>
>>> To get this working you should create your own ResourceImpl (which
>>> can replace your Session concept). This resource only needs to
>>> implement the getEObject(String uriFragment) method which calls the
>>> webservice to get the object. The uriFragment should map to something
>>> which you can use in the webservice.
>>>
>>> At runtime you create your resource through a ResourceSet (do new
>>> ResourceSetImpl() to get one). Now the thing to watch here is that
>>> the url you use to create your resource with should match the url
>>> used in the proxies. Otherwise the resourceset can't find your
>>> resource again. For example:
>>> resource ur: mgr://my.great.resource
>>> proxy uri: mgr://my.great.resource#object_identifier
>>>
>>> Where object_identifier is passed to the getEObject(String
>>> uriFragment) in your resource.
>>>
>>> Note the protocol mgr, you can tell EMF which resource to create
>>> based on the protocol:
>>> Resource.Factory.Registry.INSTANCE.getProtocolToFactoryMap() .put( "mgr",
>>> new MyGreatResourceFactory());
>>> MyGreatResourceFactory implements Resource.Factory which has one
>>> method createResource(uri).
>>> (I am not sure if this is currently the preferred way of doing this,
>>> but it works for me...)
>>>
>>> To make live simpler at first you can also just override
>>> ResourceSetImpl with your own implementation which always calls your
>>> one Resource to get the EObject. Then if this works fine move back to
>>> the standard EMF way (as this allows more flexibility and is more
>>> standard).
>>>
>>> gr. Martin
>>>
>>> SWT wrote:
>>>> Hi Martin,
>>>>
>>>> Model-to-model transformation is exactly what I need.
>>>> I knew about ATL, but OAW seems even better. I'll definitely have a
>>>> look at these solutions. Thank you.
>>>>
>>>> Regarding the proxies, I tried to "copy" Hibernate's mechanism :
>>>> I have a global object (equivalent of Hibernate's session) where I
>>>> can attach or detach objects found via web services.
>>>> To attach an object, I load a persistent object through webservices,
>>>> then transform it into local model objects (via mapping). These
>>>> resulting objects are attached to the session (reference counted).
>>>> Then for each EReference in the newly created local model objects, I
>>>> create a proxy. Whenever a method is called on one of these proxy
>>>> objects, I load the real referenced object via webservices, and I
>>>> replace the proxy by the loaded object (and I count the reference to
>>>> the object in the session).
>>>>
>>>> Should I rework this mechanism using EMF Resources ?
>>>> I'm not used to Resources (and ResourceSet...) but I think this may
>>>> be better : if I understand well, I should use my own ResourceImpl
>>>> instead of the "session" object I was talking about...
>>>> Are there any documentation on EMF proxies / Resources ?
>>>> I think I can find by myself, but with an example or something, it's
>>>> often faster :-)
>>>>
>>>> Thank you Martin !
>>>> Stephane
>>>>
>>>> Martin Taal wrote :
>>>>> Hi Stephane,
>>>>> As you say this is not something for which you can use Teneo.
>>>>>
>>>>> What you need is some kind of model-to-model transformation. I
>>>>> would transform the xml from the webservice to xml which can be
>>>>> read by EMF. Afaik this is more or less a manual task but others
>>>>> know more about this then I do (for example:
>>>>> http://www.eclipse.org/m2m/ but if your situation is simpler you
>>>>> can use any other templating language, free-marker, xslt, straight
>>>>> java, also of interest is probably what the open architectureware
>>>>> people are doing: www.openarchitectureware.org).
>>>>> Regarding the proxying issue you mention. EMF has a nice proxying
>>>>> mechanism which you can use. What you need to add is that you for
>>>>> EMF proxy resolving use the webservice. What I would do is use your
>>>>> own resource implementation (extending XMLResourceImpl), load the
>>>>> converted xml from the webservice into this resource and override
>>>>> the getEObject or getEObjectByID methods to use the webservice for
>>>>> proxy resolving.
>>>>>
>>>>> gr. Martin
>>>>>
>>>>> SWT wrote:
>>>>>> Hello all,
>>>>>>
>>>>>> I'm looking for a way to persist my EMF model using Hibernate, but I
>>>>>> think I cannot use Teneo in my case :
>>>>>> I have a "generic" database, that is to say, a DB that is designed to
>>>>>> work with multiple client applications.
>>>>>> Access to this DB is handled by a server java application which uses
>>>>>> Hibernate.
>>>>>> Client applications have access to the persistent model classes, and
>>>>>> they can send requests to the server via WebServices.
>>>>>> For instance, a client application can ask for model objects, modify
>>>>>> them, then send back the modifications to the server...
>>>>>>
>>>>>> Now, I have to develop a new client application which will have
>>>>>> it's own
>>>>>> EMF model. This EMF model is not the same as the persistence model
>>>>>> of the server application (so I will need to map the model objects
>>>>>> of the two models).
>>>>>> I can add new server WebServices, but I cannot change the server
>>>>>> model contents (I can add annotations or such things, but I cannot
>>>>>> add a dependency to EMF or change contents...).
>>>>>>
>>>>>> So my client application must roughly manage the following actions :
>>>>>> - load persistent objects through webServices, then load them in the
>>>>>> local EMF model.
>>>>>> - work transparently with the EMF model
>>>>>> - save the EMF model modifications into the persistent model, and
>>>>>> send
>>>>>> the updated persistent objects to the server to update the database
>>>>>>
>>>>>> But many problems arise, that's why I'm asking the specialists ;-)
>>>>>>
>>>>>> - How can I map the EMF model with the persistence model ?
>>>>>>
>>>>>> - How to load objects from the persistent model in the EMF model ?
>>>>>> For instance, if my models (both the server persistence model and
>>>>>> the local EMF model) contain a class A, with a 1..1 reference to
>>>>>> another class B :
>>>>>> ### Persistent Model :
>>>>>> public interface PersistentA {
>>>>>> long getId();
>>>>>> void setId(long id);
>>>>>> PersistentB getB();
>>>>>> void setB(PersistentB b);
>>>>>> }
>>>>>> public interface PersistentB {
>>>>>> long getId();
>>>>>> void setId(long id);
>>>>>> }
>>>>>> ### EMF Model :
>>>>>> public interface A {
>>>>>> long getId();
>>>>>> void setId(long id);
>>>>>> B getB();
>>>>>> void setB(B b);
>>>>>> }
>>>>>> public interface B {
>>>>>> long getId();
>>>>>> void setId(long id);
>>>>>> }
>>>>>>
>>>>>> I can ask the server for a specific instance of persistent class A
>>>>>> through web services. Then, I may manage to create the
>>>>>> corresponding instance of EMF class A, for example :
>>>>>>
>>>>>> public A createA(PersistantA pa) {
>>>>>> A a = AFactory.eINSTANCE.createA();
>>>>>> a.setId(pa.getId());
>>>>>> a.setB(createB(pa.getB()));
>>>>>> }
>>>>>>
>>>>>> public B createB(PersistantB pb) {
>>>>>> ...
>>>>>> }
>>>>>>
>>>>>> But if I use this kind of implementation, when loading any object
>>>>>> in the model, I will recursively load every dependencies to other
>>>>>> objects, and I will end up with "all" the database loaded on the
>>>>>> client side...
>>>>>> A solution would be something like :
>>>>>>
>>>>>> public A createA(PersistantA pa) {
>>>>>> A a = AFactory.eINSTANCE.createA();
>>>>>> a.setId(pa.getId());
>>>>>> a.setB(createBProxy(pa, ...));
>>>>>> }
>>>>>>
>>>>>> I won't continue with other implementations details, but I hope
>>>>>> you will understand the problems and that you'll be able to give
>>>>>> me some pointers on how to achieve all this...
>>>>>>
>>>>>>
>>>>>> Thanks a lot in advance !
>>>>>> Stephane
>>>>>
>>>>>
>>>
>>>
>
>
Re: Persisting an EMF model in a non-EMF persistance model [message #421162 is a reply to message #421150] Tue, 29 July 2008 15:23 Go to previous message
David Steinberg is currently offline David SteinbergFriend
Messages: 489
Registered: July 2009
Senior Member
SWT wrote:
>
> So, using this approach, I just need to know how to properly create EMF
> proxies... I'll search some more today, and maybe create an new
> discussion focusing on EMF proxy creation tomorrow...

Hi Stephane,

I must admit I'm not following everything that's been said, but I can
still try to offer some help...

When you "load objects" from the web service, any objects that aren't
retrieved should be represented by proxies. A proxy is just an instance
of the expected type with its proxy URI set (cast it to InternalEObject
and call eSetProxyURI()) to something that will allow the real object to
be loaded by a resource implementation.

I'm not sure if I'm telling you things you already know. I hope that
helps address your question.

Cheers,
Dave
Previous Topic:Storing EClass in a Hashmap, loading package from a file vs. from memory
Next Topic:Annotation and generate additional things
Goto Forum:
  


Current Time: Fri Mar 29 10:55:19 GMT 2024

Powered by FUDForum. Page generated in 0.03919 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top