Tech all over the world
Friday, May 26, 2006
  Enterprise Java Technologies Tech Tips, May 25, 2006 (JAX-WS and SSL, Document Handling)
You are receiving this e-mail because you elected to receive e-mail from Sun Microsystems, Inc. To update your communications preferences, please see the link at the bottom of this message. We respect your privacy and post our privacy policy prominently on our Web site http://sun.com/privacy/

Please do not reply to the mailed version of the newsletter, this alias is not monitored. Feedback options are listed in the footer for both content and delivery issues.
  Welcome to the Enterprise Java Technologies Tech Tips.
Enterprise Java Technologies
TECHNICAL TIPS
May 27, 2006
View this issue as simple text
In this Issue
 
Welcome to the Enterprise Java Technologies Tech Tips for May 30, 2006. Here you'll get tips on using enterprise Java technologies and APIs, such as those in Java 2 Platform, Enterprise Edition (J2EE) and Java Platform, Enterprise Edition 5 (Java EE 5).

This issue covers:

» Using JAX-WS-Based Web Services with SSL
» Document Handling in Web Services Applications

These tips were developed using an open source implementation of Java EE 5 called GlassFish. You can download GlassFish from the GlassFish Project page.

You can download the sample archive for the tip Using JAX-WS-Based Web Services with SSL at http://java.sun.com/developer/EJTechTips/download/ttmay2006ws-ssl.zip. You can download the sample archive for the Document Handling in Web Services Applications at http://java.sun.com/developer/EJTechTips/download/ttmay2006doc-ws.zip.

Any use of this code and/or information below is subject to the license terms.

See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.

USING JAX-WS-BASED WEB SERVICES WITH SSL
 
by Shing Wai Chan

In Java EE 5, a web service that is based on JAX-WS can be implemented either as an EJB endpoint or servlet endpoint. An example of a JAX-WS-based web service implemented as an EJB endpoint is provided in the Tech Tip Developing Web Services Using EJB 3.0. A JAX-WS-based web service implemented as a servlet endpoint is provided in the Tech Tip Developing Web Services Using JAX-WS.

Irrespective of the way a web service is implemented, most enterprise applications, including those that use web services, need to run in a secure environment. Transport Layer Security (TLS)/Secure Sockets Layer (SSL) is a point-to-point secure transport mechanism that can be used for authentication, message integrity, and confidentiality. TLS/SSL (or in this tip, simply "SSL") meets the security requirements of most enterprise application environments, and is widely adopted.

This Tech Tip shows you how to construct a JAX-WS-based web service that runs with SSL, and how to access the web service from an application client. A sample package accompanies the Tech Tip. It demonstrates a Java client accessing a JAX-WS web service using SSL. Examples are provided for web services implemented as EJB and servlet endpoints. The sample uses an open source reference implementation of Java EE 5 called GlassFish. You can download GlassFish from the GlassFish Community Downloads page.

Write the Class for the Web Service Endpoint

Let's begin by writing a Java class for the web service. SSL has no impact on the Java code for the web service endpoint. The same code works for web services that use SSL or that don't use SSL.

In Java EE 5, you can use annotations to easily construct a JAX-WS web service. Here's an example of a web service implemented as an EJB endpoint:

    package ejbws;     import javax.annotation.Resource;    import javax.ejb.Stateless;    import javax.jws.WebService;    import javax.xml.ws.WebServiceContext;     @Stateless    @WebService    public class HelloEjb {        @Resource WebServiceContext wsContext;         public String hello(String msg) {            return "Ejb WS: " + wsContext.getUserPrincipal()             + ": " + msg;        }    } 

The @Stateless annotation marks the class as a stateless session bean, and the @WebService annotation marks the class as a web service. The @Resource annotation is used to declare resource dependencies that the class has -- in essence, what resources the class needs. These resources are then injected into the endpoint implementation. In this example, the annotation identifies a resource dependency on the WebServiceContext. The class needs the WebServiceContext to get context information about requests, such as related security information.

Here's the same web service implemented as a servlet endpoint:

    package servletws;     import javax.annotation.Resource;    import javax.jws.WebService;    import javax.xml.ws.WebServiceContext;     @WebService    public class HelloServlet {        @Resource WebServiceContext wsContext;         public String hello(String msg) {            return "Servlet WS: " + wsContext.getUserPrincipal()             + ": " + msg;        }    } 

