Skip to Content
Introduction

[XML Schema | http://www.w3.org/XML/Schema] is a World Wide Web Consortium standard for describing the structure and content of XML documents. A document is said to be valid according to an XML Schema, if the document adheres to the rules specified in that schema. The XML Schema technology has been a core component of SAP Exchange Infrastructure since version 3.0, but as of SP16 it’s still not possible to have the Integration Server validate messages against an XML Schema. In other words, even if an interface is based on a message type, which is ultimately defined by a schema, we cannot know whether or not messages on the interface are valid according to that schema. This blog entry discusses one approach to performing validation in XI. Full source code is not provided; implementing the suggested solution is left as an exercise for the reader.

What are the reasons for wanting to validate messages passing through XI, anyway? For one, mapping programs necessarily make certain assumptions about the structure of the message being processed, meaning that these programs can fail, if the message is invalid. Failing an invalid message early helps pinpoint the exact cause of the problem and provides the developer with better debugging information. Another prime reason for performing validation, is ensuring the data quality of messages that go out to external partners, suppliers and customers.

In XI “userland” (i.e. outside the Integration Engine core), XML Schema validation can be implemented in a Java mapping program or in an adapter module. Code executing in either has access to the contents of the message being processed and to a validating XML parser. ABAP mapping programs are not an option, as the ABAP XML parser currently does not support XML Schema. The solution discussed in this blog entry is a Java mapping program, but the techniques described can be applied equally well to an adapter module.

A brief introduction to Java mapping programs

Contrary to adapter modules, which are Enterprise Java Beans, Java mapping programs are garden-variety J2SE classes. They do not require deployment in the Web Application Server, rather they must be packaged in ZIP or JAR archives and uploaded to the Integration Repository under Imported Archives. Every mapping program class must implement the

StreamTransformation

interface provided by SAP, which is located in the

aii_map_api.jar

file. The interface contains only two methods:

execute

and

setParameter

.

The

setParameter

method is called by the mapping runtime, which passes a

java.util.Map

object containing runtime information such as the message ID, sender and receiver of the message being processed. The keys used for looking up values in this

Map

object are constants in the

StreamTransformationConstants

class.

The

execute

method is where the interesting stuff happens. The method receives a

java.io.InputStream

object and a

java.io.OutputStream

object. The former provides access to the payload of the message being processed. The latter is used for writing the transformed message, which will either be passed on to the next mapping program or to the next XI pipeline step.

Finally, a word of caution: Since mapping programs are nothing more than ordinary Java classes, the developer has unrestricted access to the entire J2SE class library. However, code that reads or writes files, opens network connections, accesses databases etc. should never find its way into your mapping class; your code should only perform transformations on the message being processed.

Validating XML documents in Java

Performing schema validation in Java code is fairly straightforward. The first step is to obtain an object of class

javax.xml.parsers.SAXParser

, which the following piece of code takes care of for us (the appropriate

import

statements are not shown):



SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(true);
SAXParser sp = spf.newSAXParser();

The next step is to inform the parser that we want to validate using XML Schema and provide it with an

InputStream

to the schema we want to use:



sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage",
"http://www.w3.org/2001/XMLSchema");
sp.setProperty("http://java.sun.com/xml/jaxp/properties/schemaSource",
mySchemaInputStream);

Now we’re almost ready to start parsing an actual document, which we do by calling the method

parse(InputStream is, DefaultHandler dh)

on the

SAXParser

object. When recoverable errors occur during parsing (validation errors are considered recoverable), the parser calls the

error

method on the

DefaultHandler

object. However, the implementation of the

error

method in the

DefaultHandler

class does nothing. When validation errors occur, we want to throw an exception, so instead of using the

DefaultHandler

class directly, we subclass it as follows:



final class ParseErrorHandler extends DefaultHandler {
public void error(SAXParseException e) throws SAXException {
throw e;
}
}

If

myDocument

is an

InputStream

to an XML document, we’re now able to parse and validate the document by calling the parse method like so:



sp.parse(myDocument, new ParseErrorHandler());

The proposed solution

Putting it all together

When you have a working Java mapping class, you need to create a JAR file containing the mapping program class file, the schemas and the

SchemaRepository.xml

document. This JAR file must then be uploaded to the Integration Repository under Imported Archives. At this point, the Java mapping program is available to Interface Mappings in every namespace below the Software Component Version, under which the archive was uploaded.

The final step is to add the Java mapping program to each Interface Mapping that requires validation. Add the program as the first mapping step, if you want to validate inbound (relative to the Integration Server) messages. Add it as the last mapping step, if you want to validate outbound (again, relative to the Integration Server) messages.

Have fun!

