Advanced Middleware: aspetti evolutivi a supporto di sistemi distribuiti e interoperabilità
3° modulo: Web Service con JAX-RPC Massimiliano de Leoni
JAX-RPC (1)
JAX-RPC stands for Java API for XML-based RPC. JAX-RPC is a technology for building Web services and clients that use remote procedure calls (RPC) and XML. In JAX-RPC, a remote procedure call is represented by an XML-based protocol such as SOAP. The SOAP specification defines the envelope structure, encoding rules, and conventions for representing remote procedure calls and responses. These calls and responses are transmitted as SOAP messages (XML files) over HTTP.
JAX-RPC (2) On the server side, the developer specifies
the remote procedures by defining methods in an interface written in the Java programming language. The developer also codes one or more classes that implement those methods. Client programs are also easy to code. A client creates a proxy (a local object representing the service) and then simply invokes methods on the proxy.
JAX-RPC (3)
Although SOAP messages are complex, the JAXRPC API hides this complexity from the application developer. With JAX-RPC, the developer does not generate or parse SOAP messages. It is the JAX-RPC runtime system that converts the API calls and responses to and from SOAP messages. With JAX-RPC, clients and Web services have a big advantage: the platform independence of the Java programming language.
JAX-RPC (4)
In addition, JAX-RPC is not restrictive: a JAX-RPC client can access a Web service that is not running on the Java platform, and vice versa. This flexibility is possible because JAX-RPC uses technologies defined by the World Wide Web Consortium (W3C): HTTP, SOAP, and the Web Service Description Language (WSDL). WSDL specifies an XML format for describing a service as a set of endpoints operating on messages.
JAX-RPC Web service
The starting point for developing a JAX-RPC Web service is the service endpoint interface. A service endpoint interface (SEI) is a Java interface that declares the methods that a client can invoke on the service. You use the SEI, the wscompile tool, and two configuration files to generate the WSDL specification of the Web service and the stubs that connect a Web service client to the JAX-RPC runtime. Together, the wscompile tool, the deploytool utility, and the Application Server provide the Application Server’s implementation of JAX-RPC.
Steps for creating the Web service and client: 9
9
Server 1. Code the SEI and implementation class and interface configuration file. 2. Compile the SEI and implementation class. 3. Use wscompile to generate the files required to deploy the service tra cui il WSDL. 4. Use deploytool to package the files into a WAR file. 5. Deploy the WAR file. The tie classes (which are used to communicate with clients) are generated by the Application Server during deployment. Client 1. Code the client class 2. Use wscompile to generate and compile the stub files. 3. Compile the client class. 4. Run the client.
Coding the SEI and Implementation Class A service endpoint interface must conform to a few
rules:
It extends the java.rmi.Remote interface. It must not have constant declarations, such as public final static. The methods must throw the java.rmi.RemoteException or one of its subclasses. Method parameters and return types must be supported JAX-RPC types (Tutorial Pages 332-334)
Telefono Example: SEI
The service endpoint interface is named TelefonoIF It declares a single method named public String getNumero(String abbonato). This method returns a string that is the concatenation of the string Hello with the method parameter. package Telefono; import java.rmi.Remote; import java.rmi.RemoteException; public interface TelefonoIF extends Remote {
public String getNumero(String abbonato) throws RemoteException; }
Telefono Example: Class
In addition to the interface, you’ll need the class that implements the interface. In this example, the implementation class is called TelefonoImpl: package Telefono; import java.rmi.Remote; import java.rmi.RemoteException; public class TelefonoImpl implements TelefonoIF { private static String elenco[][] = {...} public String getNumero(String abbonato) { for (int i=0;i<4;i++) if(elenco[i][0].equals(abbonato)) return(elenco[i][1]); return(""); } }
The wscompile tool / 1 The tool wscompile creates the WSDL and mapping
files. The WSDL file describes the Web service and is used to generate the client stubs in Static Stub Client. The mapping file contains information that correlates the mapping between the Java interfaces and the WSDL definition. The files created in this example are MyService.wsdl and mapping.xml
The wscompile tool / 2
wscompile is run with the following arguments: wscompile -define -mapping mapping.xml -classpath . config.xml
The -classpath flag instructs wscompile to read the SEI in current directory, and the -define flag instructs wscompile to create WSDL and mapping files. The -mapping flag specifies the mapping file name.
The wscompile tool / 3
The wscompile tool reads an interface configuration file that specifies information about the SEI. In this example, the configuration file is named config.xml and contains the following: <service name="MyService” targetNamespace="urn:Foo” typeNamespace="urn:Foo” packageName=“Telefono">
The wscompile tool / 4 This configuration file tells wscompile to create a
WSDL file named MyService.wsdl with the following information:
The service name is MyService. The WSDL target and type namespace is urn:Foo. The SEI is Telefono.Telefono.
The packageName attribute instructs wscompile to
put the service classes into the Telefono package.
Packaging and Deploying the Service Behind the scenes, a JAX-RPC Web service is
implemented as a Servlet. Because a Servlet is a Web component, you run the New Web Component wizard of the deploytool utility to package the service. During this process the wizard performs the following tasks:
Creates the Web application deployment descriptor Creates a WAR file Adds the deployment descriptor and service files to the WAR file
Packaging / 1 To start the New Web Component wizard, select File→New→Web
Component. 1. Introduction dialog box 1. 2.
Read the explanatory text for an overview of the wizard’s features. Click Next.
2. WAR File dialog box 1. 2.
Select the button labeled Create New Stand-Alone WAR Module. In the WAR Location field, click Browse a. b. c.
3.
Click Edit Contents to add WSDL, mapping and class files to WAR a. b.
4. 5.
navigate to whichever position you want to create WAR In the File Name field, enter TelefonoService. Click Create Module File. Select WSDL and mapping file and click on Add Select Telefono directory (where class files are located) and click on Add
Click OK. Click Next.
Packaging / 2 3.
Component Type dialog box 1. 2.
4.
Service dialog box 1. 2. 3.
5.
Select the Web Services Endpoint button. Click Next. In the WSDL File combo box, select WEBINF/wsdl/MyService.wsdl. In the Mapping File combo box, select mapping.xml. Click Next.
Component General Properties dialog box 1. 2.
In the Service Endpoint Implementation combo box, select Telefono.TelefonoImpl. Click Next.
Packaging / 3 6. Web Service Endpoint dialog box 1. In the Service Endpoint Interface combo box, select Telefono.Telefono. 2. In the Namespace combo box, select urn:Foo. 3. In the Local Part combo box, select TelefonoPort.
4. 5.
The deploytool utility will enter a default Endpoint Address URI TelefonoImpl in this dialog. This endpoint address must be updated in the next section. Click Next. Click Finish.
Specifying the Endpoint Address To access to service, We want client to specify this service
endpoint address URI: http://localhost:8080/alcatel/telefono The /hello-jaxrpc string is the context root of the servlet that implements the service. The /telefono string is the servlet alias. To specify the endpoint address, you set the context root and alias as follows: 1. In deploytool, select TelefonoService in the tree. 2. Select the General tab and in the Context Root field, enter alcatel. 3. In the tree, select TelefonoImpl and then select the Aliases tab. 4. In the component Aliases table, add /telefono. 5. In the Endpoint tab, select telefono for the Endpoint Address in the Sun-specific Settings frame. 6. Select File→Save.
Deploying the Service In DeployTool, perform these steps: 1. 2. 3. 4.
In the tree, select TelefonoService. Select Tools→Deploy. You can view the WSDL file of the deployed service by requesting the URL http://localhost:8080/alcatel/tel efono?WSDL in a Web browser.
Static Stub Client TelefonoClient is a stand-alone program
that calls the getNumero method of the deployed service. It makes this call through a stub, a local object that acts as a proxy for the remote service. Because the stub is created by wscompile at development time (as opposed to runtime), it is usually called a static stub.
The wscompile tool (client side) / 1 The wscompile tool creates the stub with the
following arguments:
wscompile -gen:client -classpath . config.xml
The -gen:client flag instructs wscompile to
generate the stubs, other runtime files such as serializers, and value types. The config.xml file contains the following: <wsdl location="http://localhost:8080/alcatel/telefono?WSDL" packageName="staticstub"/>
The packageName attribute specifies the Java
package for the generated stubs.
The wscompile tool (client side) / 2 The packageName attribute specifies the
Java package for the generated stubs.
Because -classpath . has been specified, this example will produce stub’s file in staticstub sub-directory starting from current directory
Notice that the location of the WSDL file is
specified as a URL. This causes the wscompile command to request the WSDL file from the Web service.
TelefonoClient’s code import staticstub.*; import javax.swing.*; public class HelloClient { public static void main(String[] args) { try { TelefonoIF stub= (TelefonoIF)(new MyService_Impl().getPort(TelefonoIF.class)); String abbonato=(String)JOptionPane. showInputDialog(null,"Specificare il nome di un abbonato:"); if (abbonato==null) return; String numero=stub.getNumero(abbonato); JOptionPane.showMessageDialog(null,numero, "Il numero richiesto",JOptionPane.INFORMATION_MESSAGE); System.exit(0); } catch (Exception ex) { ex.printStackTrace(); } } }
Compiling code In order to compile code, classpath must contains some jar file
located in lib directory of application server. They are the following ones: jaxrpc-impl.jar jax-qname.jar jaxrpc-api.jar So, classpath environment has to be updated as a consequence
or it can be specified at compile-time as compiler parameter: javac -classpath C:\Sun\AppServer\lib\jaxrpcimpl.jar;.;c:\Sun\AppServer\lib\jaxqname.jar;c:\Sun\AppServer\lib\jaxrpc-api.jar TelefonoClient.java
Packaging (client)
To start the New Application Client wizard, select File→New→Application Client. 1. Introduction dialog box 1. 2.
2.
Read the explanatory text for an overview of the wizard’s features. Click Next.
JAR File content box 1. 2.
Select the button labeled Create New Stand-Alone AppClient Module. In the AppClient Location field, click Browse a. b. c.
3.
Click Edit Contents to add class files to JAR a.
b.
4.
3.
Select staticstub directory (where client stub class files are located) and click on Add Select TelefonoClient file and click on Add
Click Next.
General box 1. 2.
4.
navigate to whichever position you want to create JAR In the File Name field, enter client.jar Click Create Module File.
Select TelefonoClient as Main Class Click Next.
Click Finish
Starting web client Move in directory where client.jar is
located and here execute the following command:
appclient –jar client.jar