Java Web Services: Up and Running, 1st Edition ... The reference framework for
Java Web Services ... Also available in the core Java Standard Edition 6.
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 -d where to place processor and javac generated class files -s 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 where to find annotation processor factories -factory name of AnnotationProcessorFactory to use;
Wsimport wsimport [options] -b specify jaxws/jaxb binding files or additional schemas -d specify where to place generated output files -keep keep generated files -p specifies the target package -s 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 !
web.xml • Web Application deployment descriptor ?xml version="1.0" encoding="UTF-8"?> com.sun.xml.ws.transport.http.servlet.JAXRPCContextListener hello com.sun.xml.ws.transport.http.servlet.JAXRPCServlet 1 hello /hello 60
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 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 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 boolean handleMessage (C context) boolean handleFault (C context) void close (MessageContext context)
LogicalHandler
SOAPHandler Set 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
MessageContext Enum Scope
LogicalMessageContext LogicalMessage getMessage()
SOAPMessageContext Object[] getHeader(...) Set 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.