Title: Labo SOAP
1Labo SOAP
- Dinsdag 24 maart 2005
- Peter.Demeester_at_kahosl.be
2References
- Java and Soap, Robert Englander, OReilly
(0-596-00175-4) - Programming Web Services with SOAP, James Snell,
Doug Tidwell and Pavel Kulchenko, OReilly
(0-596-00095-2) - Writing a Client Application using Apache SOAP
(http//www.xmethods.net/gettingstarted/apache.htm
l) - The Web services (r)evolution (http//www-106.ibm.
com/developerworks/library/ws-peer2/) - Making Apache SOAP Invocations using SMTP
(http//ws.apache.org/soap/faq/faq_chawke_smtp.htm
l) - Setting up Apache Tomcat and a Simple Apache SOAP
Client for SSL Communication (http//ws.apache.org
/soap/docs/install/FAQ_Tomcat_SOAP_SSL.html)
3Soap installation
- See http//ingenieur.kahosl.be/vakgroep/it/onderwi
js/ModBest/soap.htm
4First there was
5XML-RPC?
- It's a spec and a set of implementations that
allow software running on disparate operating
systems, running in different environments to
make procedure calls over the Internet. It's
remote procedure calling using HTTP as the
transport and XML as the encoding. XML-RPC is
designed to be as simple as possible, while
allowing complex data structures to be
transmitted, processed and returned.
6XML-RPC
7Apache XML-RPC
- Java implementation of XML-RPC
- Client class
import org.apache.xmlrpc. XmlRpcClient xmlrpc
new XmlRpcClient("http//localhost8080/") Ve
ctor params new Vector () params.addElement
("some parameter") // this method returns a
string String result (String) xmlrpc.execute
("method.name", params)
8Server class
- import org.apache.xmlrpc.
-
- WebServer webserver new WebServer(port)
- webserver.addHandler ("examples",
someHandler)
9Exercise
- Write handler that allows to calculate sum of two
integers - Write server
- Write client
10Allowed types
- See http//ws.apache.org/xmlrpc/types.html
11SOAP
12SOAP
Service Provider
Service Requester
HTTP Server
SOAP Dispatch
?
SOAP request/response messages
Underlying implementation
13SOAP
- SOAP as RPC (message contains a method name
arguments) extends OO to web-based remote objects - SOAP can also be used for exchanging documents
containing XML data - We will concentrate on RPC
- Through supporting web services (in SOAP)
integration within an enterprise and with
external business partners
14SOAP
- Use of SOAP allows software processes to change
without requiring changes to the other party, of
course as long as the request and response
message do not change - Ex 1st implementation of service provider can be
thin wrapper around legacy code. When the new
code is ready the change is invisible to users of
the service - If a required service is not available or if
another provider has a better price service
requester can choose among compatible service
offerings
15What is SOAP?
- SOAP is a loosely coupled protocol
- Lightweight (minimal amount of overhead), simple
(to use, not necessarily to write) - Over HTTP SMTP, no problems with firewalls
- SOAP is a minimal set of conventions for invoking
code using XML and HTTP - SOAP is an Internet-friendly alternative to
Microsoft's DCOM, Sun's RMI, and OMG's CORBA/IIOP
16SOAP structure
SOAP Message
HTTP HEADER
Envelope
Header
XML
Body
17SOAP envelope
- SOAP envelope is analogous to envelope of a
letter - Supplies info about
- Message that is being encoded in SOAP payload
- Including data relating to the sender and
recipient - Details about the message
18SOAP envelope
- Header of an envelope specifies how a message
must be processed - Before an application goes forward with
processing a message - application can determine information about a
message (including whether it will even be able
to process the message) (SOAPAction) - A SOAP message can also include the encoding
style (assists the recipient in interpreting the
message)
19SOAP envelope request
- ltSOAP-ENVEnvelope xmlnsSOAP-ENV"http//schem
as.xmlsoap.org/soap/envelope/
xmlnsxsi"http//www.w3.org/1999/XMLSchema-instan
ce xmlnsxsd"http//www.w3.org/1999/XMLSchema"
gt ltSOAP-ENVBodygt ltns1getRate
xmlnsns1"urndemo1exchange"
SOAP-ENVencodingStyle
"http//schemas.xmlsoap.org/soap/encoding/"gt ltco
untry1 xsitype"xsdstring"gtUSAlt/country1gt ltcou
ntry2 xsitype"xsdstring"gtjapanlt/country2gt
lt/ns1getRategt lt/SOAP-ENVBodygt - lt/SOAP-ENVEnvelopegt
20SOAP envelope response
- ltSOAP-ENVEnvelope xmlnsSOAP-ENV"http//schem
as.xmlsoap.org/soap/envelope/
xmlnsxsi"http//www.w3.org/1999/XMLSchema-instan
ce xmlnsxsd"http//www.w3.org/1999/XMLSchema"
gtltSOAP-ENVBodygt ltns1getRateResponse
xmlnsns1"urndemo1exchange" SOAP-ENV
encodingStyle "http//schemas.xmlsoap.org/s
oap/encoding/"gt - ltreturn xsitype"xsdfloat"gt144.52lt/returngt lt
/ns1getRateResponsegtlt/SOAP-ENVBodygt - lt/SOAP-ENVEnvelopegt
21SOAP envelope
- Encoding is specified within envelope
- Allows application to determine whether it can
read the incoming message (using the value of the
attribute encodingStyle)
22Encoding
- Second major element is simple means of encoding
user-defined data types (in theory!) - In XML-RPC encoding can only occur for a
predefined set of data types - With SOAP you can use XML Schema to specify new
data types (using complexType) and these new
types can be easily represented in XML as part of
a SOAP payload
23Encoding
- Because of this integration with XML Schema
encode any data type in a SOAP message that you
can logically describe in XML Schema (see later)
24SOAP Client in Apache SOAP
25Writing a Client application
- Importing packages
- //Required due to use of URL class, required by
Call //class - import java.net. //Required due to use of
Vector class import java.util. //Apache SOAP
classes used by client import org.apache.soap.uti
l.xml. import org.apache.soap. import
org.apache.soap.rpc.
26Writing a Client application
- Following line sets the default Encoding style to
be the standard SOAP encoding - call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC
) - Following line sets the Target Object URI, which
can be thought of as the object interface
identifier - call.setTargetObjectURI ("urnxmltoday-airline-tic
kets") - The following line sets the Method Name that you
wish to invoke on the Object Interface that you
described in the line above - call.setMethodName ("buyTickets")
-
27Writing a Client application
- Parameter vector is setup
- Call object accepts a vector of parameters
- These parameters (each of which represents 1
argument to the method being invoked) are
serialized "for the wire" using a type mapping
system that serializes based on the type of the
object held by each parameter - Vector params new Vector( )
- params.addElement(new Parameter("flightNumber",
Integer.class, flightNumber, null))
28Writing a Client application
- Now its time to invoke the method
- URL url new URL ("http//rpc.middleearth.com")
- Response resp call.invoke (url, "")
- URL object represents the SOAP endpoint that will
be receiving the request - The invocation may throw a SoapException if
something goes wrong - Make provisions to catch the exception
29Writing a Client application
- Check the response to see if an exception was
generated at the SOAP protocol level - if (resp.generatedFault()) Fault
faultresp.getFault() System.out.println("Fault
code " fault.getFaultCode())
System.out.println("Fault string
fault.getFaultString()) - else
- Otherwise the call was successful and a return
value can be retrieved. - Parameter stores values of class Object, so
downcast the object to expected type for further
handling
30Writing a Client application
- Parameter resultresp.getReturnValue()
- Object o result.getValue()
-
31Invocation
- Actual invocation is represented by the Call
object - Allows you to set
- the target of the call,
- Method to invoke
- Encoding style
- Parameters
32A First Fast Example of a SOAP implementation in
Java
- Purpose testing your Apache SOAP installation
33Setting up Apache SOAP
- Open source project that support SOAP (and Java)
- Apache SOAP (http//xml.apache.org/soap)This
project provides a SOAP toolkit in Java
34Building our 1st web service
- The tools we are going to use are
- Apache SOAP 2.3.1 (http//xml.apache.org/soap)
- Apache Jakarta Tomcat 4.1.29 (http//jakarta.apach
e.org/tomcat) - Apache Xerces XML Parser 2.5.0 (http//xml.apache.
org/xerces-j/index.html) - Sun JavaMail 1.3.1(http//java.sun.com/products/j
avamail) - JavaBeans Activation Framework (JAF
1.0.2)(http//java.sun.com/products/beans/glasgow
/jaf.html)
35Installed software
- Apache SOAP 2.3.1 open source Java
implementation of SOAP includes support for a
useful subset of the SOAP 1.1 specification - Apache Jakarta Tomcat 4.1.29 open source Java
web server implements the Java servlets 2.2 API
specification - Apache Xerces XML Parser 2.5.0 open source XML
parser implements most of the latest XML
specifications - Sun JavaMail used for the SMTP protocol support
included in SOAP
36Tools and installation
- See http//ingenieur.kahosl.be/vakgroep/it/onderw
ijs/ModBest/soap.htm
37Starting web server
- Start the tomcat web server by entering the
command startup or catalina run
38Starting the web server
- This commands starts the web server on your local
host on port 8080 - Start IE and type in the URL http//localhost8080
/soap - This activates the Apache Soap system that was
installed into /soap when you edited the tomcat
server.xml
39Starting the webserver
40Writing a web service
- This web service will calculate the exchange rate
between 2 countries - Java interface is
- public interface IExchange
-
- float getRate( String country1, String
country2 ) -
41Writing a web service
- Implementation of the interface
- public class Exchange implements IExchange
-
- public float getRate( String country1, String
country2 ) -
- System.out.println( "getRate( " country1
", " country2 " )" ) - return 144.52F // always return the same
value for now -
-
42Writing a web service
- Add \voorbeelden to your classpath and compile
the code - Now you can publish the Java class as a web
service into Tomcat
43Deploying a web service
- To deploy the Exchange service
- Launch tomcat again from the \voorbeelden
directory - Type the URL http//localhost8080/soap
- Click on Run the admin client
44Deploying a webservice
45What happens if you click on List?
46Deploying a web service
- To deploy a web service (in this case the
Exchange service) click on the deploy option and
fill in the fields
47(No Transcript)
48(No Transcript)
49Clarification
- ID web service identifier. In this case
urndemo1exchange, with demo1 a namespace and
exchange the service string - Scope activation mode for the service.
- Request new instance of service is created with
every individual request - Session
- Application (see later)
- Methods methods to expose in the service (in
this case getRate)
50Clarification
- Provider type of web service. Apache SOAP only
supports Java classes and Bean scripts - Provider class/Static name of the Java class (in
this case Exchange)
51Deploying a web service
- After filling in the values, click the deploy
button
52Deploying a web service
- Click on the list button
- Click on the link
53(No Transcript)
54Invoke a web service
- To invoke a web service from a Java client
- Import various packages (required by SOAP)
- Prepare your remote SOAP invocation by
constructing a Call object and initialising its
fields - Encoding style Constants.NS_URI_SOAP_ENC
55Invoke a web service
- Each parameter is represented by a Parameter
object - with the name of the argument,
- type of the argument,
- value of the argument and
- the encoding style for the argument (null selects
the default)
56Invoke a web service
- To invoke the method call, execute the invoke()
method with the URL of the SOAP endpoint and the
SOAPAction value - If all goes well, the result is returned with
primitives wrapped in their object equivalent
57Invoke a web service
- import java.net.
- import java.util.
- import org.apache.soap. // Body, Envelope,
Fault, Header - import org.apache.soap.rpc. // Call, Parameter,
Response - public class Client
- public static void main( String args )
throws Exception - URL url new URL( "http//localhost8080/soa
p/servlet/rpcrouter" ) - String urn "urndemo1exchange"
- Call call new Call() // prepare the
service invocation - call.setTargetObjectURI( urn )
- call.setMethodName( "getRate" )
- call.setEncodingStyleURI( Constants.NS_URI_SO
AP_ENC )
58Invoke a web service
- Vector params new Vector()
- params.addElement(new Parameter("country1",
String.class, "USA", null)) - params.addElement(new Parameter("country2",
String.class, Japan", null)) - call.setParams(params)
- try System.out.println("invoke
service\n" " URL " url "\n URN "
urn ) - //invoke the service
- Response response call.invoke( url, "" )
if(!response.generatedFault()) // response
was OK Parameter result response.getReturnVal
ue() System.out.println("Result
"result.getValue())
59Invoke a web service
- else
- // an error occurred Fault f
response.getFault() System.err.println("Fault
"f.getFaultCode()", f.getFaultString()) - catch(SOAPException e) // call
could not be sent properly System.err.println("SO
APException " e.getFaultCode()",
e.getMessage()) -
-
-
60Invoke a web service
- Compiling and running this java program, gives
the following result
61Invoke a web service
- The web service output on Tomcat becomes
62Invoke web services across the Internet
- Web services use a XML format over HTTP for
messaging - It is rather easy to invoke web service across
the internet - Visit XMethods (http//www.xmethods.net)
- This site hosts a selection of web services that
are perfect for experimenting with this technology
63Invoke web services across the Internet
- Click on the web service called Currency
Exchange Rate - This screen describes all the details of this web
service, including the URN, the router endpoint
and a description of each method available
64Invoke web services across the Internet
- This Web service at XMethods provides the same
methods as the one you just built - To invoke the XMethods service
- Modify the URL to http//services.xmethods.net/soa
p - URN to urnmethods-CurrentExchange
- Run the client again
65Running the Currency Exchange Rate Web Service
66SOAP moves in mysterious ways or not?
- Q Where can I find SOAP in these examples?
- A you can see the SOAP messages exchanged
between client and server via TCP tunneling GUI - TCP tunneling GUI you can see TCP messages move
between client and server
67Sniffing SOAP
- With TCP tunneling GUI you can sniff SOAP
messages by acting as a TCP router - To see it in action
- Start Tomcat (starts up on port 8080 (default))
- Start (in a separate window) the TCP tunneler
java org.apache.soap.util.net.TcpTunnelGui 8070
localhost 8080This starts a TCP server on port
8070 that acts as an intermediary between any
client and port 8080 on the local host (serviced
by Tomcat)
68Sniffing SOAP
69Sniffing SOAP
- Edit Client.java and change the web service URL
to use port 8070 instead of 8080 - Compile and run it
- The result is
70Sniffing SOAP
71Sniffing SOAP
- On the left-hand outgoing SOAP request
- On the right-hand response
- This is almost self-describing
72Anatomy of a SOAP request
- Protocol use to deliver soap messages is in this
case HTTP - But you can also use SMTP (see later, if mail
server is not down -) ) - Headers differ from protocol to protocol, but the
XML payload stays the same
73SOAP/Http request
- POST /soap/servlet/rpcrouter HTTP/1.0 Host
localhost8070 Content-Type text/xml
Content-Length 461 SOAPAction ""
ltSOAP-ENVEnvelope xmlnsSOAP-ENV"http//sche
mas.xmlsoap.org/soap/envelope/
xmlnsxsi"http//www.w3.org/1999/XMLSchema-instan
ce xmlnsxsd"http//www.w3.org/1999/XMLSchema"
gt ltSOAP-ENVBodygt ltns1getRate
xmlnsns1"urndemo1exchange"
SOAP-ENVencodingStyle"http//schemas.xmlsoap.org
/soap/encoding/"gt ltcountry1
xsitype"xsdstring"gtUSAlt/country1gt
ltcountry2 xsitype"xsdstring"gtjapanlt/country2gt
lt/ns1getRategt lt/SOAP-ENVBodygtlt/SOAP-ENVEn
velopegt
74SOAP request
- A SOAP request is sent as an HTTP POST with
content type set to text/xml and field called
SOAPAction set to either an empty string or the
name of the SOAP method - SOAPAction field allows a receiving web server to
detect that its an incoming SOAP message and
potentially route or filter it
75SOAP request
- XML part of the SOAP request consists of 3
portions - Envelope defines the different namespaces
(xmlnsSOAP-ENV, xmlnsxsi and xmlnsxsd) - Header optional element. If a Header is present
is must be the 1st child of the Envelope - Body main payload of the message. When SOAP is
used to perform RPC call, Body contains a single
element that contains the method name, arguments
and web service target address
76SOAP request
- If a Header is present, Body must be its
immediate sibling, otherwise it must be the first
child of the Envelope
77Anatomy of a SOAP response
- A SOAP/HTTP response is returned as an XML
document within a standard HTTP reply whose
content type is set to text/xml - XML document is structured just like the request,
except that Body contains the encoded method
result
78Anatomy of a SOAP response
- HTTP/1.0 200 OK Content-Type text/xml
charsetUTF-8 Content-Length 425 Set-Cookie2
JSESSIONID4x1b3dqoc1Version1DiscardPath"/soa
p" Set-Cookie JSESSIONID4x1b3dqoc1Path/soap
Servlet-Engine Tomcat Web Server/3.2.3 (JSP
1.1 Servlet 2.2 Java 1.3.0 Windows 2000 5.0
x86 java.vendorSun Microsystems Inc.) - ltSOAP-ENVEnvelope xmlnsSOAP-ENV"http//schem
as.xmlsoap.org/soap/envelope/
xmlnsxsi"http//www.w3.org/1999/XMLSchema-instan
ce xmlnsxsd"http//www.w3.org/1999/XMLSchema"
gtltSOAP-ENVBodygtltns1getRateResponse
xmlnsns1"urndemo1exchange"
SOAP-ENVencodingStyle"http//schemas.xmlsoap.org
/soap/encoding/"gt ltreturn xsitype"xsdfloat"gt144
.52lt/returngtlt/ns1getRateResponsegtlt/SOAP-ENVBod
ygtlt/SOAP-ENVEnvelopegt
79SOAP Exceptions
- If an exception occurs at any time during the
processing of a message, a SOAP exception is
thrown - SOAP exceptions are encoded similar to regular
SOAP responses - Body is used to contain info about the exception
- Illustration
80SOAP Exceptions
- public class Exchange implements IExchange
-
- public float getRate( String country1, String
country2 ) -
- throw new RuntimeException( "cannot calculate
rate" ) - /
- System.out.println( "getRate( " country1
", " country2 " )" ) - return 144.52F // always return the same
value for now - /
-
-
81SOAP Exceptions
- Shutdown and restart Tomcat (to use the new
version of the web service) - Invoke the Service using the Client program
82SOAP Exceptions
83SOAP Exceptions clarification
- http reply header indicates an exception by using
status code 500 - XML payload contains an Envelope and Body (like a
regular response) except that the content of the
Body is a fault structure whose fields are
defined as follows - Faultcode SOAP-ENVClient, SOAP-ENVServer,
SOAP-ENVVersionMismatch, SOAP-ENVMustUnderstand - Faultstring description of the fault
84SOAP Exceptions clarification
- Faultactor optional field that indicates the URI
of the source of the fault - Detail application-specific XML that contains
detailed info about the fault
85Exercise
- Adapt the example in such a way that you create a
web service that is able to calculate the sum of
two numbers - Write also the corresponding client
86Java SOAP
87SOAP Implementations in Java
- Best known are
- Apache SOAP
- GLUE (http//www.themindelectric.com) can handle
WSDL (download GLUE!) - Implementators invented their own SOAP API
- Now standards for SOAP-based messaging RPC
APIs - JAXM
- JAX-RPC
- Standards implemented by Axis (next generation
Apache SOAP implementation)
88SOAP Data Encoding
- Data encoding encoding data in such a way that
sender receiver understand its the meaning - Serialisation of data (like in Java)
- Use of namespaces schemas
- Schemas not used for validation but as
references to definitions of data elements
89SOAP Data Encoding
- Namespace kind of dictionary that describes
meaning - Encoding style is defined in http//schemas.xmlsoa
p.org/encoding - Following namespaces are commonly found
- xmlnsSOAP-ENChttp//schemas.xmlsoap.org/encodin
g - xmlnsxsihttp//www.w3.org/2001/XMLSchema/instan
ce/ - xmlnsxsdhttp//www.w3.org/2001/XMLSchema
- ltxyz xsitypexsdfloatgt3.14159lt/xyzgt
90SOAP Data Encoding
- SOAP distinction between simple compound
values - simple simple piece of data (ex. strings,
integers, floats,)
91SOAP Data Encoding
- Compound value multiple pieces of data, with
some relation to each other. Way to distinguish
specific data value mechanism is referred as an
accessor
92SOAP Data Encoding
93RPC
- Required for representing an RPC method call in
SOAP - Target object URI or resource address of the
service - Method name name of the method to be invoked
- Method parameters
- SOAP header data
94RPC Service Activation
- Service activation or scope lifetime of an
object - In SOAP systems based on HTTP, 3 service
activation models - Request-level activation for each request, new
instance of object is created, deleted when
request is complete - Application-level activation single instance of
service object handles every method invocation
for the entire lifetime of service application - Session-level activation single instance of
service object is used for all method invocations
for the lifetime of the session
95Simple service to illustrate different service
activation models
- Design service called CallCounterService
- Keeps track of number of method calls
- Code
- public class MethodCounter
- int _counter
- public MethodCounter()
- _counter 0
-
- public int getCount()
- return _counter
-
- public boolean doSomething()
- _counter 1 return true
-
96Some remarks
- Methods are named according to JavaBeans naming
convention! - Our service class uses a no-argument constructor
- Java SOAP implementations load service classes
dynamically Class.newInstance() - Requires constructor with no arguments
97Deploying the service in Apache SOAP
- Deployment no part of the SOAP specifications
- 2 different ways to deploy service in Apache
SOAP - Write manually a deployment descriptor
- Or using the SOAP Admin tool
98Deployment descriptor
- ltisdservice xmlnsisdhttp//xml.apache.org/xml
-soap/deployment idurnCallCounterServicegt - ltisdprovider typejava scopeApplication
methodsdoSomething getCountgt - ltisdjava ClassMethodCounter
staticfalse/gt - lt/isdprovidergt
- ltisdfaultListenergt
- org.apache.soap.server.DOMFaultListener
- lt/isdfaultListenergt
- ltisdmappingsgtlt/isdmappingsgt
- lt/isdservicegt
99Deployment descriptor
- Save this ex. CallCounterService.dd
- Deploy the service
- java org.apache.soap.server.ServiceManagerClient
http//localhost8080/soap/sevlet/rpcrouter
deploy CallCounterService.dd
100Using the SOAP Admin tool
- Open browser with URL http//localhost8080/soap/
- Click Run the Admin Client
- Deploy service via the web interface
101Next step writing a service client
- import java.net.
- import org.apache.soap.
- import org.apache.soap.rpc.
- public class GetCountApp
-
- public GetCountApp()
-
- public void callGetCountApp() throws Exception
-
- URL url new URL("http//localhost80
80/soap/servlet/rpcrouter") - Call call new Call()
- call.setTargetObjectURI("urnCallCounterService"
) - call.setMethodName("getCount")
-
- try
- Response resp call.invoke(url,"")
- Parameter ret resp.getReturnValue()
- Object value ret.getValue()
102Next step writing a service client
- catch(SOAPException e)
- System.err.println("Caught SOAPException ("
e.getFaultCode()")"e.getMessage()) -
-
-
- public static void main(String args) throws
Exception -
- GetCountApp GCA new GetCountApp()
- GCA.callGetCountApp()
-
103Making it more spectacular
- import java.net.
- import org.apache.soap.
- import org.apache.soap.rpc.
- public class GetCountApp2
-
- public GetCountApp2()
-
- public void callGetCountApp() throws Exception
-
- URL url new URL("http//localhost8080/soap/s
ervlet/rpcrouter") - Call call new Call()
- call.setTargetObjectURI("urnCallCounterService"
) -
104Making it more spectacular
- try
- call.setMethodName("doSomething")
- Response resp call.invoke(url,"")
- resp call.invoke(url,"")
- resp call.invoke(url,"")
- call.setMethodName("getCount")
- resp call.invoke(url,"")
- Parameter ret resp.getReturnValue()
- Object value ret.getValue()
- System.out.println("Result is " value)
-
- catch(SOAPException e)
- System.err.println("Caught SOAPException ("
e.getFaultCode()")"e.getMessage()) -
-
-
105Making it more spectacular
-
- public static void main(String args) throws
Exception -
- GetCountApp2 GCA new GetCountApp2()
- GCA.callGetCountApp()
-
106Changing the service activation
- .. to requestlevel
- New instance is created for each method
invocation object is destroyed when invocation
is complete - Change Scope in Admin tool to request!
- Run the examples again!
107Changing the service activation
- session-level scope
- Run the examples again!
- Common use for this? Online shopping
108Passing parameters
109Passing parameters
- Create a StockPrice class that allows passing of
parameters - public class StockPrice
-
- public float getPrice(String stock, String
currency) -
- float result
- result (float)75.33
- System.out.println("Price is "result)
- return result
-
-
-
-
110Passing parameters
- Deploy this service with scope application
- Client program (in Apache SOAP) to access the
service
111Passing parameters (Apache SOAP)
- import java.net.
- import java.util.
- import org.apache.soap.
- import org.apache.soap.rpc.
- public class StockPriceApp
-
- public StockPriceApp()
-
- public void callStockPrice() throws Exception
-
- try
- URL url new
URL("http//localhost8080/soap/servlet/rpcrouter"
) - Call call new Call()
- call.setTargetObjectURI("urnStockPriceServic
e") - call.setEncodingStyleURI(Constants.NS_URI_SOA
P_ENC) -
112Passing parameters (Apache SOAP)
- String stock KAHOSL"
- String currency "Euro"
- Vector params new Vector()
- params.addElement(new Parameter("stock",
String.class, stock, null)) - params.addElement(new Parameter("currency",
String.class, currency, null)) - call.setParams(params)
- call.setMethodName("getPrice")
- Response resp call.invoke(url,"")
- Parameter ret resp.getReturnValue()
- Object value ret.getValue()
System.out.println("Price is " value) -
113Passing parameters (Apache SOAP)
- catch(SOAPException e)
- System.err.println("Caught SOAPException ("
- e.getFaultCode() ")" e.getMessage())
-
-
-
- public static void main(String args) throws
Exception -
- StockPriceApp SPA new StockPriceApp()
- SPA.callStockPrice()
-
-
-
-
114Passing parameters
- For setting up parameters, call the
setEncodingStyleURI of the Call object - Each parameter is held in instance of
org.apache.soap.rpc.Parameter - Constructor of this class takes
- Parameters name
- Class of the object that contains parameter value
- Object that contains the parameter value
- Encoding style URI for the parameter
115Complex data types passing arrays as parameters
- Write a service that return information about a
collection of stock symbols - For the moment service that returns the total
number of shares - Service is called urnBasicTradingService and
associated method is getTotalVolume
116Passing arrays as parameters service
- public class BasicTradingService
-
- public BasicTradingService()
-
- public int getTotalVolume(String stocks)
-
- //get the volumes for each stock from some
- //data feed and return the total
-
- int total 123456
- return total
-
-
-
- Deploy this service (scope application)
117Passing arrays as parameters client
- import java.net.
- import java.util.
- import org.apache.soap.
- import org.apache.soap.rpc.
- public class VolumeClient
- public VolumeClient()
- public void callVolumeClient() throws Exception
- URL url new URL("http//localhost8080/soap
/servlet/rpcrouter") - Call call new Call()
- call.setTargetObjectURI("urnBasicTradingService
") - call.setEncodingStyleURI(Constants.NS_URI_SOAP_E
NC) - String stocks "KAHO", "VAKIT", "SUN"
- Vector params new Vector()
- params.addElement(new Parameter("stocks",
String.class, stocks, null)) - call.setParams(params)
118Passing arrays as parameters client
- try
- call.setMethodName("getTotalVolume")
- Response resp call.invoke(url,"")
- Parameter ret resp.getReturnValue()
- Object value ret.getValue()
- System.out.println("Total Volume is "
value) -
- catch(SOAPException e)
- System.err.println("Caught SOAPException ("
- e.getFaultCode() ")" e.getMessage())
-
-
- public static void main(String args) throws
Exception -
- VolumeClient VC new VolumeClient()
- VC.callVolumeClient()
-
-
119Heterogeneous arrays
- Adapt the service
- public class BasicTradingService2
-
- public BasicTradingService2()
-
- public int getTotalVolume(String stocks)
-
- //get the volumes for each stock from some
- //data feed and return the total
-
- int total 123456
- return total
-
-
120Heterogeneous arrays
- public String executeTrade(Object params)
- String result
- try String stock (String)params0
- Integer numShares (Integer)params1
- Boolean buy (Boolean)params2
- String orderType "Buy"
- if (false buy.booleanValue())
- orderType "Sell"
-
- result (orderType " " numShares " of "
stock) -
- catch(ClassCastException e)
- result "Bad Parameter Type Encountered"
-
- return result
-
121Corresponding Client
- import java.net.
- import java.util.
- import org.apache.soap.
- import org.apache.soap.rpc.
- public class TradingClient
- public TradingClient()
- public void callTradingClient() throws
Exception - URL url new URL("http//localhost8080/soap/s
ervlet/rpcrouter") - Call call new Call()
- call.setTargetObjectURI("urnBasicTradingService
2") - call.setEncodingStyleURI(Constants.NS_URI_SOAP_E
NC) - Object multiParams "MS", new Integer(200),
new Boolean(true) - Vector params new Vector()
-
122Corresponding Client
- params.addElement(new Parameter("params",
Object.class, multiParams, null)) - call.setParams(params)
- try
- call.setMethodName("executeTrade")
- Response resp call.invoke(url,"")
- Parameter ret resp.getReturnValue()
- Object value ret.getValue()
- System.out.println("Trade description "
value) -
- catch(SOAPException e)
- System.err.println("Caught SOAPException
(" e.getFaultCode() ")" e.getMessage()) -
-
123Corresponding Client
- public static void main(String args) throws
Exception - TradingClient TC new TradingClient()
- TC.callTradingClient()
-
-
124Returning arrays
- Add method to our service, that returns String
that contains the symbols for the most actively
traded stocks - public String getMostActive()
- //get the most actively traded stocks of the
day - String actives "QD", "FB", "LD", "TM"
- return actives
125Client application
- import java.net.
- import java.util.
- import org.apache.soap.
- import org.apache.soap.rpc.
- public class MostActiveClient
-
- public MostActiveClient()
-
- public void callMostActiveClient() throws
Exception - URL url new URL("http//localhost8080/soap
/servlet/rpcrouter") - Call call new Call()
- call.setTargetObjectURI("urnBasicTradingService
3") - call.setMethodName("getMostActive")
- Response resp
126Client application
- try
- resp call.invoke(url,"")
- Parameter ret resp.getReturnValue()
- String value (String)ret.getValue()
- int cnt value.length
- for (int i 0 iltcnt i)
- System.out.println(valuei)
-
-
- catch(SOAPException e)
- System.err.println("Caught SOAPException ("
- e.getFaultCode() ") e.getMessage())
-
-
-
127Client application
- public static void main(String args) throws
Exception - MostActiveClient MAC new MostActiveClient()
- MAC.callMostActiveClient()
-
-
-
128Passing custom types as parameters
- Suppose a Java class that contains all data
necessary to specify a stock trade - Common way to express properties of Java class is
using JavaBeans design pattern - Pattern specify naming convention for the classs
access methods
129Passing custom types as parameters JavaBeans
pattern
- public void setltPropertyNamegt(ltPropertyTypegt
value) - public ltPropertyTypegt getltPropertyNamegt()
- If ltPropertyTypegt is boolean, get Method can be
replaced by - public boolean isltPropertyNamegt()
- Following this naming convention for accessors,
the accessor methods can be determined at runtime
(using Javas reflection mechanism) - Convenient way for SOAP implementations to access
data values of a Java class instance in order to
serialize the data in a SOAP message
130Passing custom types as parameters data?
- Define stock in terms of data it has to contain
- Stock symbol (String)
- Buy or sell? (boolean)
- Number of shares (integer)
- ltelement nameStockTrade typeStockTrade/gt
- ltcomplexType nameStockTradegt
- ltelement namesymbol typexsdstring/gt
ltelement namebuy typexsdboolean/gt - ltelement namenumshares typexsdint/gt
- lt/complexTypegt
131Create a custom Java class StockTrade_ClientSide
- public class StockTrade_ClientSide
- String _symbol
- boolean _buy
- int _numShares
- public StockTrade_ClientSide()
-
- public StockTrade_ClientSide(String symbol,
boolean buy, int numShares) - _symbol symbol
- _buy buy
- _numShares numShares
-
- public String getSymbol()
- return _symbol
-
- public void setSymbol(String symbol)
- _symbol symbol
-
132StockTrade_ClientSide
- public boolean isBuy()
- return _buy
-
- public void setBuy(boolean buy)
- _buy buy
-
- public int getNumShares()
- return _numShares
-
- public void setNumShares(int numShares)
- _numShares numShares
-
133Create a custom Java class StockTrade_ServerSide
- public class StockTrade_ServerSide
-
- int _shares
- boolean _buyOrder
- String _stock
-
- public StockTrade_ServerSide()
-
- public String getSymbol()
- return _stock
-
- public void setSymbol(String stock)
- _stock stock
-
-
134StockTrade_ServerSide
- public boolean isBuy()
- return _buyOrder
-
-
- public void setBuy(boolean buyOrder)
- _buyOrder buyOrder
-
-
- public int getNumShares()
- return _shares
-
-
- public void setNumShares(int shares)
- _shares shares
-
-
135Passing custom types as parameters adapting the
service
- Add new method to urnBasicTradingService
service, called executeStockTrade() - public String executeStockTrade(StockTrade_Server
Side trade) - Object params new Object3
- params0 trade.getSymbol()
- params1 new Integer(trade.getNumShares())
- params2 new Boolean(trade.isBuy())
- return executeTrade(params)
136Deploying the service
- Add
- encodingStyle http//schemas.xmlsoap.org/soap/en
coding/, - elementType urnBasicTradingService4StockTrade,
- javaTypeStockTrade_ServerSide,
- java2XMLClassName org.apache.soap.encoding.soape
nc.BeanSerializer, - xml2JavaClassName org.apache.soap.encoding.soape
nc.BeanSerializer
137Write new Client
- import java.net.
- import java.util.
- import org.apache.soap.
- import org.apache.soap.rpc.
- import org.apache.soap.encoding.
- import org.apache.soap.encoding.soapenc.
- import org.apache.soap.util.xml.
- public class StockTradeClient
- public StockTradeClient()
- public void callStockTradeClient() throws
Exception - URL url new URL("http//localhost8080/soap
/servlet/rpcrouter") - Call call new Call()
- SOAPMappingRegistry smr new
SOAPMappingRegistry() - call.setSOAPMappingRegistry(smr)
- call.setEncodingStyleURI(Constants.NS_URI_SOAP_E
NC) - call.setTargetObjectURI("urnBasicTradingService
4")
138Write new Client
- call.setMethodName("executeStockTrade")
- BeanSerializer beanSer new BeanSerializer()
- //Map the Stock Trade type
- smr.mapTypes(Constants.NS_URI_SOAP_ENC,
- new QName("urnBasicTradingService4","StockT
rade"), - StockTrade_ClientSide.class, beanSer,
beanSer) - //create an instance of the stock trade
- StockTrade_ClientSide trade new
StockTrade_ClientSide("QSD", false, 400) Vector
params new Vector() - params.addElement(new Parameter("trade",
StockTrade_ClientSide.class, trade, null)) - call.setParams(params)
- Response resp
- try resp call.invoke(url,"")
- Parameter ret resp.getReturnValue()
- Object desc ret.getValue()
- System.out.println("Trade description "
desc) -
139Write new Client
- catch(SOAPException e)
- System.err.println("Caught SOAPException ("
- e.getFaultCode() ")"e.getMessage())
-
-
-
-
- public static void main(String args) throws
Exception -
- StockTradeClient STC new StockTradeClient()
- STC.callStockTradeClient()
-
-
-
140Returning custom types
- Enhance trading service by offering a method that
takes a single stock symbol as parameter and
returns its high and low prices for a day - Create 2 new classes
- HighLow_ServerSide
- HighLow_ClientSide
141HighLow_ServerSide
- public class HighLow_ServerSide
-
- public float _high
- public float _low
- public HighLow_ServerSide()
-
- public HighLow_ServerSide(float high, float
low) - setHigh(high)
- setLow(low)
-
-
- public float getHigh()
- return _high
-
-
142HighLow_ServerSide
- public void setHigh(float high)
- _high high
-
-
- public float getLow()
- return _low
-
- public void setLow(float low)
- _low low
-
-
-
143HighLow_ClientSide
- public class HighLow_ClientSide
-
- public float _high
- public float _low
- public String toString()
-
- return "High " _high " Low " _low
-
- public HighLow_ClientSide()
-
- public float getHigh()
- return _high
-
- public void setHigh(float high)
- _high high
-
144HighLow_ClientSide
-
- public float getLow()
- return _low
-
- public void setLow(float low)
- _low low
-
-
-
145Returning custom types adapting service
- Add new method
- public HighLow_ServerSide getHighLow(String
stock) - //retrieve the high and low for the specified
stock - return new HighLow_ServerSide((float)110.375,(flo
at)109.5)
146Deploy the service
- Add 2 mappings
- Mapping 1
- encodingStyle http//schemas.xmlsoap.org/soap/en
coding/, - elementType urnBasicTradingService5StockTrade,
- javaType StockTrade_ServerSide,
- java2XMLClassName org.apache.soap.encoding.soape
nc.BeanSerializer, - xml2JavaClassName org.apache.soap.encoding.soape
nc.BeanSerializer - Mapping 2
- encodingStyle http//schemas.xmlsoap.org/soap/en
coding/, - elementType urnBasicTradingService5HighLow,
- javaType HighLow_ServerSide,
- java2XMLClassName org.apache.soap.encoding.soape
nc.BeanSerializer, - xml2JavaClassName org.apache.soap.encoding.soape
nc.BeanSerializer
147Write new client
- import java.net.
- import java.util.
- import org.apache.soap.
- import org.apache.soap.rpc.
- import org.apache.soap.encoding.
- import org.apache.soap.encoding.soapenc.
- import org.apache.soap.util.xml.
- public class HighLowClient
-
- public HighLowClient()
-
- public void callHighLowClient() throws
Exception - URL url new URL("http//localhost8080/soap/s
ervlet/rpcrouter") - Call call new Call()
- SOAPMappingRegistry smr new
SOAPMappingRegistry() -
148Write new client
- call.setSOAPMappingRegistry(smr)
- call.setEncodingStyleURI(Constants.NS_URI_SOAP_E
NC) - call.setTargetObjectURI("urnBasicTradingService
5") - call.setMethodName("getHighLow")
- BeanSerializer beanSer new BeanSerializer()
- //Map the High/Low type
- smr.mapTypes(Constants.NS_URI_SOAP_ENC,
- new QName("urnBasicTradingService5","HighLow"),
- HighLow_ClientSide.class, beanSer, beanSer)
- String stock "XYZ"
- Vector params new Vector()
- params.addElement(new Parameter("stock",
String.class, stock, null)) - call.setParams(params)
- Response resp
149Write new client
- try
- resp call.invoke(url,"")
- Parameter ret resp.getReturnValue()
- HighLow_ClientSide hilo (HighLow_Client
Side)ret.getValue() - System.out.println(hilo)
-
- catch(SOAPException e)
- System.err.println("Caught SOAPException ("
- e.getFaultCode() ")"e.getMessage())
-
-
- public static void main(String args) throws
Exception - HighLowClient STC new HighLowClient()
- STC.callHighLowClient()
-
150SOAP over SMTP
- http//ws.apache.org/soap/faq/faq_chawke_smtp.html
151How about SOAP SMTP?
- Before starting make sure that SOAP over HTTP
works - SOAP is transport independent protocol
- Apache SOAP includes classes which permit SOAP
messages using email - A class named SMTP2HTTPBridge must be running on
the server - Kind of bridge mapping requests between HTTP and
SMTP - It converts e-mail SOAP messages to and from HTTP
SOAP messages
152Running the Apache SOAP SMTP Bridge on the Server
- Include pop3.jar and smtp.jar in your classpath
- Use a test email account (ex. mail1)
- Execute the following command
- java org.apache.soap.server.SMTP2HTTPBridge 2500
pop.kahosl.be mail1 mail1x http//localhost8080/s
oap/servlet/rpcrouter smtp.kahosl.be
153Running the Apache SOAP SMTP Bridge on the Server
- Where
- 2500 is the poll delay
- pop.kahosl.be is the pop3 server
- mail1 is the login on the pop3 server
- mail1x is the password
- http//localhost8080/soap/servlet/rpcrouter
- smtp.kahosl.be is the SMTP server
154Running the Apache SOAP SMTP Bridge on the Server
- The result should be
- See demo
155Running an Apache Client using SMTP
- Find an existing SOAP client making invocations
over HTTP - Modify the code to use SMTP instead of HTTP
156Running an Apache Client using SMTP
- URL url new URL( "mailtomail1_at_kahosl.be" )
- String urn "urndemo1exchange"
- String smtpserver "smtp.kahosl.be"
- String popserver "pop.kahosl.be"
- String poplogin "mail1"
- String poppasswd "mail1x"
- String replyaddr poplogin"_at_kahosl.be"
- SOAPTransport ss new SOAPSMTPConnection (
- replyaddr, "SOAP Request", smtpserver,
3500, popserver, poplogin, poppasswd) - Call call new Call()
- call.setSOAPTransport(ss)
157SOAP and SSL
- http//ws.apache.org/soap/docs/install/FAQ_Tomcat_
SOAP_SSL.html - Note this website is rather obsolete
158How can we make SOAP secure?
- Copy (hint look in Glue lib directory)
- jsse.jar
- jcert.jar
- jnet.jar
- to lib directory of Tomcat
- Generate client and server certificates
- Generate a server key and certificate
- keytool -genkey -alias tomcat-sv -dname
"CNnewton.kahosl.be, OUVakgroepIT, OKaHo
Sint-Lieven, LGent, SOost-Vlaanderen, CBE"
-keyalg RSA -keypass changeit -storepass changeit
-keystore server.keystore
159How can we make SOAP secure?
- Export Server Certificate
- keytool export alias tomcat-sv storepass
changeit file server.cer keystore
server.keystore - Generate client key and certificate
- keytool -genkey -alias tomcat-cl -dname
"CNClient, OUVakgroepIT, OKaHo Sint-Lieven,
LGent, SOost-Vlaanderen, CBE" -keyalg RSA
-keypass changeit -storepass changeit -keystore
client.keystore
160How can we make SOAP secure?
- Export Client Certificate
- keytool export alias tomcat-cl storepass
changeit file client.cer keystore
client.keystore - Import the certificates into Keystores
- Add client certificate to servers keystore
servers certificate added to clients keystore - keytool import v trustcacerts alias tomcat
file server.cer keystore client.keystore
keypass changeit storepass changeit - keytool import v trustcacerts alias tomcat
file client.cer keystore server.keystore
keypass changeit storepass changeit
161How can we make SOAP secure?
- Adapt server.xml in conf subdirectory of Tomcat
- Uncomment the part about SSL and add
- ltFactory className"org.apache.coyote.tomcat4.Co
yoteServerSocketFactory" clientAuth"false"
keystoreFile"c\javaxml2\voorbeelden\ssl\server.
keystore" protocol"TLS"/gt
162How can we make SOAP secure?
- Test your https server
- https//localhost8443
- Modify your SOAP client! Add
- import javax.net.ssl.SSLSocketFactory
- import java.security.Security
- System.setProperty("javax.net.ssl.trustStore",
"c\\javaxml2\\voorbeelden\\ssl\\client.keystore")
- System.setProperty("javax.protocol.handler.pkgs",
"com.sun.net.ssl.internal.www.protocol") - Security.addProvider(new com.sun.net.ssl.internal.
ssl.Provider()) - URL url new URL( "https//localhost8443/soap/se
rvlet/rpcrouter" )