Eclipse Modeling Framework Examination and that mean Websphere Error.
The Eclipse Modeling Framework (EMF) is one of the least understood and most powerful frameworks ever handed down to us mortals by IBM. Often confused with providing UML modeling capability in Eclipse and the Rational toolset (that’s actually the UML2 Framework) EMF concerns models in the meta-data sense, and is, in essence, an abstraction engine for data and code. The fact that Service Data Objects (SDOs), one of the two frameworks of the holy SOA stack (SDO/SCA), is built on top of EMF points to it’s power.
Sadly, most of us often encounter EMF only as some tool failure where we get an .Ecore error or some other nasty issue, and we usually reverse tracks instead of digging in to the mysterious innards of Eclipse. It was in this scenario I discovered a problem with EMF and Websphere, and I’m certain from the message board posts it’s gonna get a whole lot worse before it gets better. Luckily, there is a simple way around it.
The EMF Error
If you do any deployment on Websphere 5.x and higher, particularly it seems now that version 7 of the IBM Rational Platform is out, and use EMF either in SDOs or other parsing technologies, you’re going to run in to this error:
java.lang.IllegalArgumentException: resolve against non-hierarchical or relative base
at org.eclipse.emf.common.util.URI.resolve(URI.java:1853)
This is all the information you get, and it can be maddening. I was forced to face this error recently when trying to load in a xsd file in to an SDO from a relative URL. You can duplicate this problem by running the code below:
public class Test1 {
private static final String PO_MODEL = "po.xsd";
private static final String PO_XML = "po.xml";
private static void definePOTypes() throws Exception {
FileInputStream fis = new FileInputStream(PO_MODEL);
XSDHelper.INSTANCE.define(fis, null); // In Websphere container this will fail
fis.close();
}
}
public static void main(String[] args) throws Exception {
definePOTypes();
FileInputStream fis = new FileOutputStream(PO_XML);
XMLDocumentImpl xmlDoc = XMLHelper.INSTANCE.load(fis);
DataObject purchaseOrder = xmlDoc.getRootObject();
Of particular interest is this line here:
XSDHelper.INSTANCE.define(fis, null); // In Websphere container this will fail
Explanation Of Error And How EMF Determines Runtime Hierarchies
This XSDHelper simply takes an XSD (either String or stream) and prepares the SDO. In essence, the XSD gets parsed so that the SDO can apply the XML or any other data it gets to the XSD for Type validation. This XSDHelper is just a wrapper around EMF, which takes the XSD and begins to fit it in to a meta-model that Java can deal with. What is interesting is what EMF does under the covers, and for this we need to know about the URI class in EMF, and in particular the resolve method.
Recall the class we got the error from:
at org.eclipse.emf.common.util.URI.resolve(URI.java:1853)
The URI class in EMF is simply a representation of a Uniform Resource Identifier (URI), as specified by RFC 2396, with certain enhancements. Like String, URI is an immutable class; a URI instance offers several by-value methods that return a new URI object based on its current state. Most useful, a relative URI can be resolved (that’s the resolve() method in the error we got) against a base absolute URI — the latter typically identifies the document in which the former appears.
It’s finding this absolute base URI that EMF is having the problem with when it says “resolve against non-hierarchical or relative base”. Why does it always want to resolve a base absolute URI? Think of the situation poor EMF is in when it gets a relative URI. What if your XSD refers to other XSDs (po-folk.xsd)? What if it specifies other relative links in relation to it’s own place in an heirarchy(../po-folk.xsd)? EMF can’t deal with that unless it knows exacly where it is in your filesystem or URI landscape.
EMF And Websphere
So, now we know how that works, but what’s wrong with getting the absolute base URI in Websphere?
Well, let’s talk about those “certain enhancements” IBM mentions when talking about the URI class. Even though you probably don’t think about it, almost everything you access in a Java runtime is some kind of archive, no matter if it’s Jar or Zip. Even if you don’t think your working inside a JAR, if you’re running an IDE chances are you are. One enhancement in the URI class of EMF provides support for the hierarchical form used for files within archives, such as the JAR scheme. By default, this support is enabled for absolute URIs with scheme equal to “jar”, “zip”, or “archive” (ignoring case), and is implemented by a hierarchical URI, whose authority includes the entire URI of the archive, up to and including the ! character.
If we would ask EMF for the absolute base URI of the po.xml file in a typical Java application, we would see this:
jar:file:/C:/workspace/test/xsd.resources.jar!/org/eclipse/xsd/po.xsd
This is the URI, with the absolute base URI being “jar:file:/C:”. EMF would be confident all things could be found in relation to this root location.
Now, what happens if we do the same thing in Websphere?
wsjar:file:/C:/workspace/test/xsd.resources.jar!/org/eclipse/xsd/po.xsd
What’s that? A non-standard archive scheme called “wsjar”?. It would appear that IBM, never content with being standard, has an archive scheme that is completely different from one if you were to access a Jar file from outside the container.
What happens when EMF tries to get an absolute base URI when it doesn’t know the archive scheme of the file it’s looking it up for?
java.lang.IllegalArgumentException: resolve against non-hierarchical or relative base
at org.eclipse.emf.common.util.URI.resolve(URI.java:1853)
How To Fix It
Now we know what we’re dealing with. How do we fix it?
Well, all we need to do is let EMF know there is another archive scheme it needs to keep an eye out for, and you can do that two ways.
At the command line:
-Dorg.eclipse.emf.common.util.URI.archiveSchemes="wsjar wszip jar zip"
Or set it up in your WAS configuration as a JVM property.
I hope you learned something interesting about absolute base URIs and stumbled upon this article before you shed too many tears. I don’t know why more people are experiencing this problem with WAS and Rational Application Developer / Rational Software Architect 7, but hopefully IBM will see it fit to provide an EMF in Eclipse that has these new archive schemas built in. Lots of headaches could be solved.
