------------------------------------------------------------------------------------- package com.conway; import java.io.*; import java.net.*; //Imports required for using JDOM import org.jdom.*; import org.jdom.input.SAXBuilder; import org.jdom.output.*; import org.jdom.xpath.XPath; //These are needed by JDOM for XPath processing. //Add these jars to your classpath - they come with JDOM: //jaxen-core.jar, jaxen-jdom.jar, saxpath.jar import org.jaxen.*; import org.jaxen.jdom.*; import org.saxpath.*; /** * Sample Java code for Con-way XML Shipment Status Tracking * @author Andrew vonderLuft * * REQUIRES: JDOM * JDOM 1.0 which can be downloaded from http://jdom.org * JDOM provides a helpful abstraction layer for working with with XML within Java * * TODO: replace the USERNAME and PASSWORD String values in variables below * with your Con-way username and password * replace PRONUMBER strings with your own 9-digit PRO numbers. * * Send questions to Con-way XML Support at xmlsupport@Con-way.com */ public class XmlTrack { // TODO: replace the USERNAME and PASSWORD String values in variables below // These could also be read in from a properties file private final static String username = "USERNAME"; private final static String password = "PASSWORD"; public final static String requestType = "ShipmentStatusRequest"; public final static String responseType = "ShipmentStatusResponse"; public final static String servletUri = "XMLj/X-ShipmentStatus"; public final static String conwayUrl = "https://www.Con-way.com/"; public final static String postUrl = conwayUrl + servletUri; // JDOM Builder to create JDOM document from HTTP POST response SAXBuilder saxb = new SAXBuilder(); // Create JDOM document for the Request XML Document inJdomDoc = new Document(new org.jdom.Element(requestType)); // Create JDOM document for the Response XML Document outJdomDoc = new Document(new org.jdom.Element(responseType)); Element inRootEl = inJdomDoc.getRootElement(); Element outRootEl = outJdomDoc.getRootElement(); XMLOutputter xmlOut = new XMLOutputter(Format.getPrettyFormat()); String xmlInput = null; XPath xpath = null; boolean error, success; /** * main() is here to demonstrate how to use this class. * In actual practice you may choose to have the main() * in another class which instantiates this class and * invokes its methods * * Arguments: the array of Strings is to hold * the XML elements and their attributes using this form: * For Elements: "name=value" * For Attributes: "@name=value" ('@'prefixed to Attribute name) * Submit content in order, with any attributes following their parent element. * hence if root element has any attributes, * submit them as the first items in the String array * * @param args java.lang.String[] */ public static void main(String[] args) { // Use this String array for the value you wish to retrieve from the response String[] respElements = {"PRONmbr","StatusMessage"}; String[] xmlArgs = null; // if arguments are not passed in to main, we can use these to test: // TODO: replace PRONUMBER strings with your own 9-digit PRO numbers. if (args.length == 0) { xmlArgs = new String[] { "@testmode=Y" // attribute of the root element ,"CustRefNbr=PRONUMBER" // first child element of root element ,"CustRefNbr=PRONUMBER" }; // otherwise use arguments which are passed in. } else { xmlArgs = new String[args.length]; for (int i=0; i<args.length; i++) { xmlArgs[i] = args[i]; } } // Instantiate a ConwayXml object with the String array argments XmlTrack myConwayXml = new XmlTrack(xmlArgs); // Report success System.out.println("XML Request success = " + myConwayXml.isSuccess()); // Use object method getElementValue() // to display text values of response elements for first request // In actual practice, you could use this method to retrieve // values for processing within your own application for (int i=0; i<respElements.length; i++) { System.out.println("Value of <" + respElements[i] + ">: " + myConwayXml.getElementValue(respElements[i])); } // You can also display the entire XML response with this method: System.out.print(myConwayXml.getXmlResponse()); // You do not have to instantiate a new object for each new request. // Rather, can reuse the same object for additional requests // by using the processXmlInput() method with a new String array // of arguments // TODO: replace PRONUMBER strings with your own 9-digit PRO numbers. xmlArgs = new String[] { "@testmode=Y" // attribute of the root element ,"CustRefNbr=PRONUMBER" // first child element of root element ,"CustRefNbr=PRONUMBER" }; // process request with new arguments myConwayXml.processXmlInput(xmlArgs); // Report success System.out.println("XML Request success = " + myConwayXml.isSuccess()); // Use object method getElementValue() // to display text values of response elements for this request for (int i=0; i<respElements.length; i++) { System.out.println("Value of <" + respElements[i] + ">: " + myConwayXml.getElementValue(respElements[i])); } // Display the entire XML response for this request System.out.print(myConwayXml.getXmlResponse()); // Use the same object a 3rd time using a complete XML String // as the input // TODO: replace PRONUMBER strings with your own 9-digit PRO numbers. String xmlInString = "<ShipmentStatusRequest testmode=\"Y\">" + "<CustRefNbr>PRONUMBER</CustRefNbr>" + "<CustRefNbr>PRONUMBER</CustRefNbr>" + "</ShipmentStatusRequest>"; // process request with full XML string myConwayXml.processXmlInput(xmlInString); // Report success System.out.println("XML Request success = " + myConwayXml.isSuccess()); // Use object method getElementValue() // to display text values of response elements for this request for (int i=0; i<respElements.length; i++) { System.out.println("Value of <" + respElements[i] + ">: " + myConwayXml.getElementValue(respElements[i])); } // Display the entire XML response for this request System.out.print(myConwayXml.getXmlResponse()); // Use the same object a 4th time using a complete XML String // as the input. Use bad data to show an example of a response // with an error xmlInString = "<ShipmentStatusRequest testmode=\"Y\">" + "<CustRefNbr>abcdefg</CustRefNbr>" + // invalid PRO Number format "</ShipmentStatusRequest>"; // process request with full XML string myConwayXml.processXmlInput(xmlInString); // Report success System.out.println("XML Request success = " + myConwayXml.isSuccess()); // Display the entire XML response for this request System.out.print(myConwayXml.getXmlResponse()); // For any questions, contact ConWay XML Support at xmlsupport@Con-way.com } /** * Default no-argument constructor */ public XmlTrack() { super(); } /** * Use this constructor if you pass in the entire XML input string * @param xmlInput java.lang.String */ public XmlTrack(String xmlInput) { processXmlInput(xmlInput); } /** * Use this constructor if you pass in an array of Strings * for the XML elements and attributes * * Arguments: the array of Strings is to hold * the XML elements and their attributes using this form: * For Elements: "name=value" * For Attributes: "@name=value" ('@'prefixed to Attribute name) * Submit content in order, with any attributes following their parent element. * hence if root element has any attributes, * submit them as the first items in the String array * * @param xmlContentArray java.lang.String[] */ public XmlTrack(String[] xmlContentArray) { processXmlInput(buildXmlInput(xmlContentArray)); } /** * Take the XML input String, encode it, submit to the Con-way servlet, * then read the result into a JDOM Document * @param xmlInput java.lang.String */ public void processXmlInput(String xmlInput) { inRootEl.removeContent(); // Clear Request JDOM document setXmlInput(xmlInput); success = false; outRootEl.removeContent(); // Clear Reponse JDOM document xmlInput = URLEncoder.encode(xmlInput); /* If using JRE 1.5, the encode method above is deprecated. * You may wish to use the following instead. try { // Encode the input for a POST xmlInput = URLEncoder.encode(xmlInput, "UTF-8"); } catch (UnsupportedEncodingException use) { // If error, add error element outRootEl.addContent(new Element("Error").setText(use.getMessage())); error = true; return; } */ HttpURLConnection conwayConn = getUrlConnection(postUrl); DataOutputStream myOutStream = null; try { myOutStream = new DataOutputStream(conwayConn.getOutputStream()); myOutStream.writeBytes(requestType + "=" + xmlInput); myOutStream.flush(); myOutStream.close(); // Test the URL Connection for success if (! conwayConn.getResponseMessage().equals("OK")) { outRootEl.addContent(new Element("Error") .setText("URL " + conwayConn.getURL().toExternalForm() + ": " +conwayConn.getResponseMessage())); error = true; return; } // Create the output JDOM document using the connection's InputStream outJdomDoc = saxb.build(conwayConn.getInputStream()); outRootEl = outJdomDoc.getRootElement(); if (outRootEl.getChild("Error")==null) success = true; error = false; } catch (IOException ioe) { outRootEl.addContent(new Element("Error").setText(ioe.getMessage())); error = true; } catch (JDOMException jde) { outRootEl.addContent(new Element("Error").setText(jde.getMessage())); error = true; } } /** * Override <code>processXmlInput(String)</code> * in order to process with String array arguments from main() * @param xmlContentArray java.lang.String[] */ public void processXmlInput(String[] xmlContentArray) { processXmlInput(buildXmlInput(xmlContentArray)); } /** * @return java.lang.String - the XML input */ public String getXmlRequest () { return xmlOut.outputString(inJdomDoc); } /** * @return java.lang.String - the XML output */ public String getXmlResponse () { return xmlOut.outputString(outJdomDoc); } /** * Get the value of an XML element in the response, given its name * If more than one element of that name exists, returns value of the first * @param elementName java.lang.String - the name of the JDOM element * @return java.lang.String - the value of the JDOM element */ public String getElementValue (String elementName) { Element myEl = null; try { xpath = XPath.newInstance("//"+ elementName); myEl = (Element) xpath.selectSingleNode(outJdomDoc); } catch (JDOMException e) { // TODO Catch JDOM Exceptions e.printStackTrace(); } if (myEl != null) { return myEl.getText(); } else { return ":: ELEMENT <" + elementName + "> NOT FOUND ::"; } } /** * @return boolean - processing errors or not */ public boolean isError() { return error; } /** * @return boolean - success processing or not */ public boolean isSuccess() { return success; } /** * Using the String array of arguments containing the input XML * elements and attributes, build the XML document to submit in * the HTTP POST to the Con-way servlet. * * @param parms java.lang.String[] - the array of XML elements and attributes * @return java.lang.String - the XML input to the POST */ private String buildXmlInput(String[] parms) { String[] argNameVal = null; String argName = null; String argVal = null; Element myEl = null; Attribute myAtt = null; for (int i=0; i < parms.length; i++) { argName = parms[i].substring(0,parms[i].indexOf("=")); argVal = parms[i].substring(parms[i].indexOf("=")+1); //Determine if this content is an attribute if (argName.startsWith("@")) { myAtt = new Attribute(argName.substring(1), argVal); // if this attribute is the first argument, add it to the root element if (i==0) { inRootEl.setAttribute(myAtt); } else { myEl.setAttribute(myAtt); } } else { // If it's not an attribute, assume it's an element myEl = new Element(argName).setText(argVal); inRootEl.addContent(myEl); } } return xmlOut.outputString(inJdomDoc); } /** * Establish and set up the URL connection * * @param theUrl java.lang.String = the POST URL * @return HttpURLConnection */ private HttpURLConnection getUrlConnection(String theUrl) { //Create a URL connection java.net.HttpURLConnection conn = null; java.net.URL conwayUrl; try { conwayUrl = new URL(theUrl); conn = (HttpURLConnection) conwayUrl.openConnection(); // Setup connection parameters conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); } catch (MalformedURLException mfe) { outRootEl.addContent(new Element("Error").setText(mfe.getMessage())); error = true; } catch (IOException ioe) { outRootEl.addContent(new Element("Error").setText(ioe.getMessage())); error = true; } // Set the headers correctly (URL encoding, authentication) conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); String authString = username + ":" + password; String auth = "Basic " + new sun.misc.BASE64Encoder().encode(authString.getBytes()); conn.setRequestProperty("Authorization", auth); return conn; } /** * Set the xmlInput instance variable, and normalize the String. * @param xmlInput java.lang.String */ private void setXmlInput(String xmlInput) { // remove tabs, CR, LF, extra spaces this.xmlInput = Text.normalizeString(xmlInput); } } -------------------------------------------------------------------------------------