Question

Okay, so here's the short of what I'm trying to achieve. I am developing a small Google App Engine application that generates XML given a particular object.

Now, I run into issues because I need to use a Relax NG schema and validate it against my Document object. This works fine on my local machine (Eclipse Helios Java EE, Mac OS X Snow Leopard, Google Web Toolkit 2.2.0, App Engine 1.4.2), but as soon as I deploy to App Engine, my code fails and throws an IllegalArgumentException.

The specific exception is this:

   java.lang.IllegalArgumentException: No SchemaFactory that implements the schema language specified by: http://relaxng.org/ns/structure/1.0 could be loaded

The specific line(s) of code that it is complaining about are the following:

  System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.CompactSyntaxSchemaFactory");
  SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);

The last line is the line that throws the Exception.

I have tried looking online, and posted in several Google Groups, but no one came forth with an idea.

Note: I took the use of some of the above code from this example: How to validate an XML document using a RELAX NG schema and JAXP?

My suspicion is that App Engine is not loading Jing.jar for some reason. I don't know how I can check that it is/isn't.

Any help would be appreciated! Thanks!

Was it helpful?

Solution 3

Well, I actually found a workaround of sorts that completely takes out the (practically hackish) use of System.setProperty.

It turns out that Jing has a little class called "CompactSyntaxSchemaFactory".

Here is how I used it:

    DocumentBuilderFactory docFactory = null;

    CompactSyntaxSchemaFactory scReader = new CompactSyntaxSchemaFactory();
    URL relaxSchemaURL = new URL("http://example.com/myschema.rng");
    Schema2 relaxSchema = scReader.newSchema(relaxSchemaURL);

    docFactory = DocumentBuilderFactory.newInstance();
    docFactory.setSchema(relaxSchema);

Worked like a charm.

OTHER TIPS

This post just to clarify.

The usual way I would validate an XML document with Jing and Relax NG is:

System.setProperty(SchemaFactory.class.getName() + ":" + XMLConstants.RELAXNG_NS_URI, "com.thaiopensource.relaxng.jaxp.XMLSyntaxSchemaFactory");
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.RELAXNG_NS_URI);
Schema schema = factory.newSchema(new File("path/to/schema.rng"));

Validator validator = schema.newValidator();
validator.validate(new StreamSource(new StringReader(xmlString)));

Now, in App Engine, the first two lines don't work, and cause an IllegalArgumentException to be thrown, like you said. So exchanging them with

SchemaFactory factory = new XMLSyntaxSchemaFactory();

does the trick. Summary (including imports):

import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import com.thaiopensource.relaxng.jaxp.XMLSyntaxSchemaFactory;

SchemaFactory factory = new XMLSyntaxSchemaFactory();
Schema schema = factory.newSchema(new File("path/to/schema.rng"));

Validator validator = schema.newValidator();
validator.validate(new StreamSource(new StringReader(xmlString)));

Note that this is for schemas in XML syntax. For compact syntax, exchange XMLSyntaxSchemaFactory with CompactSyntaxSchemaFactory.

I'd guess that System.setProperty() is failing, or rather not being used correctly. According to the docs:

All system properties and environment variables are private to your application. Setting a system property only affects your application's view of that property, and not the JVM's view.

If SchemaFactory is part of the JDK (which I think it is), you may not be able to reset it. However, you may have more luck setting the system property in your appconfig file, as this might get changed earlier in the startup sequence.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top