# Presentation: 028039

## Java TrainingIntroduction To Web Services

- Written by Jeff Smith
- (portions borrowed from Apache Axis website)

## The Problem

- Here is the age old IS/IT problem—how can I have a program (and perhaps multiple instances of it) running in one centralized place and accessible by other programs running at other places?
- Older Technologies
- Client/Server programming was big in the ‘90s. Simplest example of this is a client program that communicates with a database (perhaps Oracle), that executes code on a server
- CORBA
- RMI
- Now, Web Services...

## Web Services Solution

- Web Services are programs that can be invoked by other pograms (using a well defined protocol) over a network (e.g., the internet)
- Web Services are platform independent, programming language independent, and allow loose coupling between software systems
- What is the difference between a web application and a Web Service?
- Web application supports *user-to-program* interaction
- Web Service supports *program-to-program* interaction

## Web Services and SOAs -1

- Web Services are the building block of most SOA (Service Oriented Architectures)
- SOAs are loosely coupled systems of independent software agents
- Think of it this way—where a Java program is a collection of Java classes that work together in a single JVM, an SOA system is a collection of loosely coupled programs (Web Services) that colloborate over a network
- For example, ESRL might create an SOA ...

## Web Services and SOAs -2

- If these web services “building
- blocks” were available, imagine
- how much easier it would be to
- write some new NOAA apps!
- Moreover, developers could write
- their applications in any
- language and for any platform
- Each web service could be easily
- tested and maintained
- independently

- File/Data Finder-searches filesystems, returns path

- WMS (Web Map Service)
- -given filepath and Lat/Lon region,
- returns data as PNG image

- WFS (Web Feature Service)
- -given filepath and Lat/Lon region,
- returns data as GML

- Future ESRL Web Services?

- WCS (Web Coverage Service)
- -given filepath and Lat/Lon region,
- returns binary data

## Web Services Messaging

- How can you send messages to a Web Service?
- Two popular architectures incorporate either SOAP (Simple Object Access Protocol), which is something of a misnomer since it isn’t really that simple, and REST (Representational State Transfer)
- Regardless of whether you use SOAP or REST, your web service will probably be accessed via HTTP

## REST -1

- REST was defined by Roy Fielding in 2000 (Roy Fielding was a principal author of the HTTP protocol)
- Typical definition--a simple interface for transmiting data over HTTP without requiring a messaging layer such as SOAP or session tracking via Cookies
- Key point – REST is stateless (like HTTP)
- If a system employs REST, it is sometimes called RESTful

## REST -2

- REST advantages
- Easily supports caching (improving performance)
- Improves scalability (since state doesn’t need to be maintained, you can cluster serveral RESTful servers)
- Doesn’t require software tools to encode/decode SOAP messages
- Simpler to learn than SOAP

## SOAP -1

- From W3C – *“SOAP is a lightweight protocol for exchanging structured information in a decentralized, distributed environment. It is an XML based protocol that consists of three parts: an envelope that defines a framework for describing what is in a message and how to process it, a set of encoding rules for expressing instances of application-defined datatypes, and a convention for representing remote procedure calls and responses.**”*
- SOAP advantages
- Rigid - type checking, adheres to a contract. SOAP services are defined by Web Services Description Language (WSDL) files, which contain all the information required to make a request.
- Development tools ease creation of WSDL

## Apache AXIS

- Apache Axis2 1.2 implements both SOAP and REST
- (don’t ask me why they call it Axis2, version 1.2)
- You can download Axis from the Apache website here:http://ws.apache.org/axis2/
- Or you can download it from the Java Zone Downloads pagehttp://www-ad.fsl.noaa.gov/ac/javazone/Downloads.html
- You need Java 1.4
- You need Ant 1.65 or later (to build samples or Axis2.war file)

## Installing AXIS -1

- Locate the Ant build file (build.xml) inside the webapp directory (e.g. c:\axis2\webapp, or $AXIS2_HOME/webapps folder)
- Run the Ant build by executing "ant create.war" inside the $AXIS2_HOME/webapps folder
- Copy the newly created axis2.war file to your Tomcat webapps directory (e.g. c:\tomcat5\webapps)
- You can test your AXIS installation by starting up Tomcat and then typing in this URL:http://localhost:8080/axis2/

## Installing AXIS -2

