Using resolvers in a J2EE context

When loading artifacts in a Java 2 Platform, Enterprise Edition (J2EE) context, you should consider the special implications that apply when loading resources from local deployment artifacts.

About this task

Loading local resources—through Class.getResource and Class.getResourceAsStream—from J2EE deployment artifacts such as EARs, WARs, and library JAR files can introduce issues when loading related XML artifacts. Loading an initial local resource using these mechanisms will succeed, but artifacts loaded from the initial resource typically will fail to load without specific consideration.

Here is an example of loading documents at execution time from a stylesheet using the XPath fn:doc function. In this case, the default behavior is to resolve documents based on the base URI from the static context.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  
	<xsl:variable name="names" select="doc('names.xml')"/>
	
	<xsl:template name="loadnames">
		<xsl:copy-of select="$names"/>
	</xsl:template>
	
</xsl:stylesheet>
If this is loaded with the following Java code in a J2EE environment:
// create the factory
XFactory factory = XFactory.newInstance();

// load the XSLT file from a local resource within a J2EE deployment artifact
StreamSource source = new StreamSource(XSLTDocFunction.class.getResourceAsStream("/samplexslts/doc.xsl"));

// Create an XSL transform executable
XSLTExecutable xslTransform = factory.prepareXSLT(source);
        
// Create the result
Result result = new StreamResult(new ByteArrayOutputStream());
        
// Create a dynamic context specifying the XSLT initial template
XDynamicContext dc = factory.newDynamicContext();
dc.setXSLTInitialTemplate(new QName("loadnames"));
        
// Execute the transformation
xslTransform.execute(dc, result);
you will receive the following error:
IXJXE0364W: FATAL ERROR:  IXJXE0774E: [ERR 0693][ERR FODC0005] 
The URI string 'names.xml' does not map to an available document.

The reason for this error is that in loading the initial XML artifact (doc.xsl), no static content was established for the base URI. In this case, the processor will fall back to looking in the current working directory, which is meaningless in a J2EE environment.

There are three possible ways to fix this situation. Here are the first two:
  • Set the baseURI in the static context.
    Adjusting to set the baseURI on the static context would look like this example:
    // create the factory
    XFactory factory = XFactory.newInstance();
            
    // set the baseURI in the static context
    URL dataURL = XSLTSchemaAware.class.getResource("/samplexslts/doc.xsl");
    XStaticContext staticContext = factory.newStaticContext();
    staticContext.setBaseURI(dataURL.toString());
    
    // load the XSLT file from a local resource within a J2EE deployment artifact        
    StreamSource source = new StreamSource(XSLTDocFunction.class.getResourceAsStream("/samplexslts/doc.xsl"));
    
    // Create an XSL transform executable
    XSLTExecutable xslTransform = factory.prepareXSLT(source, staticContext);
            
    // Create the result
    Result result = new StreamResult(new ByteArrayOutputStream());
    
    // Create a dynamic context specifying the XSLT initial template
    XDynamicContext dc = factory.newDynamicContext();
    dc.setXSLTInitialTemplate(new QName("loadnames"));
            
    // Execute the transformation
    xslTransform.execute(dc, result);
  • Load the resource in a way that allows the processor to know the baseURI.
    Adjusting to load the resource in a way that allows the processor to know the baseURI by passing the absolute URL to the StreamSource constructor would look like the following example:
    // Create the factory
    XFactory factory = XFactory.newInstance();
            
    // Create the source from a URL
    URL dataURL = XSLTSchemaAware.class.getResource("/samplexslts/doc.xsl");
    StreamSource source = new StreamSource(dataURL.toString());
    
    // Create an XSL transform executable for the expression
    XSLTExecutable xslTransform = factory.prepareXSLT(source);
            
    // Create the result
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    Result result = new StreamResult(baos);
            
    // Create a dynamic context specifying the XSLT initial template
    XDynamicContext dc = factory.newDynamicContext();
    dc.setXSLTInitialTemplate(new QName("loadnames"));
            
    // Execute the transformation
    xslTransform.execute(dc, result);
These two approaches described will work well when all XML artifacts are in a single J2EE deployment unit, but they will fail if XML artifacts are split across J2EE deployment units because there is no single baseURI for all of the XML artifacts.

To have complete control over XML artifact loading to support cases such as artifacts spread across multiple deployment units, use resolvers to completely control loading behavior.

Procedure

Implement the appropriate resolvers and register those resolvers into the static or dynamic context as appropriate.

These XML artifact loading recommendations apply within a J2EE context for all XML artifacts supported by resolvers such as XML documents (fn:doc(), document()), stylesheets (xsl:include, xsl:import), unparsed text, and XML schemas (XSLT import-schema).

Task topic Task topic    

Terms and conditions for information centers | Feedback

Last updatedLast updated: Jan 30, 2014 9:17:32 AM CST
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=matt&product=was-nd-iseries&topic=txml_resolvers_j2ee
File name: txml_resolvers_j2ee.html