One of the most annoying things with XML Schema validation is that it will not accept empty elements of certain types, like xsd:date and xsd:double, even though the element is defined as optional (minOccurs=”0″). OK, I do understand that an empty element _does_ occur, and that this behaviour is therefore correct, but the implication is that developers will have to add <xsl:if> tags in their XSLT transformations around each and every element where this may cause a problem.
This article will show how using a small and generic Java class and the “Java Callout” feature of the 11g Mediator, we can automatically “fix” these empty elements so that they will not cause problems with schema validation any more.
First, a quick recap about what we’ld need to do to prevent this problem from occuring in the first place. There are basically two ways. The first is to add <xsl:if> statements around all these elements in all XSLT transformations:
<xsl:if test="/inp1:theRequest/inp1:inputDate">
<inp1:resultDate>
<xsl:value-of select="/inp1:theRequest/inp1:inputDate"/>
</inp1:resultDate>
</xsl:if>
This will prevent empty elements from occuring in the output message. The other option is to use the xsi:nil attribute from the Schema Instance namespace. For this to work, you’ld have to set the nillable=”true” attribute in the Schema definitions of these elements, and then you’ld have to map them like this to cover all possible cases:
<xsl:if test="/inp1:theRequest/inp1:inputDate">
<inp1:resultDate>
<xsl:if test="/inp1:theRequest/inp1:inputDate/@xsi:nil">
<xsl:attribute name="xsi:nil">
<xsl:value-of select="/inp1:theRequest/inp1:inputDate/@xsi:nil"/>
</xsl:attribute>
</xsl:if>
<xsl:value-of select="/inp1:theRequest/inp1:inputDate"/>
</inp1:resultDate>
</xsl:if>
Of course, the JDeveloper will generate this code for you in the graphical XLST Map Editor, when you use the following Automap setting:
But still, that’s a lot of mapping logic for a single element, and you can’t always use automap!
There’s a lot to be said for a mechanism that automatically deletes, or “xsi:nillifies”, all empty elements “on the way out”, without having to worry too much about them before that. In BPEL, I’ve often used a generic XSLT transformation at the end of the flow to do just that. But with the Mediator, that is not so easy to do, since you only have one transformation (in each direction) available to you.
However, Mediator 11g has a “Java Callout” property that you can define against each operation, which will allow you to program a Java class that gets called, among others, after all the transformations are done. An excellent discussion of this feature can be found in this blog entry by Lucas Jellema.
For this purpose, I have written a simple Java Callout class, that adds the xsi:nil=”true” attribute automatically on ALL empty elements in a document. It is invoked at the very end of the Routing Rule, just before the response is sent back to the client. The code is below:
All you need to do to invoke this logic, is to add this class to your SOA project (you can also put it in a jar and add it to the classpath of both JDeveloper and the WLS server), and add it to the “Java Callout” property of your Mediator components:
And that’s all there’s to it. There’s one thing to consider, though. You will NOT see the result of the Java Callout anywhere in the audit trail in the console! This is the screenshot of the instance details of a simple Mediator component I used for testing:
However, when you look at the XML that was returned for this test instance, you DO see the xsi:nil=”true” attributes:
The code above is easily modified to delete the empty elements instead of adding the xsi:nil attribute to them.
Happy programming!
Its really a good demo regarding to transformation….. if possible send me some more content of SOA .