- You should see the following at http://localhost:8080/axis2/

## AXIS Clients/Classpath

- To write a Java client program that will invoke an AXIS web service, you need to add several jars to your classpath (for example, in Eclipse, for development purposes)
- Note: you’ll find these files in the [axis-install-dir]/lib directory

## What is WSDL?

- Web Services Description Language
- WSDL is an XML-formatted language used to describe a Web service's capabilities as collections of communication endpoints capable of exchanging messages.
- Basically, it describes what methods are available, what parameters are passed in, and what the return type is
- WSDL is an integral part of UDDI, an XML-based worldwide business registry. WSDL is the language that UDDI uses. WSDL was developed jointly by Microsoft and IBM
- Axis2 does not require WSDL files (although supplying a WSDL file will allow you to specify more web service options)

## WSDL and AXIS -1

- Axis supports WSDL in three ways:
- With Axis web services, users can access your service's URL with a standard web browser and by appending "?WSDL" to the end of the URL, they will obtain an automatically-generated WSDL document which describes your service
- Axis provides a "WSDL2Java" tool which will build Java proxies and skeletons for services with WSDL descriptions
- Axis provides a "Java2WSDL" tool which will build WSDL from Java classes
- When you access the web service URL via a browser, you see a generic message indicating that the endpoint is an Axis service, and that you should usually access it using SOAP.
- If you tack on "?wsdl" to the end of the URL, Axis will automatically generate a service description for the deployed service, and return it as XML in your browser** **

## WSDL and AXIS -2

## Simplest Web Service With AXIS -1

- The simplest web service example with AXIS would be to use “Instant Deployment” (no WSDL required)
- write a single Java class called HelloWebService.java
- make some method(s) public
- copy the .java file to your web application directory
- rename the .java file to .jws
- You can access the WSDL contents of the Web service as *http://localhost:8080/mywebapp/HelloWebService.jws?wsdl*
- That’s all there is to it!

## Simplest Web Service With AXIS -2

- Limitations
- Creating web services this way limits you to common Java classes such as java.util.Date (an exact mapping list is available on the Axis Web site) as method arguments and method return types.
- You cannot use your custom made classes (also sometimes referred to as Value Objects or VOs) as method parameters or return types
- But if you don’t need to return custom objects (classes) and don’t need advanced deployment options, this is an easy way to deploy a web service

## Advanced Deployment With AXIS -1

- Advanced deployment permits the use our own classes as parameter values and return types. Value Objects or VOs are generally used to represent the data that needs to be passed on via methods.
- Write your Java Web Service class(s) that can return your custom data types (classes)
- Compile the classes and place the generated .class files in the WEB-INF/classes folder of your Web application (or put them in a WAR file)

## Advanced Deployment With AXIS -2

- With Axis1.x, you modify the *server-config.wsdd* file and add a ***service*** element that will define your Web service.
**<service name=“WeatherService" provider="java:RPC">**
**  ****<parameter name="allowedMethods" value="*"/> **
**  ****<parameter name="className“**
**                   ****value=“gov.noaa.WeatherFinder"/> **
**  ****<beanMapping**
**      ****languageSpecificType="java:noaa.WeatherObs“**
**      ****qname="ns1:WeatherObs" xmlns:ns1="urn:noaa.gov"/> **
**</service>**** **

## Advanced Deployment With AXIS -3

- With Axis2.x, each has a services.xml file which will inform Axis2 about the service.
**<service>**
**  ****<parameter name="ServiceClass“**
**         ****locked="false">SimpleService</parameter>**
**  ****<operation name="echo">**
**    ****<messageReceiver ****class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>****</operation> **
**</service>**
- This "service" element encapsulates the information about a single
- service. Within the "service" element there should be a parameter
- specifying the service implementation Java class.

## Java Beans Classes

- If your web service returns a custom bean class (for example a WeatherObs object), remember to follow the Java Bean specification
- Getters
- Setters
- no argument constructor (you can also define a constructor that takes arguments, but you MUST have a no argument constructor as well)
- After customizing the server-config.wsdd file, you can access your Web service's WSDL by using URL, for example, as
*http://localhost:8080/mywebapp/services/WeatherService?wsdl*

## HelloWorld Service -1

- We are going to create a simple “HelloWorld” style web service in a directory called “HelloWebService”. First, create this directory structure:

