Sending the Invoice

   

After shipping the goods, the seller prepares an invoice for the buyer. We'll write a simple application that relies on XSLT to prepare the invoice. The main point of this section is to illustrate how to build the browser on autopilot, as I mentioned previously. Indeed, this application generates an XML document (the invoice) and sends it automatically on behalf of the user . The code for the servlet is in Listing 7.9.

Listing 7.9 Ship.java
 package com.psol.xcommerce; import java.io.*; import java.net.*; import java.sql.*; import java.text.*; import org.xml.sax.*; import javax.servlet.*; import javax.servlet.http.*; import org.xml.sax.helpers.*; import org.apache.xalan.xslt.*; public class Ship    extends HttpServlet {    public void init()       throws ServletException    {       try       {          Class.forName(getInitParameter("driver"));       }       catch(ClassNotFoundException e)       {          throw new ServletException(e);       }    }    protected void style(String document,                         String stylesheet,                         Writer writer,                         String id,                         String servletPath)       throws IOException, SAXException    {       XSLTProcessor processor =          XSLTProcessorFactory.getProcessor();       XSLTInputSource source =          new XSLTInputSource(new StringReader(document));       XSLTInputSource styleSheet =          new XSLTInputSource(new FileInputStream(stylesheet));       XSLTResultTarget target = new XSLTResultTarget(writer);       processor.setStylesheetParam("id",'\ ''+ id + '\ '');       processor.setStylesheetParam("servletPath",                                    '\ ''+ servletPath +'\ '');       processor.process(source,styleSheet,target);    }    protected String style(String document,                           String stylesheet,                           String id)       throws IOException, SAXException    {       XSLTProcessor processor =          XSLTProcessorFactory.getProcessor();       XSLTInputSource source =          new XSLTInputSource(new StringReader(document));       XSLTInputSource styleSheet =          new XSLTInputSource(new FileInputStream(stylesheet));       StringWriter writer = new StringWriter();       XSLTResultTarget target = new XSLTResultTarget(writer);       processor.setStylesheetParam("id",'\ ''+ id + '\ '');       SimpleDateFormat formatter =          new SimpleDateFormat("yyyy-MM-dd");       processor.setStylesheetParam("date",'\ ''+                 formatter.format(new java.util.Date()) + '\ '');       processor.process(source,styleSheet,target);       return writer.toString();    }    protected void writeOrder(Connection connection,                              String id,                              Writer writer,                              String servletPath)       throws SQLException, SAXException, IOException    {       PreparedStatement stmt =          connection.prepareStatement("select document from " +                                      "documents where id=?");       try       {          stmt.setString(1,id);          ResultSet rs = stmt.executeQuery();          try          {             if(rs.next())                style(rs.getString(1),                      "stylesheet/toconfirm.xsl",                      writer,                      id,                      servletPath);          }          finally          {             rs.close();          }       }       finally       {          stmt.close();       }    }    protected void writeList(Connection connection,                             Writer writer,                             String servletPath)       throws IOException, SQLException    {       Statement stmt = connection.createStatement();       try       {          ResultSet rs = stmt.executeQuery("select id " +                                "from documents where new=true");          try          {             writer.write("<HTML><HEAD><TITLE>Shipping");             writer.write("</TITLE></HEAD><BODY>");             writer.write("<H1>Choose an order</H1><UL>");             while(rs.next())             {                writer.write("<LI><A HREF=\ "");                writer.write(servletPath);                writer.write("?id=");                writer.write(rs.getString(1));                writer.write("\">order #");                writer.write(rs.getString(1));                writer.write("</A></LI>");             }             writer.write("</UL></BODY></HTML>");          }          finally          {             rs.close();          }       }       finally       {          stmt.close();       }    }    protected void postInvoice(String document,                               String id,                               String post)       throws IOException, SAXException    {       String toPost = style(document,                             "stylesheet/toinvoice.xsl",                             id);       URL url = new URL(post);       HttpURLConnection connection =          (HttpURLConnection)url.openConnection();       connection.setRequestProperty("Content-type",          "application/x-www-form-urlencoded");       connection.setRequestProperty("Accept:","text/xml");       connection.setRequestMethod("POST");       connection.setDoOutput(true);       connection.setDoInput(true);       OutputStream os = connection.getOutputStream();       os.write(new String("document=").getBytes());       os.write(URLEncoder.encode(toPost).getBytes());       connection.connect();       XMLReader reader =          XMLReaderFactory.createXMLReader(             "org.apache.xerces.parsers.SAXParser");       reader.setContentHandler(new DefaultHandler()       {          public void startElement(String namespaceURI,                                   String localName,                                   String rawName,                                   Attributes atts)             throws SAXException          {             if(rawName.equals("result"))             {                String att = atts.getValue("error");                if(att == null  !att.equalsIgnoreCase("false"))                   throw new SAXException("Error during POST");             }          }       } );       reader.parse(new InputSource(connection.getInputStream()));    }    public void doGet(HttpServletRequest request,                      HttpServletResponse response)       throws IOException    {       Writer writer = response.getWriter();       try       {          String url = getInitParameter("url"),                 username = getInitParameter("username"),                 password = getInitParameter("password");          Connection connection =             DriverManager.getConnection(url,username,password);          try          {             String id = request.getParameter("id");             if(null != id && id.length() != 0)                writeOrder(connection,                           id,                           writer,                           request.getServletPath());             else                writeList(connection,                          writer,                          request.getServletPath());          }          finally          {             connection.close();          }       }       catch(SQLException e)       {          response.sendError(             HttpServletResponse.SC_INTERNAL_SERVER_ERROR,             e.getMessage());       }       catch(SAXException e)       {          response.sendError(             HttpServletResponse.SC_INTERNAL_SERVER_ERROR,             e.getMessage());       }    }    public void doPost(HttpServletRequest request,                       HttpServletResponse response)       throws IOException    {       Writer writer = response.getWriter();       try       {          String id = request.getParameter("id"),                 approved = request.getParameter("approved"),                 url = getInitParameter("url"),                 username = getInitParameter("username"),                 password = getInitParameter("password"),                 post = getInitParameter("post");          Connection connection =             DriverManager.getConnection(url,username,password);          try          {             PreparedStatement stmt =                connection.prepareStatement("select document, " +                   "address from documents where id=?");             try             {                stmt.setString(1,id);                ResultSet rs = stmt.executeQuery();                try                {                   if(rs.next())                      postInvoice(rs.getString(1),                                  id,                                  rs.getString(2));                }                finally                {                   rs.close();                }             }             finally             {                stmt.close();             }             stmt = connection.prepareStatement("update " +                       "documents set new=false where id=?");             try             {                stmt.setString(1,id);                stmt.executeUpdate();                connection.commit();             }             finally             {                stmt.close();             }             writer.write("<HTML><HEAD><TITLE>Payment " +                "confirmation</TITLE></HEAD><BODY><P> " +                "Successfully paid!<P><A HREF=\ '");             writer.write(request.getServletPath());             writer.write("\ '>Go to list</A></BODY></HTML>");          }          finally          {             connection.close();          }       }       catch(SQLException e)       {          response.sendError(             HttpServletResponse.SC_INTERNAL_SERVER_ERROR,             e.getMessage());       }       catch(SAXException e)       {          response.sendError(             HttpServletResponse.SC_INTERNAL_SERVER_ERROR,             e.getMessage());       }    } } 

