Web services with Java
Distributed Systems SS03
RPC over XML
• Layered architecture based on TCP
• Bottommost layer is HTTP
• SOAP (XML) sits above it
• LOT of W3C standards and W3C drafts
describe it.
Reference implementation
• Sun JWSDK (Java Web Services Development
kit )
• Enables to test the newest technology for free
• Contains Tomcat (Apache-based webserver), Ant
(make utility) and several example applications
and JAX-RPC ( we will use this component),
JAXM (the message-based middleware).
• Installation and maintenance is quite hard! (About
6000 files in the tree, 60 MB disk-space required)
• Works under Windows and Linux (everything is
written in Java)
How to install it?
• Install J2SE 1.3.1 or better 1.4.x!
• Start the JWSDP installer!
• Follow the instructions to replace some
older files in the J2SE library tree
• Set the PATH variables
• Experiment with it!
Setting the environment variables
• Set JAVA_HOME to the J2SE‘s root
• Set TOMCAT_HOME and CATALINA_HOME
to the JWSDP‘s root
• Put the „bin“ directories into the search PATH
(don‘t forget to include ant‘s bin directory )
– PATH to JWSDP‘s Ant‘s bin directory should be at the
beginning! Otherwise things won‘t work
• Most problems with J2EE/JWSDP are caused by
wrong PATH and variable settings
Preparing the system
• Create a file, called build.properties in your
home-directory
– ~ on Unices
– C:\Dokumente und Einstellungen\yourName on
Windows systems
– It should contain the following 2 lines:
– username=your TOMCAT user name
– password=your TOMCAT password
– Look at the tomcat-users.xml file if you have forgotten
your user name and password
Starting/Stopping Tomcat
• $JWSDP_HOME/bin/startup.sh
• Install your web applications
• (Write them if necessary)
• You can access the Tomcat server on the
port 8080
– http://localhost :8080/yourApplication
• $JWSDP_HOME/bin/shutdown .sh
How to develop a web service
with JAX-RPC?
• Write only 2 classes. One class exposes the service
method signature, the other class should provide
implementation of the service
• Define an XML configuration file that contain
instructions to generate client-side and server-side
stubs required by JAX-RPC (necessary for the
Java-to-WSDL mapping tool)
• Define a web.xml file that specifies the
deployment descriptor for deployment in an
application server
• That‘s all! – and install („deploy“) them!
Our sample web service – the
interface
• The interface defining the service should
extend java.rmi.Remote
• Every method should throw a
java.rmi.RemoteException
• No constant declaration is allowed
• Only SOAP-able data types are supported
• We will see the SOAP-able
Primitive data types in JAX-RPC
• JAX-RPC uses the following type-mapping
– Boolean -> xsd:boolean
– Byte -> xsd:byte
– Double -> xsd:double
– Float -> xsd:float
– Integer (int) -> xsd:int
– Long -> xsd:long
– Short -> xsd:short
Supported Java standard-classes
• BigDecimal -> xsd:decimal
• BigInteger -> xsd:integer
• Calendat -> xsd:dateTime
• Date -> xsd:dateTime [broken]
• GregorianCalendar -> xsd:dateTime
• String -> xsd:string
• JWSDP supports more data types that can be used only
if all involved parties are using Java (Vector, Stack,
HashTable, etc.)
• Arrays of supported JAX-RPC types are also supported
Supported application classes
• Other, programmer defined classes are also
supported. They must adhere to some conventions
– They must have a public default constructor
– It must not implement the java.rmi.Remote interface
– Ist fields must be supported JAX-RPC types
– A public field cannot be final or transient
– A non-public field may have corresponding getter and
setter methods (JavaBeans coding convention)
Hello web service description
• The world‘s simplest distributed greeting
serviceJ
• Its input is a name (String)
• The result is a greeting in String form
• Implemented as a JAX-RPC web service
endpoint
The hello web service interface
package hello;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface HelloIF extends Remote {
public String sayHello(String s)
throws RemoteException;
}
A sample XML configuration file
for the hello service
<?xml version="1.0" encoding="UTF-8"?>
<configuration
xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<wsdl location="http://localhost:8080/hello -jaxrpc/hello?WSDL“ packageName="hello"/></configuration>
This file (config.xml) will be used to generate cliens/server
stubs/skeletons with the wscompile utility.
hello – implementation class
package hello ;public class HelloImpl implements HelloIF {
public String message = "Hello ";
public String sayHello(String s) { return message + s;
} }
Using wscompile(.sh/.bat) to
generate client stubs
• The hard way ....
~/jwsdp -1.1/jaxrpc- 1.0.3/bin/wscompile.sh -gen:client - d build/client/ hello –classpath
build/shared config.xml
– And then execute deployment, etc. etc. with the
manager login of your Tomcat server!
• The easy way:
– Download ds2003webservices.tar from the course page – Modify the war-path (use your directory instead of /home /itec/csb) – Start the command „kompajl“ to compile everything
– Start the command „ant run“ to execute the client
– If the paths are set correctly , the program will be deployed and run!
A client application of the service
import javax.xml.rpc.Stub; import java.util .Date; public class HelloClient {
public static void main(String[] args) { try {
Stub stub = createProxy (); HelloIF hello = ( HelloIF)stub ; System.out.println(hello.sayHello("Duke!")); } catch (Exception ex) {ex.printStackTrace();} }
private static Stub createProxy() {
return (Stub)(new MyHello _Impl(). // for JWSDP
getHelloIFPort()); //see jaxrpc -ri.xml!
} }
Client stub name
• The name of the client stub is not standardized
• JWSDP uses the file jaxrpc-ri.xml when contructing
the client stub
• Look at it! Here is an excerpt:
<endpointMapping
endpointName="MyHello"
• That ‘s why wscopile and we used MyHello for the
stub‘s classname.
• wscompile creates client stubs based on their WSDL
description („downloaded“ from the Tomcat server)
Implementation-specific parts
• The file config.xml is used by JWSDP only
• jaxrpc-ri.xml too
• Stub and tie (server skeleton ) class names
• The tools (wscompile,wsdeploy,deploytool)
• Support for collections as parameters and return
values
• (Using JAX- RPC with J2EE is not the same as
with JWSDP)
• We use the latest version (1.1) of JWSDP
Common errors
• The paths are not set
• An older version of „ant“ is in the PATH before a
newer one
• Tomcat is not running during compilation time
(remember: WSDL descriptions stored in WAR
files are accessed during compilation)
• HTTP -specific response codes:
– 404: resource unavailable
– 401: password required (does the file named
build.properties contain the right password?)
SOAP on the wire – request hdr
localhost.37408 > localhost.http-alt:
POST /hello-jaxrpc/hello HTTP/1.1 Content-Type: text/xml; charset="utf-8" Content-Length:477
SOAPAction : ""
User-Agent:Java/1.4.1_02 Host: localhost:8080
Accept: text/html, image/gif, image/jpeg , *; q=2, */*; q=2
Connection : keep -alive
SOAP on the wire – request body
<?xml.version="1.0" encoding ="UTF-8"?> <env:Envelope xmlns:env="http:// schemas.xmlsoap.org/soap/envelop e/" xmlns:xsd="http:// www.w3.org/2001/XMLSchema" xmlns:xsi="http:// www.w3.org/2001/XMLSchema-instance" xmlns:enc="http:// schemas.xmlsoap.org/soap/encoding/ " xmlns:ns0="http:// com.test/wsdl/MyHello" env:encodingStyle="http:// schemas.xmlsoap.org/soap/e ncoding/"> <env:Body><ns0:sayHello ><String_1 xsi:type="xsd:string">Duke!</String_1> </ns0: sayHello ></env:Body></ env:Envelope >
SOAP on the wire – reply hdr
localhost.http-alt > localhost.37408
HTTP/1.1 200 OK
Content-Type: text/xml; charset="utf-8"
SOAPAction: ""
Transfer-Encoding: chunked
Date: Sun, 01 Jun 2003 16:39:54 GMT
Server: Apache Coyote HTTP/1.1 Connector
SOAP on the wire - reply body
<?xml.version ="1.0".encoding ="UTF- 8"?><env :Envelope
xmlns:env="http://schemas .xmlsoap. org /soap/ envelope/" xmlns:xsd="http://www.w3. org /2001/ XMLSchema "
xmlns:xsi="http://www.w3. org /2001/ XMLSchema -instance" xmlns:enc="http://schemas .xmlsoap. org /soap/ encoding/" xmlns:ns0="http://com.test/wsdl /MyHello"
env: encodingStyle="http://schemas. xmlsoap.org/ soap /enco ding /">
<env :Body><ns0:sayHelloResponse >
<result xsi:type ="xsd: string ">Hello Duke!</ result> </ns0:sayHelloResponse ></ env :Body></env: Envelope>
And where are WSDL&UDDI?
• WSDL descriptions are automagically
generated by the wscompile tool in JWSDP
• They are stored in .war files (WEB
application archives)
• Take a look at the file hello-jaxrpc.war
– Unzip it
– Look for WEB-INF/MyHello .wsdl
• See the next 3 slides about the generated WSDL file
<?xml version="1.0" encoding ="UTF-8"?> <definitions name="MyHello"
targetNamespace="http://com.test/wsdl/MyHello" xmlns:tns="http://com.test/wsdl/MyHello" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/ XMLSchema" xmlns:soap ="http://schemas.xmlsoap .org/wsdl/soa p/">
<types/>
<message name="HelloIF_sayHello">
<part name="String_1„ type="xsd:string"/> </message>
<message name="HelloIF_sayHelloResponse"> <part name="result " type ="xsd:string "/> </message>
<portType name ="HelloIF"> <operation name="sayHello" parameterOrder="String_1"> <input message ="tns:HelloIF_sayHello"/>
<outputmessage="tns:HelloIF_sayHelloResponse"/> </operation></portType > <binding name="HelloIFBinding" type="tns:HelloIF"> <operation name="sayHello"> <input> <soap:body encodingStyle="http:// schemas.xmlsoap.org/soap / encoding/" use="encoded" namespace="http://com.test/wsdl/MyHello"/></inp ut> <output> <soap:body encodingStyle="http:// schemas.xmlsoap.org/soap / encoding/" use="encoded" namespace="http://com.test/wsdl/MyHello"/></out put> <soap:operation soapAction=""/></operation> <soap:binding transport="http://schemas.xmlsoap.org/soap/http " style="rpc"/></binding>