Specify Security Information in Deployment Descriptors

To use SSL in a web service that is implemented as an EJB endpoint, you need to specify security information in a vendor-specific deployment descriptor (in this tip, sun-ejb-jar.xml). For a web service implemented as a servlet, you need to specify the security information in the web.xml descriptor.

One important aspect of secure communication through SSL is server authentication, that is, confirming the identity of the server to the client. Another aspect is client authentication, where the server confirms the identity of the client. In SSL, you can have either server authentication or the combination of server and client authentication (but not client authentication alone). This tip uses the term "mutual authentication" to mean the combination of server and client authentication. (Note however that other documents might attach a different meaning to mutual authentication. For example, in some documents, the term client authentication is synonymous with mutual authentication.)

To enable SSL server authentication, you need to set the <transport-guarantee> element to CONFIDENTIAL. For a web service implemented as an EJB endpoint, you set the element in the sun-ejb-jar.xml deployment descriptor. For a web service implemented as a servlet, you set the element in the web.xml deployment descriptor. As an example, for the HelloEjb web service, the <transport-guarantee> element in the sun-ejb-jar.xml deployment descriptor should look this:

    <ejb>      <ejb-name>HelloEjb</ejb-name>      <webservice-endpoint>        <port-component-name>HelloEjb</port-component-name>        <transport-guarantee>CONFIDENTIAL</transport-guarantee>      </webservice-endpoint>    </ejb> 

For the HelloServletService service, the <transport-guarantee> element web.xml deployment descriptor should look like this:

    <security-constraint>      <web-resource-collection>        <web-resource-name>Secure Area</web-resource-name>        <url-pattern>/HelloServletService/HelloServlet        </url-pattern>        <http-method>POST</http-method>      </web-resource-collection>      <auth-constraint>        <role-name>EMPLOYEE</role-name>      </auth-constraint>      <user-data-constraint>        <transport-guarantee>CONFIDENTIAL</transport-guarantee>      </user-data-constraint>    </security-constraint> 

Notice the <http-method> element value of POST in web.xml. JSR-109, "Implementing Enterprise Web Services", specifies that the service endpoint authorization must be defined using an http-method element value of POST.

In GlassFish, WSDL files are protected by SSL for endpoints with SSL or SSL mutual authentication. For SSL mutual authentication, you need to set the <auth-method> subelement of the <login-config> element to CLIENT-CERT. You also need to set the <transport-guarantee> element to CONFIDENTIAL. For instance, in sun-ejb-jar.xml;

    <ejb>      <ejb-name>HelloEjb</ejb-name>      <webservice-endpoint>        <port-component-name>HelloEjb</port-component-name>        <login-config>          <auth-method>CLIENT-CERT</auth-method>          <realm>certificate</realm>        </login-config>        <transport-guarantee>CONFIDENTIAL</transport-guarantee>      </webservice-endpoint>   </ejb> 
    <security-constraint>      <web-resource-collection>        <web-resource-name>Secure Area</web-resource-name>        <url-pattern>/HelloServletService/HelloServlet        </url-pattern>        <http-method>POST</http-method>      </web-resource-collection>      <auth-constraint>        </role-name>EMPLOYEE</role-name>      </auth-constraint>      <user-data-constraint>        <transport-guarantee>CONFIDENTIAL</transport-guarantee>      </user-data-constraint>    </security-constraint>    <login-config>      <auth-method>CLIENT-CERT</auth-method>      <realm-name>certificate</realm-name>    </login-config> 

No deployment descriptor is needed for the client program.

Package and Deploy the Web Service Application

Packaging and deploying a web service application that uses SSL is the same as for a web service application that doesn't use SSL. Keep in mind however, that if the web service is implemented as a servlet endpoint in an enterprise archive (that is, a .ear file), you need to include the application.xml file to specify the context-root for the web application.

Write the Client