This servlet accepts both GET and POST requests . In response to a GET request, it displays the list of invoices (see Figure 7.9) or the details of a given invoice (see Figure 7.10). The former reads data from the database, whereas the latter applies a style sheet to an invoice.

Figure 7.9. The list of invoices.

graphics/07fig09.gif

Figure 7.10. Details of one invoice.

graphics/07fig10.gif

The heart of this servlet is the postInvoice() method, which is called in response to the user clicking the Has been shipped button.

The method is roughly divided into three steps. First, the application uses a style sheet to convert the order into an invoice. Both are XML documents, so a style sheet is a simple and effective solution to transform one into the other:

 String toPost = style(document,                          "stylesheet/toinvoice.xsl",                          id); 

Next, it posts the result using HttpURLConnection . HttpURLConnection , part of http://java.net, implements the HTTP protocol:

 URL url = new URL(post);    HttpURLConnection connection =       (HttpURLConnection)url.openConnection();    connection.setRequestProperty("Content-type",       "application/x-www-form-urlencoded");    connection.setRequestProperty("Accept:","text/xml");    connection.setRequestMethod("POST");    connection.setDoOutput(true);    connection.setDoInput(true);    OutputStream os = connection.getOutputStream();    os.write(new String("document=").getBytes());    os.write(URLEncoder.encode(toPost).getBytes());    connection.connect(); 

