WARNING: This tutorial is being written! Do not hesitate to report any errors or suggestions.
Quick access:
General concepts
SOAP (Simple Object Access Protocol) and WSDL (Web Service Description Language)
Presentation of the API JAX-WS
Deployment of a Web service in a web application
Calling a web service in Java
Exchanging objects through a Web service
A Web service is an object hosted by a HTTP server on which it is possible to invoke methods remotely. Each method call is made by carrying the value of parameters through a HTTP request (from the client post to the HTTP server) and by carrying the return value of the distant method considered through a HTTP response (from the server to the client). Another feature of the Web services is in the interoperability of the technology: whether the client code or the Web service, they can both be developed through different technologies (Java, .Net, PHP, ...).
In fact, the technology relating to the Web services is a recommendation from the W3C (World Wide Web Consortium: http://www.w3.org ). The W3C is a consortium of many companies with an interest in promoting and developing the Web technologies. The recommendation is the most successful level in the process of standardization of the W3C. the Web services represent a mature technology: as such, it is notably supported by the Java SE 6.0.
The advantage of this technology is to put the presented datas on the web available to physical persons (through the web pages) but also to some programs (through the Web services). We can therefore imagine two Web servers, for two different companies, exchanging datas through this technology with the aim of producing a single trading proposition and integrating informations from the two companies involved. In such a case the two servers exchange the information with simple calling methods (with parameters and values of return) on objects of type "web service".
The interest to host your Web services by an HTTP server lies in the fact that by default, the networks requests/responses are using the port 80. If between the client making the request and the server that provides the service, the network infrastructure used put in game firewalls or HTTP proxy, it will not create any problem because on these systems, the port 80 is normally open. You can also note that the use of the web services may allow you to build a SOA Architecture (Service Oriented Architecture).
With the Web services, the requests and the HTTP responses will contain some structured informations through the XML syntax (it is also a recommendation of the W3C). Don't remember that XML is a meta language: it is used to produce adapted languages to your needs, but based on a syntax with tags. For more informations on XML, i refer you to our XML tutorial.
Two XML languages (also known as XML grammar) are very important for the understanding for the running of the Web services. This is SOAP (Simple Object Access Protocol) and WSDL (Web Service Description Language).
SOAP makes it possible to structure the datas that will be exchanged between the service user and the provider (the Web service). Although we can consider other alternatives to XML, that choice can easily ensure the interoperability. Indeed, it exists any XML parsers on nearly all the platforms (Solaris, Linux, ...) and for all the languages (Java, C++, PHP, ...).
The interest of WSDL is a little more subtle to discern. Let's say, for simplicity that the two teams that will develop the Web service and the consumer code
of the Service, are not required to know one another. They can, moreover, be located anywhere on the earth, it will not hamper
for the proper functioning of the model. However, a calling method on a distant object, in the absolute, do not want to say anything: if we go down at
the machine code, we can say that a calling method can operate only within a single process (at least for the modern processors). So,
the call at the client application is made between your code and the local agent of the Web service. That local agent (often called
proxy - not to be confused with the HTTP proxy) allows us to "simulate" the distant call in the way that it behaves like the distant object. It
provides exactly the same methods, but their implementations are responsible for producing the HTTP communication. The question is to know how we generate
this local agent. This is where the WSDL is starting: this description of the accessible methods through this web service will use to a tool
(wsimport avec le Java SE 6.0) to generate the proxy. Moreover, the WSDL can be retrieved through a simple HTTP request on the service.
So yes, the two development teams may not know each other and not have discussed on how to use the Web service considered.
Historically, the first API that allowed the development of Web services with the Java language was JAX-RPC. This model was relatively heavy to implement and did not use the latest object technologies introduced in the Java SE 5.0 (i think, of course, the Java annotations). These considerations were successful in producing a second model for implementing the Web service.
It is now preferable to use the API JAX-WS (Java API for XML - Web Services), now in version 2.1. This API is mainly
localized in the package javax.jws. If you care to open the Javadoc on this package, you will find that it consists of a
certain number of annotations (javax.jws.WebService and particularly javax.jws.WebMethod). This is because the new
API of web services implementation is very simple to use: you just have to code a traditional Java class and to join it a certain
number of annotations to describe the methods which will be accessible through the outside.
For example, we will consider an application of online chat accessible through the Web. This application is divided into two separate parts:
the client bracket that displays the exchanged messages and the server component acting as the chat room. This is on this
last part that we will begin to focus our attention. The implementation, you will see, is relatively simple. Only one
class of type web service will be sufficient to encode the server part. We call this class ChatRoomServiceImpl. Note that
this class is part of the demonstration application of the Ellipse framework.
This class will include five methods accessible through HTTP: subscribe, unsubscribe, sendMessage,
getMessages and getUsers. Here's a quick description of the responsibility of each of these methods.
@WebMethod public synchronized void subscribe( String pseudo ): This method allows you to register to the chat room considered.
Effectively, HTTP is a disconnected protocol and, most importantly, the Web architecture will not allows you to an send information to the browser
(at least at the initiative of the HTTP server): so this is the client application which must periodically has to interrogate the chat room to see if
new messages have been received. The chatroom must memorize, for each user, the new messages that have been received.
Under the system, a user will be identified by his nickname.
@WebMethod public synchronized void unsubscribe( String pseudo ): unlike the previous one, this method allows to
unsubscribe someone from the chat room. From there, it is not necessary to memorize the new messages for this user.
@WebMethod public synchronized void sendMessage( String pseudo, String message ): this method is used by the client
afford him to send a message to the chat room. This method allows two parameters: the name and the message itself.
@WebMethod public synchronized ArrayList getMessages( String pseudo ): this method allows to find all the messages
received by this user since the previous invocation of the method getMessages. This method will be invoked periodically.
@WebMethod public synchronized ArrayList getUsers(): this one lets you retrieving all the users connected to the chat room.
This method will be invoked periodically.
Here is the complete code of the chat room class. Note the use of the JAX-WS annotations. You can also note that a static method
main is associated: it helps to launch the web service in stand-alone without necessarily requiring a HTTP server. This is very convenient
to test the web service.
01 package corelib.services.web.samples.virtualcaddy.webservices;
02
03 import java.util.ArrayList;
04 import java.util.Hashtable;
05
06 import javax.jws.WebMethod;
07 import javax.jws.WebService;
08 import javax.xml.ws.Endpoint;
09
10 @WebService(serviceName = "ChatRoomService", name = "ChatRoom")
11 public class ChatRoomServiceImpl {
12
13 private Hashtable<String, ArrayList<String>> userMessages =
14 new Hashtable<String, ArrayList<String>>();
15
16 @WebMethod public synchronized void subscribe( String pseudo ) {
17 sendMessage( "ChatRoom", "User " + pseudo + " connected" );
18 userMessages.put( pseudo, new ArrayList() );
19 }
20
21 @WebMethod public synchronized void unsubscribe( String pseudo ) {
22 userMessages.remove( pseudo );
23 sendMessage( "ChatRoom", "User " + pseudo + " disconnected" );
24 }
25
26 @WebMethod public synchronized void sendMessage( String pseudo, String message ) {
27 String fullMessage = pseudo + " >>> " + message;
28 System.out.println( fullMessage );
29 for ( ArrayList<String> array : userMessages.values() ) {
30 array.add( fullMessage );
31 }
32 }
33
34 @WebMethod public synchronized ArrayList<String> getMessages( String pseudo ) {
35 if ( pseudo == null ) return null;
36 ArrayList<String> messages = (ArrayList) userMessages.get( pseudo );
37 if ( messages == null ) return null;
38 userMessages.put( pseudo, new ArrayList() );
39 return messages;
40 }
41
42 @WebMethod public synchronized ArrayList<String> getUsers() {
43 ArrayList<String> users = new ArrayList();
44 if ( users == null ) return null;
45 for( String user : userMessages.keySet() ) users.add( user );
46 return users;
47 }
48
49 public static void main( String[] args ) {
50 // For standalone tests
51 Endpoint.publish( "http://localhost:8080/webapp/simple", new ChatRoomServiceImpl() );
52 }
53
54 }Warning: this code is a prototype: it could without difficulty be improved to enable it to run even deeper. For example, with this implementation, if two users are connected with exactly the same name, the things may not be fine.
To deploy the web service on a HTTP server (Tomcat in this case), two last stages are required. The first is to add a
configuration in the file WEB-INF/web.xml. The Ellipse framework operates two types of web components: the web pages (with an extension .wp) and
the web services (with an extension .ws). The proposed extensions are not imposed: if you want to change, you can. You could
even ensure that these two types of components use the same extension. But, the proposal that is made has the advantage of reminding us
immediately the file nature of which we have to do. Here is the minimum configuration for invoking a Web service (see lines
19 to 22).
01 <?xml version='1.0' encoding='UTF-8'?> 02 <!DOCTYPE web-app PUBLIC 03 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 04 "http://java.sun.com/dtd/web-app_2_3.dtd"> 05 <web-app> 06 07 <!-- Begin of file --> 08 09 <servlet> 10 <servlet-name>Ellipse Servlet</servlet-name> 11 <servlet-class>corelib.services.web.webapplications.ControllerServlet</servlet-class> 12 </servlet> 13 14 <servlet-mapping> 15 <servlet-name>Ellipse Servlet</servlet-name> 16 <url-pattern>*.wp</url-pattern> 17 </servlet-mapping> 18 19 <servlet-mapping> 20 <servlet-name>Ellipse Servlet</servlet-name> 21 <url-pattern>*.ws</url-pattern> 22 </servlet-mapping> 23 24 <!-- End of file --> 25 26 </web-app>
The second step is to define the file of extension .ws which will serve as a point of invoking the Web service (known as "end point").
This file looks, in some ways, to an Ellipse Web page in the sense that it referred to the class of the web service to use. Eventually, the
Ellipse framework is expected to add other informations in this file.
01 <?xml version="1.0" encoding="ISO-8859-1" ?> 02 <web:Service xmlns:web="corelib.services.web.webservices" 03 codeBehind="corelib.services.web.samples.virtualcaddy.webservices.ChatRoomServiceImpl" />
You can now deploy your Web application on your HTTP server. To test that the Web service is correctly deployed, you can invoke the following url: http://localhost:8080/VirtualCaddy/ChatRoom.ws?wsdl. If everything goes well, the WSDL of your service should be returned to you.
For those who have already tested the solutions for the deployment of web services under Metro (or Glassfish), you can note this: the generations of
the proxy server as well as the one of the WSDL (normally done through the tool wsgen provided by the Java SE) are completely automated here. It was at
the first invocation of the Web service that the missing informations will be produced. It follows an important point: to run, Ellipse
needs a Java SE 6.0 (not a JRE) otherwise the production tool wsgen will not be available.
We can now just use our web service. In the client part (Javascript) of the Ellipse tutorial, the Web service deployed in this document will be used through a web interface using Javascript to perform the calls on the methods carried by our web service. Nevertheless, we will only, at this time, to make some test calls in Java.
The first thing to do to code our client application is to generate the proxy client. To do so, the Java SE 6.0 brings at our disposition
the tool wsimport. This tool takes in the command line parameter the web address of the WSDL of your service. The following command line
should allows you to produce this proxy. Note that the files .class are directly
produced (you may also ask to obtain .java: option -keep).
wsimport http://localhost:8080/VirtualCaddy/ChatRoom.ws?wsdl
Then you need to encode your client application. In the example below, we concentrate us on the subscribe to the chat room, to send a message, to ask all our available messages, to list the connected users and finally to unsubscribe us from this chat room (all this sequentially).
01 import corelib.services.web.samples.virtualcaddy.webservices.*;
02 import java.util.*;
03
04 public class Client {
05
06 public static void main( String [] args ) {
07
08 ChatRoom room = new ChatRoomService().getChatRoomPort();
09 room.subscribe( "Donald" );
10 List users = room.getUsers();
11 for( Object user : users ) System.out.println( user );
12 room.sendMessage( "Donald", "Trop fort" );
13 List messages = room.getMessages( "Donald" );
14 for( Object message : messages ) System.out.println( message );
15 room.unsubscribe( "Donald" );
16
17 }
18
19 }Now you can compile your client application and execute it. Normally it should be connected properly to your web service. And you should pass on the messages in the log of the HTTP server used.
Web services can also allow you to exchange parameters (as well as a return value of method) of object type. To do this, the classes used for the exchanged data must provide a default constructor. If this is not the case, an exception will be triggered. Again, the demonstration application of the Ellipse framework offers you a small example of implementation: you will find here a web service that allows to retrieve an item presented in the catalog or, frankly, all the articles in this catalog. Here is the code of this web service.
01 package corelib.services.web.samples.virtualcaddy.webservices;
02
03 import javax.jws.WebMethod;
04 import javax.jws.WebService;
05
06 import corelib.services.web.samples.virtualcaddy.business.Article;
07 import corelib.services.web.samples.virtualcaddy.business.ArticleHome;
08
09
10 @WebService(serviceName = "CatalogBrowserService", name = "CatalogBrowser")
11 public class CatalogBrowserServiceImpl {
12
13 @WebMethod
14 public Article [] getAllArticles() {
15 return ArticleHome.findAll();
16 }
17
18 @WebMethod
19 public Article getArticle( int idArticle ) {
20 return ArticleHome.findByPrimaryKey( idArticle );
21 }
22
23 }It is important to understand that the Web service could be used by another language that Java (.NET, JavaScript, ...). The terminology for the exchange of objects may be a bit exaggerated. In fact, only the data objects will be transferred between the client and the web service (and not the methods, which the code is specific to a runtime environment). The client application will therefore seek to represent the objects of the web sevices, through any similar types, but that only expose the public properties of the servers objects.
|
|
|||||||