WEB SERVICES
Sam Guinea
[email protected]
http://servicetechnologies.wordpress.com/
Reference Book
Martin Kalin
Java Web Services: Up
and Running, 1st Edition
O'Reilly Media, Inc.
JAX-WS
• Java API for XML-Web Services
• The reference framework for Java Web Services
• Bundled into the Metro Web Services Stack
• Part of the Glassfish Application Server but…
• Also available in the core Java Standard Edition 6.
@WebService
@WebService(targetNamespace = "http://duke.org", name="AddNumbers")
public interface AddNumbersIF extends Remote {
@WebMethod(operationName="add", action="urn:addNumbers")
@WebResult(name="return")
public int addNumbers(
@WebParam(name="num1")int number1,
@WebParam(name="num2")int number2) throws RemoteException, AddNumbersException;
@WebMethod
@WebService(targetNamespace = "http://duke.org", name="AddNumbers")
public interface AddNumbersIF extends Remote {
@WebMethod(operationName="add", action="urn:addNumbers")
@WebResult(name="return")
public int addNumbers(
@WebParam(name="num1")int number1,
@WebParam(name="num2")int number2) throws RemoteException, AddNumbersException;
@WebParam
@WebService(targetNamespace = "http://duke.org", name="AddNumbers")
public interface AddNumbersIF extends Remote {
@WebMethod(operationName="add", action="urn:addNumbers")
@WebResult(name="return")
public int addNumbers(
@WebParam(name="num1") int number1,
@WebParam(name="num2") int number2) throws RemoteException, AddNumbersException;
@WebResult
@WebService(targetNamespace = "http://duke.org", name="AddNumbers")
public interface AddNumbersIF extends Remote {
@WebMethod(operationName="add", action="urn:addNumbers")
@WebResult(name="return")
public int addNumbers(
@WebParam(name="num1") int number1,
@WebParam(name="num2") int number2) throws RemoteException, AddNumbersException;
@SOAPBinding
@WebService(targetNamespace = "http://duke.org", name="AddNumbers")
@SOAPBinding(style=SOAPBinding.Style.RPC, use=SOAPBinding.Use.LITERAL)
public interface AddNumbersIF extends Remote {
@WebMethod(operationName="add", action="urn:addNumbers")
@WebResult(name="return")
public int addNumbers(
@WebParam(name="num1")int number1,
@WebParam(name="num2")int number2) throws RemoteException, AddNumbersException;
@RequestWrapper @ResponseWrapper
@WebMethod
@WebResult(targetNamespace = "")
@RequestWrapper(localName = "addNumbers", targetNamespace = "http:// server.fromjava/",
className = "fromjava.client.AddNumbers")
@ResponseWrapper(localName = "addNumbersResponse", targetNamespace = "http://
server.fromjava/", className = "fromjava.client.AddNumbersResponse")
public int addNumbers(
@WebParam(name = "arg0", targetNamespace = "”) int arg0,
@WebParam(name = "arg1", targetNamespace = "”) int arg1)
throws AddNumbersException_Exception;
WS Programming
• Defining the SEI (Service Endpoint Interface)
• Marked with @WebService
• Declaring the methods which are the web service operations.
• Marked with @WebMethod
• Implementing the SIB (Service Implementation Bean)
• Defining the methods declared in the SEI.
• Publishing the WS:
• With core Java 6
• With Application Server (Glassfish)
• Let’s see a first example…
Time Server
• TimeServer is the SEI
• TimeServerImpl is the SIB
• A Java Application to publish the WS
(TimeServerPublisher)
• Testing the WS:
• With a Browser
• With SOAPUI
• Client Programming
TimeServer Client with wsimport
• Publishing the service ( and the associated wsdl )
• In the src directory:
wsimport -keep -p eser1.tsClient http://127.0.0.1:9877/ts?wsdl
• Easily create the tsClientFromWSDL
Let’s see how…
SERVICES IN
GLASSFISH
GlassFish
• An open source application server.
• Provides a fully-featured implementation of Java EE 6:
• JAX-WS
• JAX-RS
• JAXB
• EJB
• Web Container:
• deploys servlets and web services.
• Message-oriented middleware:
• supporting JMS (Java Message Service).
• RDBMS (Relational Database Management System)
• much more…
Apt (Annotation Processing Tool)
Usage: apt <apt and javac options> <source files>
-d <path>
where to place processor and javac generated class files
-s <path>
where to place processor generated source files
-nocompile
do not compile source files to class files
-print
print out textual representation of specified types
-factorypath <path>
where to find annotation processor factories
-factory <class>
name of AnnotationProcessorFactory to use;
Wsimport
wsimport [options] <WSDL_URI>
-b <path>
specify jaxws/jaxb binding files or additional schemas
-d <directory>
specify where to place generated output files
-keep
keep generated files
-p <pkg>
specifies the target package
-s <directory>
specify where to place generated source files
.war files
• Web Application archive file.
• Standard structure to respect:
AppName
WEB-INF
web deployment descriptor
web.xml
jax-ws deployment descriptor
sun-jaxws.xml
classes
SEI
META-INF
service implementation
jax-ws.xml
• Service Deployment descriptor:
• specifies where to find the concrete service implementation when a
service is invoked.
• name: name of the endpoint
• implementation: where to find the SIB
• url-pattern: must be equal to the one specified in web.xml
<?xml version="1.0" encoding="UTF-8"?>
<endpoints
xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version="2.0">
<endpoint
name="MyHello"
implementation="hello.HelloImpl"
url-pattern="/hello"/>!
</endpoints>
web.xml
• Web Application deployment descriptor
?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://
java.sun.com/j2ee/dtds/web-app_2_3.dtd">
<web-app>
<listener>
<listener-class>com.sun.xml.ws.transport.http.servlet.JAXRPCContextListener</listener-class>
</listener>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.JAXRPCServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
</web-app>
Exercise part 1
• Implement a service for exposing soccer team details.
• Use JAXWS annotations to generate and deploy the service
• The service should offer the following two methods:
• public Team getTeam(String name);
• public List<String> getTeams();
• Team should contain:
• The name of the team
• A list of players
• Each player should contain:
• The name of the player
• The number on the player’s shirt.
• Test the service with SOAPUI
Exercise part 2
• Use the WSDL exposed by the service to create a Java
client
• Use WSImport
• Use the Java client to print out to System.out
• The list of all the teams
• The details of the players that play for Spain
BINARY DATA
MTOM
• Message Transmission Optimization Mechanism (W3C)
• Used with XML-binary Optimized Packaging (XOP)
• Alternative to Soap with Attachments
• Efficiency refers to size of the message
• SwA: Base64 sends as text encoding leads to 33% increase in size
• MTOM: sends in original binary form
ServerSide
Just a new Annotation…
@MTOM
@WebService(endpointInterface = "server.ImageServer")
public class ImageServerImpl implements ImageServer {
…
}
Client Side
• Receiving doesn’t require anything since the WSDL
references an array of bytes…
• Sending needs to be programmatically enabled…
BindingProvider bp = (BindingProvider) service;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
A Simple ImageServer
@WebService
@SOAPBinding(style = Style.RPC)
public interface ImageServer {
@WebMethod Image downloadImage(String name);
@WebMethod String uploadImage(Image data, String fileName);
@WebMethod List<String> getImageNames();
}
HANDLERS
Handlers in JAX-WS
• Message interceptors plugged into the JAX-WS runtime.
• Both client-side and server-side.
• Used to do additional processing of inbound/outbound
messages.
• Client/Provider Authentication.
• Client/Provider Performance Monitor.
• Envelope/HTTP/Payload logging.
Protocol and Logical Handlers
Handler<C extends
MessageContext>
boolean handleMessage (C context)
boolean handleFault (C context)
void close (MessageContext context)
LogicalHandler<C extends
LogicalMessageContext>
SOAPHandler<C extends
SOAPMessageContext>
Set<QName> getHeaders()
• Protocol Handlers:
• may access or change the protocol specific aspects of the
message.
• Only SOAPHandler actually available.
• Logical Handlers:
• protocol-agnostic.
• act only on the payload of the message.
Message Context
• A bag of properties shared by:
• client, client run-time, client-side
handlers.
• provider, provider run-time,
provider-side handlers.
Map <String, Object>
MessageContext
Enum Scope
LogicalMessageContext
LogicalMessage getMessage()
SOAPMessageContext
Object[] getHeader(...)
Set<String> getRoles()
SOAPMessage getMessage()
void setMessage(SOAPMessage)
• Examples of properties:
• MESSAGE_OUTBOUND_PROPERTY (Boolean): specifies message
direction.
• INBOUND_MESSAGE_ATTACHMENTS (java.Util.Maps): access to the
inbound message attachments.
• OUTBOUND_MESSAGE_ATTACHMENTS (java.Util.Maps): access to
the outbound message attachments.
Handlers in practice
• Handlers are programmer-written class that contains
callbacks.
• Methods invoked by the JAX-WS runtime so that an application has
access to:
• the underlying SOAP for SOAPHandlers
• the payload for Logical Handlers.
• A Handler can be injected into the handler framework in
two steps:
• Create a Handler class (implemeting the *Handler interface) with
handleMessage() , handleFault() , close(). getHeaders() (only for
SOAPHandler).
• Place a handler within a handler chain.
• Through configuration file or code.
The RabbitCounter Example
• The RabbitCounter service has one operation
(countRabbits) that computes the Fibonacci numbers.
• a SOAP fault is thrown if the argument is a negative integer.
• The service, its clients, and any intermediaries are
expected to process SOAP headers:
• client injects a header block.
• intermediaries and the service validate the information in the
header block.
• generating a SOAP Fault if necessary.
• Two ways to throw SOAP faults:
• extend the Exception class and throw the exception
• throw a fault from a handler.
The RabbitCounter Example
• Injecting a Header Block into a SOAP Header.
• FibClient generates a request against the RabbitCounter.
• The client-side JWS libraries create a SOAP message that serves
as the request.
• The UUIDHandler callbacks are invoked.
• The handleMessage callback has access to the whole SOAP
message and injects a UUID (Universally Unique Identifier) value
into the header.
handler-chain.xml
Order of execution in handler chain
• Typically the top-to-bottom sequence of the handlers in
the configuration file determines the order of execution.
• With some exeptions:
• For outbound messages handleMessage and
handleFault in LogicalHandler execute before their
counterparts in SOAPHandler.
• For inbound messages handleMessage and handleFault
in SOAPHandler execute before their counterparts in
LogicalHandler.
Example
Handler-chain:
SH1
LH1
SH2
SH3
LH2
Inbound messages:
SH1
SH2
SH3
LH1
LH2
Outbound messages:
LH1
LH2
SH1
SH2
SH3
Configuring the Client-Side Handler
• With a configuration file:
In the ws-import generated class
FibC.RabbitCounterService simply add the annotation:
@HandlerChain(file = "handler-chain.xml")
• Or you can add the handler programmatically:
SEE FibClientHR
SOAP Fault
• In handler.fib.RabbitCounter a customized exception that
the @WebMethod countRabbits throws if it is invoked with
a negative integer as argument.
• SOAP Message:
Adding a Logical Handler to the Client
• To avoid the fault let’s add to the client the LogicalHandler
ArgHandler that:
• intercepts the outgoing requests.
• check the argument to countRabbits
• change the argument if it is negative.
• It uses a JAXBContext to extract the payload ( in this case
the body of the outgoing SOAP message).
• Get – Check - Change - Set the arg0 (the argument of
CountRabbits).
• Add ArgHandler in the handler-chain
Adding a Service-Side SOAP Handler
• To complete the example we need a service-side SOAP
handler to process the header block and throw a fault if
needed.
• see UUIDValidator
LAB EXERCISES
UEFA European League
• Requirements:
• Implement a Java Application which prints to the
console:
• All the city names where games are played
• All the players of all the qualified teams
• All the strikers of the Italian Team
• The data source is provided as a web-service.
• You can find the WSDL at:
http://footballpool.dataaccess.eu/data/info.wso?WSDL
Exercise part 3
• Change the teams service to use the data exposed by the
following UEFA European League web service
• http://footballpool.dataaccess.eu/data/info.wso?WSDL
Exercise part 4
• Implement a SOAP handler that timestamps and logs all
the requests made to the service
• Logging should occur on the client’s side and the log
should be saved to a local file.