Finally, it parses the result to test whether any errors have occurred:

 XMLReader reader =       XMLReaderFactory.createXMLReader(          "org.apache.xerces.parsers.SAXParser");    reader.setContentHandler(new DefaultHandler()    {       public void startElement(String namespaceURI,                                String localName,                                String rawName,                                Attributes atts)          throws SAXException       {          if(rawName.equals("result"))          {             String att = atts.getValue("error");             if(att == null  !att.equalsIgnoreCase("false"))                throw new SAXException("Error during POST");          }       }    } );    reader.parse(new InputSource(connection.getInputStream())); 

This is a prime example of a browser on autopilot. The application creates the document and posts it on behalf of the user. It even interprets the response.

Tip

To test this application, you'll need a server that accepts XML calls. The easiest solution is to run another copy of the Post servlet on a different server or on the same server but on a different port.


Transforming Orders

The style sheet in Listing 7.10 is used to transform the order into an invoice.

Listing 7.10 toinvoice.xsl
 <?xml version="1.0"?> <xsl:stylesheet    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"    version="1.0"> <xsl:output method="xml"/> <xsl:param name="id"/> <xsl:param name="date"/> <xsl:template match="/Order"> <Invoice>    <Reference><xsl:value-of select="$id"/></Reference>    <YourReference><xsl:value-of       select="Reference"/></YourReference>    <Date><xsl:value-of select="$date"/></Date>    <Due>30 days</Due>    <Terms>Please make your check payable to Que.</Terms>    <Seller>       <Name>QUE</Name>       <Address>          <Street>201 West 103RD Street</Street>          <Locality>Indianapolis</Locality>          <PostalCode>46290</PostalCode>          <Region>IN</Region>          <Country>US</Country>       </Address>    </Seller>    <Buyer>       <Name><xsl:value-of select="Buyer/Name"/></Name>       <Address>          <Street><xsl:value-of             select="Buyer/Address/Street"/></Street>          <Locality><xsl:value-of             select="Buyer/Address/Locality"/></Locality>          <PostalCode><xsl:value-of             select="Buyer/Address/PostalCode"/></PostalCode>          <Region><xsl:value-of             select="Buyer/Address/Region"/></Region>          <Country><xsl:value-of             select="Buyer/Address/Country"/></Country>       </Address>    </Buyer>    <Lines>       <xsl:for-each select="Lines/Product">          <Product>             <Description><xsl:value-of                select="Description"/></Description>             <Quantity><xsl:value-of                select="Quantity"/></Quantity>             <Price><xsl:value-of                select="Price"/></Price>             <Total><xsl:value-of                select="Total"/></Total>          </Product>       </xsl:for-each>    </Lines>    <Total><xsl:value-of select="Total"/></Total> </Invoice> </xsl:template> </xsl:stylesheet> 

The only remarkable aspect of this style sheet is that it takes two parameters:

 <xsl:param name="id"/>    <xsl:param name="date"/> 

The style() method in Ship passes the parameter values to the style sheet:

 SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");    processor.setStylesheetParam("date",'\ ''+       formatter.format(new java.util.Date()) + '\ ''); 