After deploying the web service, you can access it from a client program. The client program for a web service application that uses SSL is essentially the same as one that doesn't use SSL. The major difference is that instead of using HTTP as the internet protocol, you need to use HTTPS. In the client, you use the @WebServiceRef annotation to declare a reference to a web service. The value of the wsdlLocation parameter in @WebServiceRef is a URL that points to the location of the WSDL file for the service being referenced. So for a web service client that uses SSL, the wsdlLocation parameter in the @WebServiceRef annotation needs to specify an HTTPS URL. For example:

    @WebServiceRef(wsdlLocation=        "https://serverName:8181/HelloEjbService/HelloEjb?WSDL")    private static HelloEjbService helloEjbService; 

You can then access the port for the web service and invoke the web service:

    HelloEjb helloEjbPort = helloEjbService.getHelloEjbPort();    helloEjbPort.hello("Hello World"); 

Client-side artifacts are generated by accessing the WSDL file through HTTPS. To do that, you need to specify the location of a truststore file for the server and its password in the environment variable VMARGS. In SSL, you can use certificates to authenticate the server or for mutual authentication of both the server and client. The truststore file for the server contains the trusted certificates for the server and its keys.

You can specify the location of the server's truststore file and its password in various ways, for example, you can specify them in an ant script as follows:

    <exec executable="wsimport">      <env key="VMARGS"           value="-Djavax.net.ssl.trustStore=${truststore.location}           -Djavax.net.ssl.trustStorePassword=${ssl.password}"/>     <arg line="-keep -d ${client.build}      https://serverName:8181/HelloEjbService/HelloEjb?WSDL"/>    </exec> 

Set Up the Client Truststore and Keystore

In addition to a truststore file for the server, you also need a truststore file for the client. The client validates the server certificate against a set of certificates in its truststore. For a secure connection to be made using SSL, the client-side truststore needs to trust the server certificate. For SSL mutual authentication, the server-side truststore also needs to trust the client certificate. If you modify the server-side truststore, you need to restart the server (this allows use of the new certificate). You might not need to do this in a production environment because production certificates are signed by a common Certificate Authority (CA). The GlassFish builds include certificates for several common root CAs.