## HelloWorld Service -2

- The services.xml file will go in the META-INF directory

## HelloWorld Service -3

- Place this Java file in the HelloWorldService directory:
**public class HelloWorldWebService**
**{**
**  ****/****
**   ***** This echoHello method will be exposed as the **
**   ***** operation of the web service**
**   *****/**
**  ****public String echoHello(String personName) **
**  ****{**
**    ****return("Hello " + personName);**
**  ****}**
**}**

## HelloWorld Service -4

- Place this services.xml file in the META-INF directory
**<service>**
** ****<parameter name="ServiceClass"**
**             ****locked="false">****HelloWorldWebService**
** ****</parameter>**
** ****<operation name="****echoHello****">**
**    ****<messageReceiver**
**   ****class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>**
** ****</operation>    **
**</service>**
- For more information about services.xml, go here:
- http://ws.apache.org/axis2/0_93/axis2config.html#service

## HelloWorld Service -5

- We’re going to create the HelloWorldWebService.aar file (basically a special jar file). Note: the file name before ".aar" should be the same name as your web service class
- First, CD to the HelloWebService directory and compile your class like so
**javac HelloWorldWebService.java -d temp/**
- Second, CD to the temp directory and build your .aar
**jar -cvf HelloWorldWebService.aar *** ** **

## HelloWorld Service -6

- Now we’ve got our .aar file

## HelloWorld Service -7

- Deploy your web service by copying it to the [tomcat]/webapps/axis2/WEB-INF/services directory

## HelloWorld Service -8

- Restart Tomcat and go to http://localhost:8080/axis2/services/listServices

## Intro to Stubs -1 

- Axis2 includes a WSDL2Java tool to generate the client side stubs from a WSDL to invoke the web service. Go to the Axis bin directory (e.g. C:\axis2-1.2\bin)
- A Stub class implements the SDI (Service Definition Interface**)**
- Its name is the binding name with the suffix "Stub"
- It contains the code which turns the method invocations into SOAP calls using the Axis Service and Call objects. It stands in as a **proxy** for the remote service, letting you call it exactly as if it were a local object
- With stubs, you don't need to deal with the endpoint URL, namespace, or parameter arrays which are involved in dynamic invocation via the Service and Call objects. The stub hides all that work for you

## Intro to Stubs -2

- SDI is the interface you use to access the operations on the service. For example, given the WSDL:
**<message name="empty"> **
**<message name="AddEntryRequest"> **
**  ****<part name="name" type="xsd:string"/> **
**  ****<part name="address" type="typens:address"/>**
**</message> **
**<portType name="****AddressBook****"> **
**  ****<operation name="****addEntry****"> **
**    ****<input message="tns:AddEntryRequest"/> **
**    ****<output message="tns:empty"/> **
**  ****</operation> **
**</portType>**** **

## Intro to Stubs -3

- WSDL2Java will generate this Java stub:** **
**public interface ****AddressBook**** extends java.rmi.Remote **
**{ **
**  ****public void ****addEntry****(String name, Address address) throws java.rmi.RemoteException; **
**}**** **

## Intro to Stubs -4

- Normally, a client program would not instantiate a stub directly. It would instead instantiate a service locator and call a get method which returns a stub. This locator is derived from the service clause in the WSDL. WSDL2Java generates two objects from a service clause. For example, given the WSDL:
- <service name="AddressBookService">
-   <port name="AddressBook" binding="tns:AddressBookSOAPBinding">
-     <soap:address location="http://localhost:8080/axis/services/AddressBook"/>
-   </port>
- </service>

## Intro to Stubs -5

- WSDL2Java will generate the service interface:
- public interface AddressBookService extends javax.xml.rpc.Service
- {
-   public String getAddressBookAddress();
-   public AddressBook getAddressBook() throws javax.xml.rpc.ServiceException;
-   public AddressBook getAddressBook(URL portAddress)
-   throws javax.xml.rpc.ServiceException;
- }
- WSDL2Java will also generate the locator which implements this interface:
- public class AddressBookServiceLocator extends org.apache.axis.client.Service
-   implements AddressBookService
- {
-  ...
- }** **

## Intro to Stubs -6

- The service interface defines a get method for each port listed in the service element of the WSDL.
- A typical usage of the stub classes would be as follows:
- public class Tester
- {
-   public static void main(String [] args) throws Exception
-   {
-     AddressBookService service = new AddressBookServiceLocator();
-     // Now use the service to get a stub which implements the SDI.
-     AddressBook port = service.getAddressBook();
-     Address address = new Address(...);
-     port.addEntry("Russell Butek", address);
-   }
- }

## HelloWorld Client Using Stubs -1

- Under Windows (all of this is one command)...
- WSDL2Java.bat -uri http://localhost:8080/axis2/services/
- HelloWorldWebService?wsdl -o c:\CoreJava\jeff\HelloWebService
- Under Linux (all of this is one command)...
- $ sh WSDL2Java.sh -uri http://localhost:8080/axis2/services/
- HelloWorldWebService?wsdl -o /path/to/my/client/code/
- You can import the stub file into your client project to invoke your
- web service. For more information, see
- http://ws.apache.org/axis/java/user-guide.html

## HelloWorld Client Using Stubs -2

- Your command window should look something like this

## HelloWorld Client Using Stubs -3

- You should see some directories and files created. You can use the “Stub” class to invoke the "echoHello" operation of the service.
- This is a bit complicated—just look at those filenames!

## HelloWorld Client Using Stubs -4

- You could  create a new Client.java class which uses the stub class. For simplicity, place the Client.java file in the same package as the generated code (i.e.org.apache.ws.axis2) and save it along with the other generated code.

## HelloWorld Client Using Stubs -5

- package org.apache.ws.axis2;
- import org.apache.ws.axis2.HelloWorldWebServiceHelloWorldWebServiceHttpportStub.EchoHelloResponse;
- public class Client
- {
-   public static void main(String[] args) throws Exception
-   {
-       HelloWorldWebServiceHelloWorldWebServiceHttpportStub stub =
-          new HelloWorldWebServiceHelloWorldWebServiceHttpportStub();
-         //Create the request using the stub
-       HelloWorldWebServiceHelloWorldWebServiceHttpportStub.EchoHello request =
-           new HelloWorldWebServiceHelloWorldWebServiceHttpportStub.EchoHello();
-       request.setParam0("Jeff");
-         //Invoke the service
-       EchoHelloResponse response = stub.echoHello(request);
-        //dump the web service response to the console
-       System.out.println("Response : " + response.get_return());
-     }
- }

## Simple HelloWorld RPC Client -1

- You can build a client by creating a ServiceClient object, building your SOAP XML payload, and then sending that SOAP message to your web service
- A simpler way (in my opinion) of building a SOAP client is to is to write a simple RPCServiceClient
- You don’t need to build any stub files this way (although you also don’t get any type checking that stubs offer)
- We’ll dynamically invoke our web service by specifying the EndpointRefererence in our client code
- Behind the scenes, the RPCServiceClient is generating the SOAP (XML) message required to invoke our web service

## Simple HelloWorld RPC Client -2

## Simple HelloWorld RPC Client -3

- import javax.xml.namespace.QName;
- import org.apache.axis2.AxisFault;
- import org.apache.axis2.addressing.EndpointReference;
- import org.apache.axis2.client.Options;
- import org.apache.axis2.rpc.client.RPCServiceClient;
- public class HelloWorldClient
- {
-   public static void main(String[] args) throws AxisFault
-   {
-     RPCServiceClient serviceClient = new RPCServiceClient();
-     Options options = serviceClient.getOptions();
-     EndpointReference targetEPR = new EndpointReference(
-              "http://localhost:8080/axis2/services/HelloWorldWebService");
-     options.setTo(targetEPR);

## Simple HelloWorld RPC Client -4

-     //specify “http://ws.apache.org/axis2/xsd” if using default package
-     QName opEchoHello = new QName("http://ws.apache.org/axis2/xsd",
-                                                                "echoHello");
-     Object[] opEchoHelloArgs = new Object[] { "jeff" };
-     Class[] returnTypes = new Class[] { String.class };
-     Object[] response =
-       serviceClient.invokeBlocking(opEchoHello, opEchoHelloArgs, returnTypes);
-     String result = (String) response[0];
-     if (result == null)
-       System.out.println("No response from web service!");
-     else
-       System.out.println(result);
-   }
- }

## Simple HelloWorld RPC Client -5

- To compile HelloWorldClient.java, you’ll need to include the jar files in the Axis2-1.2/lib directory in your classpath:
**javac -extdirs C:\axis2-1.2\lib\ HelloWorldClient.java**
- To run HelloWorldClient, you’ll need to include these same jars in your runtime classpath like so
**java -Djava.ext.dirs=C:\axis2-1.2\lib\ HelloWorldClient**

## QName

- QName represents a **Q**ualified **N**ame as defined in the XML specifications** **
- it includes a namespace URI (or address)
- and the “local part” (or method name)
- Go here to learn more about qualified names:
- http://www.w3.org/TR/REC-xml-names/#ns-qualnames

## Creating A Web Service With Packages -1

- The simple HelloWorld web service we looked at was in the default package
- If you use your own package (a good idea), you’ll need to build your .aar file a little differently
- Copy your class files directory tree to your temp directory

## Creating A Web Service With Packages -2

- Delete the .java files from the new copy under temp (so you are just left with the .class files)

## Creating A Web Service With Packages -3

- Your META-INF directory should still contain your services.xml file

## Creating A Web Service With Packages -4

- services.xml file should now specify the full package name
- <service name="WeatherFinderService">
-    <Description>Search for weather data by city</Description>
-    <parameter name="ServiceClass“
-       locked="false">gov.noaa.webservice.WeatherFinderService</parameter>
-    <operation name="findByCity">
-      <messageReceiver
-          class="org.apache.axis2.rpc.receivers.RPCMessageReceiver"/>
-    </operation>
- </service>
- Note: I discovered that Description has to start with a capital “D” or else it isn’t picked up by the listServices (a bug they will no doubt fix)

## Creating A Web Service With Packages -5

- QName in your Java client program should now specify the web service class package too, in reverse order
**//if your web service package is gov.noaa.webservice**
**QName opFindByCity = new**
**  ****QName("****http://webservice.noaa.gov/xsd****", "findByCity");**