Note

To improve the conversion, you could create extensions, as we used in Chapter 6, and validate the pricing against a database of products. As it stands, if the buyer sends an order with incorrect pricing, he will be invoiced with these prices, which might not be acceptable.


Viewing Invoices

For completeness, Listing 7.11 is the style sheet Ship uses to display invoices. It also takes a parameter with the invoice number.

Listing 7.11 toconfirm.xsl
 <?xml version="1.0"?> <xsl:stylesheet    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"    xmlns="http://www.w3.org/TR/REC-html40"    version="1.0"> <xsl:output method="html"             encoding="ISO-8859-1"/> <xsl:param name="id"/> <xsl:template match="/Order">    <HTML>    <HEAD><TITLE>Order</TITLE></HEAD>    <BODY><TABLE>       <TR><TD><FORM ACTION="/ship" METHOD="POST">          <INPUT TYPE="HIDDEN" NAME="id" VALUE="{ $id} "/>          <INPUT TYPE="SUBMIT" VALUE="Has been shipped"/>       </FORM></TD>       <TD><FORM ACTION="/ship" METHOD="GET">          <INPUT TYPE="SUBMIT" VALUE="Will ship later"/>       </FORM></TD></TR></TABLE>       <TABLE><TR><TD COLSPAN="2" BGCOLOR="black">          <FONT COLOR="white">Order</FONT></TD></TR>       <TR><TD>Date:</TD>          <TD><xsl:value-of select="Date"/></TD></TR>       <TR><TD>Reference:</TD>          <TD><xsl:value-of select="Reference"/></TD></TR>       <TR><TD VALIGN="TOP">Seller:</TD>          <TD>             <xsl:value-of select="Seller/Name"/><BR/>             <xsl:value-of select="Seller/Address/Street"/><BR/>             <xsl:value-of select="Seller/Address/Locality"/>             <xsl:if test="Seller/Address/Region">                <xsl:text>, </xsl:text>                <xsl:value-of select="Seller/Address/Region"/>             </xsl:if>             <xsl:text> </xsl:text>             <xsl:value-of                select="Seller/Address/PostalCode"/><BR/>             <xsl:value-of select="Seller/Address/Country"/>          </TD></TR>       <TR><TD VALIGN="TOP">Buyer:</TD>          <TD>             <xsl:value-of select="Buyer/Name"/><BR/>             <xsl:value-of select="Buyer/Address/Street"/><BR/>             <xsl:value-of select="Buyer/Address/Locality"/>             <xsl:if test="Buyer/Address/Region">                <xsl:text>, </xsl:text>                <xsl:value-of select="Buyer/Address/Region"/>             </xsl:if>             <xsl:text> </xsl:text>             <xsl:value-of                select="Buyer/Address/PostalCode"/><BR/>             <xsl:value-of select="Buyer/Address/Country"/>          </TD></TR>    </TABLE><TABLE>       <TR><TD>Qty</TD><TD>Description</TD>          <TD>Price</TD><TD>Total</TD></TR>       <xsl:for-each select="Lines/Product">          <TR><TD><xsl:value-of select="Quantity"/></TD>             <TD><xsl:value-of select="Description"/></TD>             <TD><xsl:value-of select="Price"/></TD>             <TD><xsl:value-of select="Total"/></TD></TR>       </xsl:for-each>       <TR>          <TD><xsl:text             disable-output-escaping="yes">&amp;nbsp;</xsl:text>          </TD><TD><xsl:text             disable-output-escaping="yes">&amp;nbsp;</xsl:text>          </TD><TD><xsl:text             disable-output-escaping="yes">&amp;nbsp;</xsl:text>          </TD><TD><xsl:value-of select="Total"/></TD></TR>    </TABLE></BODY></HTML> </xsl:template> </xsl:stylesheet> 
   


Applied XML Solutions
Applied XML Solutions
ISBN: 0672320541
EAN: 2147483647
Year: 1999
Pages: 142

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net