For SSL mutual authentication, you need to provide your own key in a client keystore (a file that contains the client's keys and certificates). You can use keytool, a key and certificate management utility in JDK 5.0, to generate the keystore.

Run the Client

Before you run the client that access a web service with SSL, you need to set the value of the environment variable, VMARGS. After that, you can run the application as usual. For SSL, set the value of VMARGS to:

    -Djavax.net.ssl.trustStore=${truststore.location}     -Djavax.net.ssl.trustStorePassword=${ssl.password} 

For SSL mutual authentication, set the value of VMARGS to:

    -Djavax.net.ssl.trustStore=${truststore.location}     -Djavax.net.ssl.trustStorePassword=${ssl.password}     -Djavax.net.ssl.keyStore =${keystore.location}     -Djavax.net.ssl.keyStorePassword=${ssl.password} 

Running the Sample Code

To install and run the sample code that accompanies this tip:

  1. If you haven't already done so, download GlassFish from the GlassFish Community Downloads Page, and install it.

  2. Set the following environment variables:

    • GLASSFISH_HOME. This should point to where you installed GlassFish.

    • ANT_HOME. This should point to where ant is installed. Ant is included in the GlassFish bundle that you downloaded. (In Windows, it's in the lib\ant subdirectory.)

    • JAVA_HOME. This should point to the location of JDK 5.0 on your system.

    Add $JAVA_HOME/bin, $ANT_HOME/bin, and $GLASSFISH_HOME/bin to your PATH environment variable.

  3. Download the sample package and extract its contents. You should now see the newly extracted directory as <sample_install_dir>/ttmay2006ws-ssl, where <sample_install_dir> is the directory in which you installed the sample package. The ws-ssl directory below ttmay2006ws-ssl contains the source files and other support files for the sample.

  4. Change to the ws-ssl directory and edit the build.properties file as appropriate. For example, if the admin host is remote, change the value of admin.host from the default localhost to the appropriate remote host. Also, make sure that the following properties are correctly specified:

    • server.cert.cn. The CN name of the server certificate. It should be the host name or the fully-qualified domain name. In the default installation of GlassFish, the server certificate has the alias name s1as. You can display the CN by issuing the following command:
               keytool -list -v -alias s1as -keystore          $GLASSFISH_HOME/domains/domain1/config/cacerts.jks 
      In response, you'll be prompted for a keystore password. Respond with the default password, changeit. You can change the password.

    • admin.user. The ID of the administrator who starts and stops the domain.

    • admin.port. The http port number of administrative server.

    • https.port. The https port number of server.

  5. Update the value of AS_ADMIN_PASSWORD in the passwd file to the administrator password.

  6. Set up the client key and certificate, by entering the following command:
           ant setup 
    This creates a private key in a local keystore, exports the certificate, and imports it to the common truststore. Note that a self-signed certificate is installed in the truststore. This is for testing purposes only and is not recommended for production.

  7. If GlassFish is running, stop it as follows:
           $GLASSFISH_HOME/bin/asadmin stop-domain domain1 
    Then start it:
              $GLASSFISH_HOME/bin/asadmin start-domain domain1 
    This picks up the new certificate in the truststore.

  8. Build and deploy the sample. First enter the following command:
           ant build 
    This compiles the EJB and Servlet Web Services classes and creates an ear file.

    Then enter the command:
           ant deploy 
    This deploys the ear file in GlassFish.

    And finally, the following command:
           ant build-client 
    This generates artifacts and compiles the client-side code.

  9. Run the client application to access the web service with SSL. Enter the following command:
           ant run 
    You should see results that look something like this:
           [exec] Retrieving port from the service        ejbws.HelloEjbService@4e21db       [exec] Invoking hello operation on the        HelloEjbService port       [exec] Ejb WS: CN=serverName, OU=SSLClient, O=EJTechTips,        L=Santa Clara, ST=California, C=US: Hello World       [exec] Retrieving port from the service        servletws.HelloServletService@ea7549       [exec] Invoking hello operation on the        HelloServletService port       [exec] Servlet WS: CN=serverName, OU=SSLClient,        O=EJTechTips, L=Santa Clara, ST=California,        C=US: Hello World 
    You can see additional information, such as information about the SSL handshake, by adding jvm option -Djavax.net.debug=ssl,handshake. You can do this for the sample by entering the following command:
            ant run-debug 
    You can verify that this is an SSL mutual authentication by looking at the CertificateRequest during handshake.

    If you want to see more debugging information, use the jvm option -Djavax.net.debug=all.

  10. You can undeploy the Web Service ear file, by entering the command:
            ant undeploy 
  11. After you undeploy the application, remove the generated client certificate from the keystores and restart the server so that the certificate is removed from memory. To do that, enter the commands:
            ant unsetup        $GLASSFISH_HOME/bin/asadmin stop-domain domain1        $GLASSFISH_HOME/bin/asadmin start-domain domain1  

About the Author

Shing Wai Chan is a senior member of the Sun Java Application Server and Java EE SDK development teams. He has been focusing on development projects that relate to security, annotations, CMP, B2B and B2C.

Back to Top

DOCUMENT HANDLING IN WEB SERVICES APPLICATIONS
 
by Deep Singh

Java EE provides various technology choices for handling XML documents. Three of these technologies are Java Architecture for XML Binding (JAXB), Streaming API for XML (StAX), and the Document Object Model (DOM) API. This Tech Tip compares these choices, and shows the technologies in use in a sample application.

JAXB

JAXB technology provides a way to bind XML schemas to Java objects so that developers can easily process data in their Java applications. The JAXB API provide methods to unmarshal an XML document into a Java object and marshal a Java object into an XML document. For more information about JAXB, see the Tech Tip What's New in JAXB 2.0.

A significant advantage of using JAXB is that you can compile the schema (or dtd) to generate a Java content tree, and then work with plain Java objects. JAXB is not particularly good in cases where complex schemas are involved and you want to work with only a small set of content.

StAX

StAX is a streaming API for processing XML documents. It's an event-driven, "pull" parser that reads and writes XML documents. For more information about StAX, see the Tech Tip Introducing the Sun Java Streaming XML Parser.

StAX's bidirectional features, small memory footprint, and low processor requirements give it an advantage over APIs such as JAXB or DOM. StAX is particularly effective in extracting a small set of information from a large document. The primary drawback in using StAX is that you get a narrow view of the document -- essentially you have to know what processing you will do before reading the XML document. Another drawback is that StAX is difficult to use if you return XML documents that follow complex schema.

DOM

DOM is platform-neutral and language-neutral API that enables programs to dynamically update the contents of XML documents. For more information about DOM, see the Tech Tip Using the Document Object Model.

DOM creates an in-memory object representation of an entire XML document. This allows extreme flexibility in parsing, navigating, and updating the contents of a document. DOM's drawbacks are high memory requirements and the need for more powerful processing capabilities.

The sample application: comparing JAXB, StAX, and DOM

A sample application accompanies this tip. It demonstrates JAXB, StAX, and DOM in use to handle an XML document that is passed as input to a web service. The sample application involves credit card authorization. The application client code calls a web service to authorize payment on a credit card provided by a customer. The client sends credit card and card holder information contained in an XML document to the web service. The client can process the XML document using JAXB, StAX or DOM. The sample demonstrates the XML document processing using all three technologies.

This section describes how to install and run the sample application.

Setting up your environment

The sample uses an open source reference implementation of Java EE 5 called GlassFish. If you haven't already done so, download GlassFish from the GlassFish Community Downloads page. To build and run the sample, you also need JDK 5.0, which you can download from the J2SE 5.0 downloads page, and Apache Ant 1.6.5, which is in the GlassFish bundle (in Windows, it's in the lib\ant subdirectory).

Installing the sample application

Download the sample package and unzip its contents. The root directory for the sample is techtip. Change the current directory to the techtip directory. Edit the script env.sh (for UNIX) or env.bat (for Windows) to reflect your build environment. For example, change the value of the JAVA_HOME environment variable in the script to the location of JDK 5.0 on your system. Then execute the script to set up your environment.

Building the web service

The sample builds a web service using a WSDL file. The steps involved in doing this are:

  1. Create a WSDL file based on XML schemas.
  2. Write an endpoint implementation class.
  3. Generate portable artifacts for web services execution.
  4. Compile the web service, package it as a WAR file, and deploy it.
Let's look at these steps a little closer.

Create a WSDL file based on XML schemas

A WSDL file is packaged with the sample. You can find the WSDL file, CreditCardService.wsdl, in the conf directory. The WSDL file exposes web service operations that authorize credit card payments. There's a separate operation for each of the three XML handling technologies used in the application, JAXB, StAX, and DOM. For more information about WSDL, see Web Services Description Language (WSDL) 1.1.

Schema files

The two schema files that the WSDL file imports are CreditCardAuthorization.xsd and CreditCardServiceException.xsd. CreditCardAuthorization.xsd defines the structure of the XML document that a client can send to the web service. The elements in the schema that are pertinent to credit card authorization requests are:

   <element name="AuthorizationRequest"    type="tns:AuthorizationRequest"/>       <element name="authorizePaymentSTAX" type="xsd:string"/>        <element name="authorizePaymentDOM">        <complexType>                <sequence>                        <any maxOccurs="1"/>                </sequence>        </complexType>     </element>   

The type value tns:AuthorizationRequest is a complex type with elements for information about the credit card and its user. For StAX, the element type is xsd:string, and for DOM the element type is xsd:any. Similar elements are defined and used for returning authorization status.

CreditCardServiceException.xsd defines the structure of an XML document for returning an error message, that is, when the web service cannot process the request.

Generate portable artifact

The sample uses the wsimport tool to generate portable artifacts such as the Service Endpoint Interface (SEI), the service class, JAXB classes, and exception classes. In the sample this is done in an ant task that has the target name generate-server. You can find the ant tasks for the sample in the build.xml file in the techtip directory. The XML for the ant task that generates the portable artifacts is as follows:

    <target name="generate-server" depends="prepare">       <wsimport           ...                          wsdl="${server.wsdl}">         <binding dir="${confdir}"            includes="${server.config}"/>       </wsimport>    </target>  

The ant variables mentioned above are defined in the build.properties file in the conf directory. Notice the <binding> element. It uses an external binding file, config-server.xml, that you can find in the conf directory. In JAXB, you bind the schema for an XML document into a set of Java interfaces and classes that represents the schema. You then compile the interfaces and classes. The config-server.xml file defines the JAXB bindings for the schema used in the sample. As far as compiling the interfaces and classes that represent the schema, GlassFish includes JAX-WS which internally calls JAXB's binding compiler, xjc.

After the artifacts are generated, they're compiled using the javac compiler. In the sample, this is done using an ant task with the target name compile-server.

Write an endpoint implementation class

The sample provides an endpoint implementation class, CreditCardService.java, which you can find in the src\server directory. CreditCardService.java implements the SEI that was generated in the previous step using CreditCardService.wsdl and the wsimport tool. The class contains the methods for the different document handling technologies.

Here is the method that makes use of JAXB:

    public AuthorizationStatus authorizePaymentJAXB(     AuthorizationRequest parameters) throws      com.sun.techtip.cardservice.service.CardServiceException {       try {            CreditCard card = parameters.getCreditCard();           CardUser user = parameters.getCardUser();                // For sake of simplicity, read only limited            // information about credit card and credit card user           String cardNumber = card.getCardNumber();           String lastName = user.getLname();               // Emulate charge authorization           dao.authorizeCharge(cardNumber, lastName);            // Create and populate authorization status object           ObjectFactory of = new ObjectFactory();           AuthorizationStatus status =              of.createAuthorizationStatus();           status.setAuthorizationToken(dao.authorizationToken);           ...                      return status;  

The method receives a JAXB-generated object as a parameter. The method retrieves relevant JAXB objects: CreditCard and CardUser. It then uses these objects to get required information, such as the credit card number and card user name. Next, the method calls the business logic in the application to authorize the charge on the card. The dao object is an instance of the CreditCardDAO class in src\server directory. This class provides information such as an authorization token, whether the charge is authorized or not, and an error code, if any. Finally, the method populates and returns the authorization status in a JAXB object.

Here is the method that uses StAX for performing the same authorization task. The parameter passed to the method is a String object, which is actually an XML document.

    public String authorizePaymentSTAX(String parameters) throws      CardServiceException {       try {           // Create the StAX reader to read the XML document           StringReader strReader = new StringReader(parameters);           XMLInputFactory staxFactory =              XMLInputFactory.newInstance();           staxFactory.setProperty(             XMLInputFactory.IS_VALIDATING, Boolean.FALSE);           XMLStreamReader xmlReader =              staxFactory.createXMLStreamReader(strReader); 

StAX parsers use an XMLStreamReader to read XML documents, and an XMLStreamWriter to write them back. The XMLInputFactory is used to configure the XMLStreamReader. The next block of code in the method traverses the XML document and reads from the elements of interest:

    // For sake of simplicity, we read only limited information     // about credit card and credit card user     String cardNumber= null;    String lastName = null;    while (xmlReader.hasNext()) {        if (xmlReader.isStartElement()) {            String sName = xmlReader.getLocalName();            if (sName.equals("cardNumber")) {                cardNumber = xmlReader.getElementText();            }            if (sName.equals("lname")) {                lastName = xmlReader.getElementText();            }         }         xmlReader.next();    }    xmlReader.close();  

The business logic in the application authorizes the charge on the card. Then the method creates the response XML document. In the code below, notice that an XMLOutputFactory object is used to create an XMLStreamWriter. The XMLWriter writes the response XML document. The web service response is sent back as a String object.

    // Emulate charge authorization    dao.authorizeCharge(cardNumber, lastName);        // Create response XML document    StringWriter strWr = new StringWriter();    XMLStreamWriter resvStatusWr =       XMLOutputFactory.newInstance().createXMLStreamWriter(strWr);    resvStatusWr.writeStartDocument();     resvStatusWr.writeStartElement(      "ns0", "AuthorizationStatus", "urn:CardService");     resvStatusWr.writeStartElement(      "ns0", "authorizationToken", "urn:CardService");    resvStatusWr.writeCharacters(dao.authorizationToken);    resvStatusWr.writeEndElement();     ...        resvStatusWr.writeEndDocument();        return strWr.toString(); 

Here is the method that uses DOM. The parameter to the method gives the root element of the XML document sent by the client. The method uses it to parse the document and gather the required information about the credit card and its user.

    public AuthorizeStatusDOM authorizePaymentDOM(     AuthorizePaymentDOM parameters) throws      CardServiceException {      try {          Element element = (Element)parameters.getAny();           // For sake of simplicity, we read only limited           // information about credit card and credit card user           Node cardNode = (            element.getElementsByTagName("cardNumber")).item(0);          String cardNumber =             cardNode.getFirstChild().getNodeValue();          Node lnameNode =             (element.getElementsByTagName("fname")).item(0);          String lastName =             lnameNode.getFirstChild().getNodeValue(); 

As before, the method calls the application's business logic to authorize the credit charge. Next, the method creates the response using a SOAPElement class. Notice that a SOAPFactory object is used to create the root element. Child elements are then added with authorization information.

    // Emulate charge authorization    dao.authorizeCharge(cardNumber, lastName);        SOAPFactory sf = SOAPFactory.newInstance();    SOAPElement root = sf.createElement(      "AuthorizationStatus","ns0","urn:CardService");    SOAPElement token = sf.createElement("authorizationToken");    token.addTextNode(dao.authorizationToken);    root.addChildElement(token);    ...        ObjectFactory of = new ObjectFactory();    AuthorizeStatusDOM status = of.createAuthorizeStatusDOM();    status.setAny(root);           return status; 

Compile the web service, package it as a WAR file, and deploy it

You need to compile the service implementation class as well as portable artifacts for the web service that were generated earlier by running wsimport on CreditCardService.wsdl. Next the classes need to be packaged into a WAR file along with the deployment descriptor for web services, sun-jaxws.xml. These steps are performed in the sample by an ant task with the target build.

Building the client

Here are the steps to build the web service client:

  1. Write the client class.
  2. Generate portable artifacts for web service execution.
  3. Compile the client.

Write the client class

A standalone web service client, CreditCardServiceTest.java, is packaged with the sample. You can find it in the src\client directory. The client calls the credit card web service to authorize payment on a credit card provided by the customer. The client sends credit card and card holder information contained in an XML document to the server. The client can process the XML document using JAXB, StAX or DOM, and in fact, uses all three technologies.

Here's the method in the client that calls the service using JAXB. A JAXB unmarshaller converts an XML document into a Java object. The client uses an instance of the Unmarshaller to unmarshal an XML document into a JAXB object for the authorization request. The client then makes a call to the web service.

    public void testAuthorizePaymentJAXB(     String authrequestXMLfile) throws Exception {         try {            // Get the unmarshaller to convert XML into Object            JAXBContext jc =               JAXBContext.newInstance("creditcard");            Unmarshaller u = jc.createUnmarshaller();             // Unmarshal the XML document into authorization             // request object            JAXBElement cardAuthorizationElement =               (JAXBElement)u.unmarshal(              new FileInputStream(authrequestXMLfile));            AuthorizationRequest cardAuthorizationRequest =               (AuthorizationRequest)              cardAuthorizationElement.getValue();            // Make web service call           AuthorizationStatus reply =              stubC.authorizePaymentJAXB(cardAuthorizationRequest); 

Notice that the response from the service is a JAXB authorization status object. Also, stubC is a proxy that is used to invoke methods on the service endpoint interface. It's used in all the XML handling methods in the client. The proxy is initialized in the constructor of the CreditCardServiceTest class.

As an alternative to using an XML document, the client could populate relevant JAXB objects and then make the service call. You can see this approach in the method testAuthorizePaymentJAXB() in CardServiceTest.java.

Here's the method in the client that calls the service using StAX. This method passes the XML document to the service in the form of a String object. The response from the service is also a String. The readStringFromFileRaw method is a utility method that reads an XML file and returns a String.

    public void testAuthorizePaymentSTAX(     String authrequestXMLfile) throws Exception {        // Read XML document into a string        String authRequest =           readStringFromFileRaw(authrequestXMLfile);        try {            // Make web service call             String reply =               stubC.authorizePaymentSTAX(authRequest); 

Finally, here is the method in the client that uses DOM to make the web service call. The utility method createElementMessage returns the document's root element after reading the XML file. The client uses the document's root element in the web service call. The response from the service can be displayed through DOM traversal APIs.

  public void testAuthorizePaymentDOM(String authrequestXMLfile)    throws Exception    {    // Get document root element    Element authRequest =       createElementMessage(authrequestXMLfile);    try {            // Populate authorization request object            ObjectFactory of = new ObjectFactory();             AuthorizePaymentDOM msg =               of.createAuthorizePaymentDOM();            msg.setAny(authRequest);             // Make web service call             AuthorizeStatusDOM reply =               stubC.authorizePaymentDOM(msg); 

Generate portable artifacts

Generate client-side portable artifacts using the WSDL on server. This is done in the sample using an ant task with the target build. Actually, when you call ant target build, it compiles both the server and client classes, including the generated artifacts. It also builds a deployable WAR file. Note that the client uses a JAXB binding configuration file, config-client.xml.

Running the sample

To run the sample:

  1. Start GlassFish by entering the following command:
           %J2EE_HOME%/bin/asadmin start-domain domain1 
    Ensure that the J2EE_HOME environment variable is set to the GlassFish install directory.

  2. Build the web service, the client, and needed artifacts, and package it into a WAR file by entering the following command:
           ant build 
  3. Deploy the application by entering the following command:
           ant deploy 
  4. Run the application by entering the following command:
           ant run 
    The command runs the application using all three XML handling technologies. You should see output that looks something like this:
           run:         [java] Calling Credit Card Service using JAXB         [java] Authorization token = 84706723         [java] Authorized = true         [java] Error code = 0         [java] Calling Credit Card Service using STAX         [java] <?xml version="1.0" ?><ns0:AuthorizationStatus>         <ns0:authorizationToken>39114069</ns0:authorizationToken>         <ns0:authorized>true</ns0:authorized><ns0:errorCode>0         </ns0:errorCode></ns0:AuthorizationStatus>         [java] Calling Credit Card Service using DOM         [java] authorizationToken = 66927959         [java] authorized = true         [java] errorCode = 0 
  5. Undeploy the application by entering the following command:
           ant undeploy 
  6. Delete all classes and the WAR file generated for the application by entering the following command:
           ant clean 

About the Author

Deep Singh is a staff member of Java Performance Engineering group at Sun Microsystems.

Back to Top

DEVELOPER ASSISTANCE
 

Need programming advice on Java EE? Try Developer Expert Assistance http://developers.sun.com/services/expertassistance/

Back to Top

Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
If you would like a reply to your comment, please submit your email address:
Note: We may not respond to all submitted comments.
Comments? Send your feedback on the Tech Tips: http://developers.sun.com/contact/feedback.jsp?category=newslet

Subscribe to the following newsletters for the latest information about technologies and products in other Java platforms:
  • Core Java Technologies Tech Tips. Get tips on using core Java technologies and APIs, such as those in the Java 2 Platform, Standard Edition (J2SE).
  • Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME).
You can subscribe to these and other Java technology developer newsletters or manage your current newsletter subscriptions on the Sun Developer Network Subscriptions page

IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:
http://www.sun.com/share/text/termsofuse.html
http://www.sun.com/privacy/
http://developer.java.sun.com/berkeley_license.html

ARCHIVES: You'll find the Enterprise Java Technologies Tech Tips archives at:
http://java.sun.com/developer/EJTechTips/index.html

© 2006 Sun Microsystems, Inc. All Rights Reserved. For information on Sun's trademarks see: http://sun.com/suntrademarks
Java, J2EE, J2SE, J2ME, and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.



Please unsubscribe me from this newsletter.


 
Comments: Post a Comment



<< Home
News, Articles, events from all over the world

My Photo
Name:
Location: India

Born on shraavana shudha chauthi of dundubhi naama samvaswara, Im kiran alias kini alias kiri bought up by loving parents. Being from agricultural family I have learnt plowing, carting but never learnt climbing trees. Now away from home I have lost touch with the agricultural skills.

ARCHIVES
January 2006 / February 2006 / March 2006 / April 2006 / May 2006 / June 2006 / July 2006 / August 2006 / September 2006 / October 2006 / November 2006 / December 2006 / April 2007 / May 2007 / June 2007 / July 2007 / August 2007 / September 2007 / October 2007 / November 2007 / December 2007 / January 2008 / February 2008 / March 2008 / April 2008 / May 2008 / June 2008 / July 2008 / August 2008 / September 2008 / October 2008 / November 2008 / December 2008 / January 2009 / February 2009 / March 2009 / April 2009 /


Powered by Blogger