To report this post you need to login first.

8 Comments

You must be Logged on to comment or reply to a post.

  1. Giovanni Maria Pace
    Hi Morten,
    following your suggestions I did a simple java mapping with PARSING task.(THANKS A LOT :-))
    nevertheless with a simple output stream in bytes format I do not have any output.
    any suggestion on this issue?

    thanks in advance for all the help you can give me.

    Regards,
    Giammaria Pace
    Xi consultant

    (0) 
  2. Danny De Roovere
    hello,

    Please find below my source code. I’ve created a jar file containing the schema’s and both classes but it doesn’t seem to work.
    What can be wrong?

    Kr,
    Danny

    —– SaxParserFactoryImplementation class —–

    import java.io.File;
    import java.io.IOException;

    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;

    import org.xml.sax.SAXException;

    public class SaxParserFactoryImplementation {

      public SaxParserFactoryImplementation(Object mySchemaInputStream, File myDocument, Object schema, Object schemaName) {

         SAXParserFactory factory = SAXParserFactory.newInstance();
         factory.setNamespaceAware(true);
         factory.setValidating(true);
         try {

         SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();

         saxParserFactory.setNamespaceAware(true);

         saxParserFactory.setValidating(true);

         SAXParser saxParser = saxParserFactory.newSAXParser();


         saxParser.setProperty(“http://java.sun.com/xml/jaxp/properties/schemaLanguage“, “http://www.w3.org/2001/XMLSchema“);

         saxParser.setProperty(“http://java.sun.com/xml/jaxp/properties/schemaSource“, mySchemaInputStream);

    saxParser.parse(myDocument, new ParseErrorHandler());

         } catch(SAXException exc) {

         exc.printStackTrace();

         } catch (ParserConfigurationException e) {
              e.printStackTrace();
         } catch (IOException e) {
              e.printStackTrace();
         }

       }

    }

    —– ParseErrorHandler class —–

    import org.xml.sax.SAXException;
    import org.xml.sax.SAXParseException;
    import org.xml.sax.helpers.DefaultHandler;

    public class ParseErrorHandler extends DefaultHandler {
         public void error(SAXParseException e) throws

    SAXException {
              throw e;
         }
    }

    (0) 
  3. CHANDRASEKHAR TARAPAREDDY
    Hi

    It is very usefull. however i have a question.. I am executing this as part of transformation step (after recieve) in BPM. so when ScehmaValidation fails i am throwing StreamTrasformationException (with actual message of where it is failing) from the Java code, how can i send the exception message (ex.getMessage()) back to the sender..

    thanks

    (0) 
  4. Eugene Balakhonov

    Hello,<br/><br/>Do you have any idea how to validate XML message when XML Schema has two or more different files?<br/>It need when input XML message have tags from different name spaces.<br/><br/>According SAP documentation <br/>http://help.sap.com/saphelp_erp2004/helpdata/en/c4/e1343e8c7f6329e10000000a114084/content.htm<br/>I created following code:<br/><br/><br/>File operday.xsd contains tag <br/><br/><xsd:import namespace=”http://sap.com/xi/XI/SplitAndMerge” schemaLocation=”operday_sp.xsd”/><br/><br/><br/><br/>….<br/>org.xml.sax.InputSource shemaSource[] = new org.xml.sax.InputSource[2];<br/>shemaSource[0] = xml_schema_inputStream1;<br/>shemaSource[0].setSystemId(“operday_sp.xsd”);<br/>shemaSource[0].setPublicId(“operday.xsd”);<br/>shemaSource[1] = xml_schema_inputStream1;<br/>shemaSource[1].setSystemId(“operday_sp.xsd”);<br/>shemaSource[1].setPublicId(“operday_sp.xsd”);<br/>….<br/>saxParser.setProperty(“http://java.sun.com/xml/jaxp/properties/schemaSource“, shemaSource);<br/>…<br/>saxParser.parse(document_InputStream, new ParseErrorHandler());<br/><br/><br/>But this isn’t works.<br/><br/>What is wrong?<br/><br/>Thanks.<br/><br/>Best regards,<br/>Eugeny

    (0) 
    1. Morten Wittrock Post author
      Hi Eugene

      I get this question quite often, actually. I’ll put the answer in a blog post shortly. Stay tuned.

      Regards,

      Morten Wittrock

      (0) 
      1. CHANDRASEKHAR TARAPAREDDY
        Hi Morten,

        I have the same problem, cannot validate if the root schema has xsd:include another schema. the parser is not able to find the included schema. i have included both schemas in the jar file that i imported into the repository.

        Any ideas??

        thanks
        Chandra

        (0) 

Leave a Reply