Home » Modeling » EMF » Problems reading instances serialized with an old package
| Problems reading instances serialized with an old package [message #423995] |
Mon, 13 October 2008 17:05  |
Ben Messages: 46 Registered: July 2009 |
Member |
|
|
Though the reading does throw an exception, should not the objects in the
resource still be populated with the information?
File file = new File(args[i]);
URI uri = file.isFile() ? URI.createFileURI(file.getAbsolutePath()):
URI.createURI(args[0]);
Resource resource = null;
try {
resource = resourceSet.getResource(uri, true);
} catch (RuntimeException exception) {
exception.printStackTrace();
// An error occurred:
// org.eclipse.emf.ecore.resource.Resource$IOWrappedException: Package
with
// uri 'http://www.acme.com/XYZ3.2' not found.
for (EObject eObject : resource.getContents()) {
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eObject);
if (diagnostic.getSeverity() != Diagnostic.OK) {
printDiagnostic(diagnostic, "");
}
}
}
|
|
| | | | | |
| Re: Problems reading instances serialized with an old package [message #424081 is a reply to message #424079] |
Wed, 15 October 2008 19:55   |
Ed Merks Messages: 25227 Registered: July 2009 |
Senior Member |
|
|
Ben,
Once the resource load has failed, it won't try again until you call
resource.unload...
Ben wrote:
> Thanks Mario, it works now, but only if I register the old uri before
> I call getResource() the first time.
> So, why EMF does not allow me to register the uri/package after the
> exception has been thrown as shown below?
>
> try {
> resource = resourceSet.getResource(uri, true);
> } catch (RuntimeException rte) {
> Throwable throwable = rte.getCause();
> if (throwable instanceof PackageNotFoundException) {
> EPackage.Registry.INSTANCE.put(((PackageNotFoundException)
> throwable).uri(), XYZPackage.eINSTANCE);
> resource = resourceSet.getResource(uri, false);
>
> // In this case, contents is still empty!?!?!
> //
> EList<EObject> contents = resource.getContents();
> }
> }
>
|
|
| | |
| Re: Problems reading instances serialized with an old package [message #424103 is a reply to message #424079] |
Thu, 16 October 2008 10:41   |
Mario Winterer Messages: 136 Registered: July 2009 |
Senior Member |
|
|
I can see no advantage in trying to load the model twice.
If you don't want to mess your global package registry with "model
compatibility entries", you could use the ResourceSet's local registry:
resourceSet.getPackageRegistry().put(oldURI, XYZPackage.eINSTANCE);
In this case, EMF will automatically choose the XYZPackage on the first try.
Ben schrieb:
> Thanks Mario, it works now, but only if I register the old uri before I
> call getResource() the first time.
> So, why EMF does not allow me to register the uri/package after the
> exception has been thrown as shown below?
>
> try {
> resource = resourceSet.getResource(uri, true);
> } catch (RuntimeException rte) {
> Throwable throwable = rte.getCause();
> if (throwable instanceof PackageNotFoundException) {
> EPackage.Registry.INSTANCE.put(((PackageNotFoundException)
> throwable).uri(), XYZPackage.eINSTANCE);
> resource = resourceSet.getResource(uri, false);
>
> // In this case, contents is still empty!?!?!
> //
> EList<EObject> contents = resource.getContents();
> }
> }
>
|
|
| |
| Re: Problems reading instances serialized with an old package [message #424111 is a reply to message #424105] |
Thu, 16 October 2008 12:46   |
Ed Merks Messages: 25227 Registered: July 2009 |
Senior Member |
|
|
Ben,
Comments below.
Ben wrote:
> Hi Ed,
>
> Here is the stack trace and how it occurs. Thanks!
>
>
>
> ResourceSet resourceSet = new ResourceSetImpl();
> resourceSet.getResourceFactoryRegistry().getExtensionToFacto ryMap().put
> (Resource.Factory.Registry.DEFAULT_EXTENSION,
> new MyAcmeResourceFactoryImpl());
>
> // register the old uri (without this resource.getContents() comes
> back empty)
> //
> EPackage.Registry.INSTANCE.put('http://www.acme.com/XYZ3.2',
> MyAcmePackage.eInstance);
>
>
> try {
> resource = resourceSet.getResource(uri, true);
> ...
> ....
> }catch (RuntimeException e) {
>
> exception.printStackTrace();
>
> /*
> org.eclipse.emf.ecore.resource.impl.ResourceSetImpl$1Diagnos ticWrappedException:
> org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'Plan' not
> found. (file:/users/ben/plans.rml, 2, 114)
> at
> org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.handleDe mandLoadException(ResourceSetImpl.java:315)
>
> at
> org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLo adHelper(ResourceSetImpl.java:274)
>
> */
So it's not finding the root element? There's no magic here. If
there's no way to figure out what root object should be created, it's
not going to be able to do it. I.e., it will load as much as possible,
and no more...
>
> resource = resourceSet.getResource(uri, false);
> EList<EObject> contents = resource.getContents();
> DocumentRoot root = (DocumentRoot) contents.get(0);
> Assert.assertNotNull("Plan is null", root.getPlan());
> }
>
|
|
|
| Re: Problems reading instances serialized with an old package [message #424151 is a reply to message #424111] |
Fri, 17 October 2008 11:48   |
Ben Messages: 46 Registered: July 2009 |
Member |
|
|
Ed,
I think that the unexpected result I am getting is caused by the
DocumentRoot in my model. For instance, the combination of
resourceSet.getPackageRegistry().put(old_eNS_URI,
LibraryPackage.eINSTANCE) -> getResource(uri, true) -> exception ->
getResource(uri, false) -> "resource loads OK", works fine with the
original library.xsd schema since it does generate a DocumentRoot. So,
even the when the xmlns value changes, the resource is always loaded (all
objects are populated) when getResource(uri, false) is invoked.
Now, I modified the original library.xsd so it generates a DocumentRoot
(see it at the bottom) like my model. However, when I try to get the
resource, I get the following exception:
org.eclipse.emf.ecore.resource.impl.ResourceSetImpl$1Diagnos ticWrappedException:
org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'PLAN' not
found. (file:/Users/ben/test.library, 2, 55)
at
org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.handleDe mandLoadException(ResourceSetImpl.java:315)
at
org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLo adHelper(ResourceSetImpl.java:274)
at
org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResou rce(ResourceSetImpl.java:397)
at
org.eclipse.example.library.presentation.LibraryEditor.creat eModel(LibraryEditor.java:855)
---
public void createModel() {
URI resourceURI = EditUIUtil.getURI(getEditorInput());
editingDomain.getResourceSet().getPackageRegistry().put("http://www.example.eclipse.org/Library2",
LibraryPackage.eINSTANCE);
Resource resource = null;
try {
resource = editingDomain.getResourceSet().getResource(resourceURI, true);
} catch (Exception e) {
e.printStackTrace();
resource = editingDomain.getResourceSet().getResource(resourceURI,
false);
EList<EObject> contents = resource.getContents();
DocumentRoot root = (DocumentRoot) contents.get(0);
Assert.assertNotNull("Plan is null", root.getPLAN());
}
}
---
These are the 2 persisted models, as you can see they are identical except
for the xmlns value.
<?xml version="1.0" encoding="UTF-8"?>
<PLAN xmlns="http://www.example.eclipse.org/Library2">
<Library>
<name>Baker</name>
<writers>
<name>Ed Merks</name>
<books>#//@pLAN/@library/@books.0</books>
</writers>
<books>
<title>EMF</title>
<pages>100</pages>
<author>#//@pLAN/@library/@writers.0</author>
</books>
</Library>
</PLAN>
<?xml version="1.0" encoding="UTF-8"?>
<PLAN xmlns="http://www.example.eclipse.org/Library">
<Library>
<name>Baker</name>
<writers>
<name>Ed Merks</name>
<books>#//@pLAN/@library/@books.0</books>
</writers>
<books>
<title>EMF</title>
<pages>100</pages>
<author>#//@pLAN/@library/@writers.0</author>
</books>
</Library>
</PLAN>
Here is the library schema I modified to generate an DocumentRoot so
please let me know if this a bug in EMF or if I am doing something wrong.
Thanks again!
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema targetNamespace="http://www.example.eclipse.org/Library"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
xmlns:lib="http://www.example.eclipse.org/Library"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="PLAN">
<xsd:complexType ecore:name="PLAN">
<xsd:sequence>
<xsd:element name="Library">
<xsd:complexType ecore:name="Library">
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
<xsd:element maxOccurs="unbounded"
minOccurs="0" name="writers" type="lib:Writer" />
<xsd:element maxOccurs="unbounded"
minOccurs="0" name="books" type="lib:Book" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="Version" type="xsd:string"
use="required"></xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="Book">
<xsd:sequence>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="pages" type="xsd:int"/>
<xsd:element name="category" type="lib:BookCategory"/>
<xsd:element name="author" type="xsd:anyURI"
ecore:reference="lib:Writer" ecore:opposite="books"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Writer">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element maxOccurs="unbounded" minOccurs="0" name="books"
type="xsd:anyURI" ecore:reference="lib:Book"
ecore:opposite="author"/>
</xsd:sequence>
</xsd:complexType>
<xsd:simpleType name="BookCategory">
<xsd:restriction base="xsd:NCName">
<xsd:enumeration value="Mystery"/>
<xsd:enumeration value="ScienceFiction"/>
<xsd:enumeration value="Biography"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
|
|
|
| Re: Problems reading instances serialized with an old package [message #424152 is a reply to message #424151] |
Fri, 17 October 2008 12:15   |
Ed Merks Messages: 25227 Registered: July 2009 |
Senior Member |
|
|
This is a multi-part message in MIME format.
--------------010807030308050008000007
Content-Type: text/plain; charset=ISO-8859-15; format=flowed
Content-Transfer-Encoding: 7bit
Ben,
The problem with the approach you're taking is that the document root's
features are qualified with the namespace of the containing package, so
even if you redirect the old nsURI to a different package, the features
of that package's document root will be qualified with the new nsURI.
Last time someone asked I suggested they override getLocalElement so
that the document root lookup finds the redirected element.
http://www.google.com/cse?cx=017941334893793413703%3Asqfrdtd 112s&q=getLocalElement+news.eclipse.tools.emf&sa=Sea rch
< http://www.google.com/cse?cx=017941334893793413703%3Asqfrdtd 112s&q=getLocalElement+news.eclipse.tools.emf&sa=Sea rch>
http://dev.eclipse.org/newslists/news.eclipse.tools.emf/msg3 5706.html
Ben wrote:
> Ed,
>
> I think that the unexpected result I am getting is caused by the
> DocumentRoot in my model. For instance, the combination of
> resourceSet.getPackageRegistry().put(old_eNS_URI,
> LibraryPackage.eINSTANCE) -> getResource(uri, true) -> exception ->
> getResource(uri, false) -> "resource loads OK", works fine with the
> original library.xsd schema since it does generate a DocumentRoot.
> So, even the when the xmlns value changes, the resource is always
> loaded (all objects are populated) when getResource(uri, false) is
> invoked.
>
>
> Now, I modified the original library.xsd so it generates a
> DocumentRoot (see it at the bottom) like my model. However, when I
> try to get the resource, I get the following exception:
>
>
> org.eclipse.emf.ecore.resource.impl.ResourceSetImpl$1Diagnos ticWrappedException:
> org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'PLAN' not
> found. (file:/Users/ben/test.library, 2, 55)
> at
> org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.handleDe mandLoadException(ResourceSetImpl.java:315)
>
> at
> org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.demandLo adHelper(ResourceSetImpl.java:274)
>
> at
> org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.getResou rce(ResourceSetImpl.java:397)
>
> at
> org.eclipse.example.library.presentation.LibraryEditor.creat eModel(LibraryEditor.java:855)
>
>
>
> ---
> public void createModel() {
> URI resourceURI = EditUIUtil.getURI(getEditorInput());
> editingDomain.getResourceSet().getPackageRegistry().put("http://www.example.eclipse.org/Library2",
> LibraryPackage.eINSTANCE);
> Resource resource = null;
> try {
> resource =
> editingDomain.getResourceSet().getResource(resourceURI, true);
> } catch (Exception e) {
> e.printStackTrace();
> resource =
> editingDomain.getResourceSet().getResource(resourceURI, false);
> EList<EObject> contents = resource.getContents();
> DocumentRoot root = (DocumentRoot) contents.get(0);
> Assert.assertNotNull("Plan is null", root.getPLAN());
> }
> }
> ---
>
>
> These are the 2 persisted models, as you can see they are identical
> except for the xmlns value.
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <PLAN xmlns="http://www.example.eclipse.org/Library2">
> <Library>
> <name>Baker</name>
> <writers>
> <name>Ed Merks</name>
> <books>#//@pLAN/@library/@books.0</books>
> </writers>
> <books>
> <title>EMF</title>
> <pages>100</pages>
> <author>#//@pLAN/@library/@writers.0</author>
> </books>
> </Library>
> </PLAN>
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <PLAN xmlns="http://www.example.eclipse.org/Library">
> <Library>
> <name>Baker</name>
> <writers>
> <name>Ed Merks</name>
> <books>#//@pLAN/@library/@books.0</books>
> </writers>
> <books>
> <title>EMF</title>
> <pages>100</pages>
> <author>#//@pLAN/@library/@writers.0</author>
> </books>
> </Library>
> </PLAN>
>
>
> Here is the library schema I modified to generate an DocumentRoot so
> please let me know if this a bug in EMF or if I am doing something
> wrong. Thanks again!
>
>
> <?xml version="1.0" encoding="UTF-8"?>
> <xsd:schema targetNamespace="http://www.example.eclipse.org/Library"
> xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore"
> xmlns:lib="http://www.example.eclipse.org/Library"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema">
> <xsd:element name="PLAN">
> <xsd:complexType ecore:name="PLAN">
> <xsd:sequence>
> <xsd:element name="Library">
> <xsd:complexType ecore:name="Library">
> <xsd:sequence>
> <xsd:element name="name" type="xsd:string" />
> <xsd:element maxOccurs="unbounded"
> minOccurs="0" name="writers"
> type="lib:Writer" />
> <xsd:element maxOccurs="unbounded"
> minOccurs="0" name="books"
> type="lib:Book" />
> </xsd:sequence>
> </xsd:complexType>
> </xsd:element>
> </xsd:sequence>
> <xsd:attribute name="Version" type="xsd:string"
> use="required"></xsd:attribute>
> </xsd:complexType>
> </xsd:element>
> <xsd:complexType name="Book">
> <xsd:sequence>
> <xsd:element name="title" type="xsd:string"/>
> <xsd:element name="pages" type="xsd:int"/>
> <xsd:element name="category" type="lib:BookCategory"/>
> <xsd:element name="author" type="xsd:anyURI"
> ecore:reference="lib:Writer" ecore:opposite="books"/>
> </xsd:sequence>
> </xsd:complexType>
> <xsd:complexType name="Writer">
> <xsd:sequence>
> <xsd:element name="name" type="xsd:string"/>
> <xsd:element maxOccurs="unbounded" minOccurs="0" name="books"
> type="xsd:anyURI" ecore:reference="lib:Book"
> ecore:opposite="author"/>
> </xsd:sequence>
> </xsd:complexType>
> <xsd:simpleType name="BookCategory">
> <xsd:restriction base="xsd:NCName">
> <xsd:enumeration value="Mystery"/>
> <xsd:enumeration value="ScienceFiction"/>
> <xsd:enumeration value="Biography"/>
> </xsd:restriction>
> </xsd:simpleType>
> </xsd:schema>
>
--------------010807030308050008000007
Content-Type: text/html; charset=ISO-8859-15
Content-Transfer-Encoding: 8bit
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-15"
http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Ben,<br>
<br>
The problem with the approach you're taking is that the document root's
features are qualified with the namespace of the containing package, so
even if you redirect the old nsURI to a different package, the features
of that package's document root will be qualified with the new nsURI.
|
|
|
| Re: Problems reading instances serialized with an old package [message #424157 is a reply to message #424152] |
Fri, 17 October 2008 14:20  |
Ben Messages: 46 Registered: July 2009 |
Member |
|
|
Thanks Ed. It works now.
Just for the records so others can use the same approach, here is the
suggested approach:
public class LibraryResourceFactoryImpl extends ResourceFactoryImpl {
protected ExtendedMetaData extendedMetaData;
/**
* Creates an instance of the resource factory.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
public LibraryResourceFactoryImpl() {
super();
extendedMetaData = new BasicExtendedMetaData(new
EPackageRegistryImpl(EPackage.Registry.INSTANCE)) {
@Override
protected EStructuralFeature getLocalElement(EClass eClass, String
namespace, String name) {
return super.getLocalElement(eClass, LibraryPackage.eNS_URI, name);
}
};
extendedMetaData.putPackage(null, LibraryPackage.eINSTANCE);
}
/**
* Creates an instance of the resource.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
@Override
public Resource createResource(URI uri) {
XMLResource result = new LibraryResourceImpl(uri);
result.getDefaultSaveOptions().put(XMLResource.OPTION_EXTEND ED_META_DATA,
Boolean.TRUE);
result.getDefaultLoadOptions().put(XMLResource.OPTION_EXTEND ED_META_DATA,
extendedMetaData);
result.getDefaultSaveOptions().put(XMLResource.OPTION_SCHEMA _LOCATION,
Boolean.TRUE);
result.getDefaultLoadOptions().put(XMLResource.OPTION_USE_EN CODED_ATTRIBUTE_STYLE,
Boolean.TRUE);
result.getDefaultSaveOptions().put(XMLResource.OPTION_USE_EN CODED_ATTRIBUTE_STYLE,
Boolean.TRUE);
result.getDefaultLoadOptions().put(XMLResource.OPTION_USE_LE XICAL_HANDLER,
Boolean.TRUE);
return result;
}
}
|
|
|
Goto Forum:
Current Time: Tue Oct 08 07:54:00 EDT 2013
Powered by FUDForum. Page generated in 0.02269 seconds
|