Index Changes

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:

    • For "delimited1" field:
    • For "delimited2" field:
  • 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)(info)

  • Any questions/feebacks?
Email: soabi-encoders@sun.com

JSPWiki v2.4.100
[RSS]
« Home Index Changes Prefs
This page (revision-11) was last changed on 20-Nov-08 14:24 PM, -0800 by LixinTang