Use Encoders in Java SE
Table of Content
This exercise shows how to invoke encoders (specifically, the custom encoder) in a Java SE Applicatgion with an option to perform basic validation against XML schema.
Back to Top
Prerequisites
Back to Top
Create a Java SE Application project
- Using NetBeans, create a "Java Application" project by selecting "New Project..." from the "File" menu.
- Choose "Java Application" as project type.
- In this example, we use the following:
- Project Name: UseEncoderInJavaSE
- Main Class: com.sun.customencoder.Decoder
- When "Finish", the Decoder.java class is generated with the empty "main" method:
Back to Top
Create a Custom Defined Structure
- To test the invocation of the custom encoder in Java SE Application, we need to have a XSD metadata with custom encoding information and input data in native format.
Please refer to
Create a Custom Structure and Test it for creating the sample custom defined structure and test it using Encoder Tester.
- In order to test validation of decoded XML against the custom defined XML schema metadata, we need to modify the "delimited1" and "delimited2" fields to have following restriction patterns:
- Now the XSD content is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://xml.netbeans.org/schema/customDefined1"
xmlns:tns="http://xml.netbeans.org/schema/customDefined1"
elementFormDefault="qualified" xmlns:enc="urn:com.sun:encoder">
<xsd:annotation>
<xsd:appinfo source="urn:com.sun:encoder">
<enc:encoding name="Custom Encoding" namespace="urn:com.sun:encoder-custom-1.0" style="customencoder-1.0"/>
</xsd:appinfo>
</xsd:annotation>
<xsd:element name="root">
<xsd:annotation>
<xsd:appinfo source="urn:com.sun:encoder">
<urn:top xmlns:urn="urn:com.sun:encoder">true</urn:top>
<urn:nodeProperties xmlns:urn="urn:com.sun:encoder-custom-1.0">
<urn:nodeType>group</urn:nodeType>
<urn:delimiterSet>
<urn:level>
<urn:delimiter>
<urn:kind>normal</urn:kind>
<urn:precedence>10</urn:precedence>
<urn:optionalMode>never</urn:optionalMode>
<urn:terminatorMode>never</urn:terminatorMode>
<urn:bytes>
<urn:constant>|</urn:constant>
</urn:bytes>
</urn:delimiter>
</urn:level>
<urn:level>
<urn:delimiter>
<urn:kind>normal</urn:kind>
<urn:precedence>10</urn:precedence>
<urn:optionalMode>never</urn:optionalMode>
<urn:terminatorMode>never</urn:terminatorMode>
<urn:bytes>
<urn:constant>,</urn:constant>
</urn:bytes>
</urn:delimiter>
</urn:level>
</urn:delimiterSet>
</urn:nodeProperties>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="group1">
<xsd:annotation>
<xsd:appinfo source="urn:com.sun:encoder">
<urn:nodeProperties xmlns:urn="urn:com.sun:encoder-custom-1.0">
<urn:nodeType>delimited</urn:nodeType>
</urn:nodeProperties>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="delimited1">
<xsd:annotation>
<xsd:appinfo source="urn:com.sun:encoder"/>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:length value="1"/>
<xsd:pattern value="(V|X)"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="delimited2">
<xsd:annotation>
<xsd:appinfo source="urn:com.sun:encoder"/>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:decimal">
<xsd:totalDigits value="18"/>
<xsd:fractionDigits value="8"/>
<xsd:pattern value="(\+|-)?[0-9]{10}.[0-9]{8}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="group2">
<xsd:annotation>
<xsd:appinfo source="urn:com.sun:encoder">
<urn:nodeProperties xmlns:urn="urn:com.sun:encoder-custom-1.0">
<urn:nodeType>delimited</urn:nodeType>
</urn:nodeProperties>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="fixed1" type="xsd:string">
<xsd:annotation>
<xsd:appinfo source="urn:com.sun:encoder">
<urn:nodeProperties xmlns:urn="urn:com.sun:encoder-custom-1.0">
<urn:nodeType>fixedLength</urn:nodeType>
<urn:length>10</urn:length>
</urn:nodeProperties>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="fixed2" type="xsd:string">
<xsd:annotation>
<xsd:appinfo source="urn:com.sun:encoder">
<urn:nodeProperties xmlns:urn="urn:com.sun:encoder-custom-1.0">
<urn:nodeType>fixedLength</urn:nodeType>
<urn:length>15</urn:length>
</urn:nodeProperties>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Back to Top
Include Jar Files for Custom Encoder
Please refer to
Include Jar Files for Custom Encoder for details on how to include the set of jars for the custom encoder into the Java SE project.
Invoke Custom Encoder in Java SE
Now we will invoke the custom encoder in Java SE Application to decode an input data, and optinally validate the decoded XML against the custom defined XML Schema metadata.
"decode" method
/**
* Invoke custom encoder to decode the given input data, and optionally
* validate decoded XML content against the custom-defined XML schema.
*
* @param input given input data to be decoded by custom encoder.
* @param toValidate if true, then validate decoded XML content against the
* custom-defined XML schema. Otherwise, no validation.
* @return if toValidate is flase, returns decoded XML or parsing exception
* string; if toValidate is true, then returns validation error string if
* any, or parsing exception string, or valid decoded XML.
*/
public String decode(String input, boolean toValidate) {
String output = "";
try {
if (logger.isLoggable(Level.INFO)) {
logger.info("Starting invoke parse on input [" + input + "]");
}
// Get the encoder factory instance
EncoderFactory encFactory = EncoderFactory.newInstance();
// Get the encoder type instance using an encoding style, which
// in our case is "customencoder-1.0" for custom encoder.
EncoderType encoderType = encFactory.makeType("customencoder-1.0");
// Specify a top element
String namespaceURI = "http://xml.netbeans.org/schema/customDefined1";
String rootElementName = "root";
QName topElement = new QName(namespaceURI, rootElementName);
// Locate xsd metadata
String xsdMetaFile = "com/sun/customencoder/customDefined1.xsd";
URL schemaURL = this.getClass().getClassLoader().getResource(xsdMetaFile);
if (schemaURL == null) {
throw new NullPointerException("Not able to locate xsd: " + xsdMetaFile);
}
// Construct the metadata instance
MetaRef metaRef = encFactory.makeMeta(schemaURL, topElement);
// Create the encoder instance. In our case, a custom encoder instance
Encoder encoder = encFactory.newEncoder(encoderType, metaRef);
// Decode the native input data
Source decodedXMLSource = encoder.decodeFromString(input);
if (decodedXMLSource == null) {
return "";
}
// Create a writer for decoded XML string
StringWriter writer = new StringWriter();
// Create the StreamResult object
StreamResult streamResult = new StreamResult(writer);
// Get the TransformerFactory instance
TransformerFactory tfFactory = TransformerFactory.newInstance();
// Create a Transformer instance
Transformer transformer = tfFactory.newTransformer();
// Transform from decoded XML source to StreamResult
transformer.transform(decodedXMLSource, streamResult);
// Set decoded XML string as output
output = writer.toString();
if (logger.isLoggable(Level.INFO)) {
logger.info("Finished parse, get output=[" + output + "]");
}
if (toValidate) {
// invoke validation on decoded XML against XSD,
// and assign validation result to output
output = validate(output, schemaURL);
}
if (logger.isLoggable(Level.INFO)) {
logger.info("Finish validation, about to return output=[" + output + "]");
}
} catch (Exception e) {
logger.severe(e.toString());
// assign the exception details to the output
output = e.toString();
}
return output;
}
"validate" method
/**
* Validates input XML against the XML schema.
*
* @param xml input XML to be validated.
* @param schemaURL URL referencing the schema.
* @return validation error string if any during validation, or input XML
* string if no validation error.
*/
private String validate(String xml, URL schemaURL) {
String output = xml;
try {
// Create a schema factory
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
// Create a validator
Validator validator = sf.newSchema(schemaURL).newValidator();
// Create a streamSource based on input XML
StreamSource source = new StreamSource(new StringReader(xml));
// Invoke the validation
validator.validate(source);
} catch (Exception e) {
logger.severe(e.toString());
// assign the exception details to the output
output = e.toString();
}
return output;
}
"main" method
/**
* Test program.
* @param args the command line arguments
*/
public static void main(String[] args) {
try {
// create a new instance of Decoder.
Decoder decoder = new Decoder();
// set input data.
String input = "a,b|0123456789abcde12345ABCDE";
// set toValidate flag.
boolean toValidate = true;
// invoke decoding of custom encoder and to validate based on flag.
String result = decoder.decode(input, toValidate);
if (logger.isLoggable(Level.INFO)) {
logger.info("result=" + result);
}
} catch (Exception e) {
System.err.println(e.toString());
logger.severe(e.toString());
}
}
Back to Top
Run Java SE Application
- "Clean and Build" the project:
- Right click on the "Decoder.java" and select "Run File".
- Change the input data and the "toValidate" flag in the "main" method, and run the program and examine the result in the output panel or server.log file.
| Input data | toValidate | result= |
| a,b|0123456789abcde12345ABCDE | false | <?xml version="1.0" encoding="UTF-8"?><root xmlns="http://xml.netbeans.org/schema/customDefined1" xsi:schemaLocation="${SCHEMA_LOCATION}" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><group1><delimited1>a</delimited1><delimited2>b</delimited2></group1><group2><fixed1>0123456789</fixed1><fixed2>abcde12345ABCDE</fixed2></group2></root> |
| a,b|0123456789abcde12345ABCDE | true | org.xml.sax.SAXParseException: cvc-pattern-valid: Value 'a' is not facet-valid with respect to pattern '(V|X)' for type 'null'. |
| X,b|0123456789abcde12345ABCDE | true | org.xml.sax.SAXParseException: cvc-pattern-valid: Value 'b' is not facet-valid with respect to pattern '(\+|-)?[0-9]{10}.[0-9]{8}' for type 'null'. |
| X,-0000012345.50000000^|0123456789abcde12345ABCDE | true | <?xml version="1.0" encoding="UTF-8"?><root xmlns="http://xml.netbeans.org/schema/customDefined1" xsi:schemaLocation="${SCHEMA_LOCATION}" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><group1><delimited1>X</delimited1><delimited2>-0000012345.50000000</delimited2></group1><group2><fixed1>0123456789</fixed1><fixed2>abcde12345ABCDE</fixed2></group2></root> |
Back to Top
Source Code
The complete NetBean Projects are available to
download (UseEncodersInJavaSE.zip)
Email:
soabi-encoders@sun.com