## Creating A Web Service With Packages -6

- Create your JAR file like you did before. CD to the temp directory and build your .aar
**jar -cvf WeatherFinderService.aar *** ** **

- Next copy your .aar file to the [tomcat]/webapps/axis2/WEB-INF/services directory

## Creating A Web Service With Packages -7

- Restart Tomcat and list the services in Axis2

## Development Tips

- If your web service returns a custom object (ie a java bean), you must implement a no argument constructor)
- Look at the Tomcat console for your debug messages and error messages. Also look at it to make sure your web service loads without error!

## HelloWorld Exercise -1

- Create the HelloWorld web service and deploy it to Tomcat
- Write a RPCServiceClient to invoke and test your web service

## WeatherFinderService Exercise -2a

- Write a WeatherFinderService web service that looks up weather information for a city (by name) and returns this information as a custom object
- For example, you could have classes called WeatherFinderService and a Java bean class called CityWeatherData
- When invoked, your web service should read this information out of a text file

## WeatherFinderService Exercise -2b

- Denver,88.5,40.2,36.7
- San Antonio,98.5,61.5,16.7
- New York,89.5,70.2,76.3
- Los Angeles,81.5,44.6,31.1
- Cheyenne,78.5,20.2,15.5
- Boston,86.5,45.3,56.2
- Test your web service with a RPCService client by having your client request the weather for ‘Denver’, ‘Los Angeles’, and ‘Boston’ and display the results to the console.
- Extra: Create an ant script (build.xml) to compile and deploy
- your web service

## Axis Generated WSDL -1

**QName**

**method name and parameter**

**method return type**

**return type defined**

## Axis Generated WSDL -2

**SOAP 1.1 binding**

**SOAP 1.2 binding**

## Axis Generated WSDL -3

**HTTP binding**

## HttpConnection and REST -1

- WSDL 2.0 HTTP binding marries REST with web services.
- So basically, you can design your web services to support plain old XML (POX) interactions with services over basic HTTP operations like GET, POST, PUT, and DELETE
- We’ll create an example that does an HTTP GET to our WeatherFinderService
- You can think of it this way--since our web service is accessible via simple http, we can invoke it by writing a client that just retrieves the XML from a URL
- Note this client could be written in any language and could access our web service over an intranet, or from across the world via the internet

## HttpConnection and REST -2

- As we saw in the WSDL that Axis2 generated, it automatically creates an HTTP binding for us, making it easy for us to write a simple, RESTful client
- To learn more about defining HTTP bindings in WSDL, there is a good article on IBM DeveloperWorks:
- http://www.ibm.com/developerworks/webservices/library/ws-rest1/
- The next slide shows you how to invoke your web service using HTTP binding and a web browser...

## HttpConnection and REST -3

**web service response as XML**

- You can invoke your web service using HTTP GET (no SOAP message required). The response will be XML

## Http Connections in Java

*A little refresher example on connecting to URLs in Java:*
- URL url = **new** URL(“http://www.wrfportal.org/index.html”);
- URLConnection urlCon = url.openConnection();  //connect to this URL
- //use the urlCon’s InputStream to create a BufferedReader
- InputStream inputStream = urlCon.getInputStream();
- InputStreamReader isr = **new** InputStreamReader(inputStream);
- BufferedReader bufReader = **new** BufferedReader(isr);
- String line = **null**;
**while** ((line = bufReader.readLine()) != **null**)  //read lines from URL until null
-    System.out.println(line + "\n");
- bufReader.close();  //close the BufferedReader for this urlCon InputStream

## XML -1

- Many web services return data in the form of XML
- There are a number of ways to encode and decode XML documents in Java
- SAX (Simple API for XML) enables you to process a document while it is being read, so your program doesn’t have to wait until the entire document is received before starting to process it
- With DOM (Document Object Model), data is stored in a tree-like structure (object) which mirrors the structure of the XML document. DOM can be a bit simpler conceptually (since it isn’t event driven like SAX), and is more flexible because your Java program can easily modify data in the “tree”. JDOM is an implementation of DOM for Java

## XML -2

- Use SAX when you need to process huge XML files and want to conserve memory.
- SAX also tends to be faster
- Use JDOM when the XML is relatively small and/or you need to modify it at run time
- JDOM is easy to use
- JDOM implementation is available here:http://www.jdom.org/
- Add jdom.jar and xerces.jar to your classpath (you can download them from the Java Zone downloads page)
- Next slide shows an example using JDOM

## XML -3

**import java.io.*; ****import org.jdom.*;**** **
**import ****org.jdom.input.*; import org.jdom.output.*;**** **
**public class XMLPrinter **
**{ **
**  ****public static void main(String[] args) throws Exception**
**  ****{ ****// Assume filename argument **
**   ****String filename = args[0]; **
**   ****try **
**   ****{ ****// Build the document with SAX and Xerces**
**     ****SAXBuilder builder = new SAXBuilder(); **
**     ****Document doc = builder.build(new File(filename));**
**     ****// Output to console, use standard formatter**
**     ****XMLOutputter fmt = new XMLOutputter(); **
**     ****fmt.output(doc, System.out); **
**  ****} **
**}**** **

## XML -4

- This code iterates through an incoming stream of XML from our WeatherFinderService and dumps results to the console
-  SAXBuilder builder = new SAXBuilder();
-  Document doc = builder.build(inputStream);
-  Element rootElement = doc.getRootElement();
-    //first element is “return” value
-  Element returnElement =  (Element)rootElement.getChildren().get(0);
-  List namedChildren = returnElement.getChildren();
-  for (Iterator it = namedChildren.iterator(); it.hasNext(); )
-  {
-     Element element = (Element)it.next();
-     System.*out*.println(element.getName() + "=" + element.getValue());
-  }

## XML -5

- Console Results:
**cityName=Denver**
**cloudCoverPct=36.7**
**relativeHumidityPct=40.2**
**temperatureDegFah=88.5**

## RESTful Web Service Client Exercise

- Create a simple Java class that connects to your WeatherFinderService using HTTP
- Issue a request to your web service for the weather in several cities, and display the results in the system console
- You can either dump the XML as simple text, or you can use JDOM to build a DOM object representing your XML

## Summary -1

- We’ve just scratched the surface of web service possibilities and technologies
- It is fairly easy to create an Axis2 web service by writing a POJO (plain old Java class) with public method(s) and which returns values as Java beans
- define a services.xml file
- Archive it as an .aar (Axis archive file)
- Since Axis2 supports SOAP and REST (as well as HTTP bindings), we can write clients using stubs, RPCs, or by writing simple HttpConnection clients
- There are other Java XML libraries such as JAXP that offer more advanced capabilities