Professional Documents
Culture Documents
Introduction
A webservice is a software system acknowledged by a URI, A Webservice is an application constituent accessible over open protocols, Webservices model follows the publish, find, and bind paradigm, Webservices ties together SOAP, WSDL, and UDDI to provide a simple plug-and-play interface for finding and invoking Webservices. Webservices are usually associated with SOAP. Using the REpresentational State Transfer architecture, REST is based on principles, which are used in the largest distributed application on the World Wide Web. Without intention there are many search engines, shops or booking systems that are already available as REST based Webservices. TheREpresentational State Transfer architecture is an architecture that describes how the Web should work. REST is neither a product nor a standard. The address space between REST and SOAP is a crucial difference. REST uses a global address space with URLs, over which each resource can be addressed. In REST, the resource is the center of attention. Each request to REST service from a client covers all the info and server does not grip client context in the session.
REST is stateless
HTTP is a protocol that treats each request as an independent transaction that is unrelated to any previous request so that the communication consists of independent pairs of requests and responses. Furthermore it does not require the server to retain session information or status about each communications partner for the duration of multiple requests. REST is an architectural style which is designed work upon HTTP and hence it is stateless. It requires each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. However there are exceptional cases where the architecture of an application demands saving session state with the service. The below sections talk about three ways to maintain state with REST.
the user and respond the accordingly. Infact not the REST, but the communication with REST becomes stateful here. For instance, below are two simple representations, the first representation is sent for logging in. <Login> <Name>centurylink.com</Name> <Password>rosewin#43445</Password> </Login> If you are logged in successfully you receive the below representation. <Login> <Success>true</Success> </Login> If you want to search for customer, you would need to send the below representation stating that you are in a state of successful logging in and would like to search all customers. <Customer> <Filter>All</Filter> <Success>true</Success> </Customer> In other words, every request is independent and the server does not need to remember your previous request and states. This is achieved in REST using the standard HTTP methods. The following list describes the meaning of the HTTP methods and how they are used by REST.
Method GET
POST
PUT DELETE
Description GET queries the representation of a resource. The execution of requests should be free from side effects. GET requests can be sent arbitrarily often. You cannot blame the client for effects caused by GET requests. That means a GET can be sent heedlessly. With POST you can change the state of a resource. For example you can add a good to a shopping cart. POST isn't free from side effects. For example you can change fields in a data base or start a new process on the server with a POST request. New resources can be produced with PUT or you can replace the content of existing resources. Resources can be deleted using DELETE.
Example scenario:
Public class CalculatorImpl implements Provider { @Resource protected WebServiceContext wsContext; public Source invoke(Source request) { try { } catch(Exception e) { e.printStackTrace(); throw new HTTPException(500); } } } For this example, the Calculator Webservice will accept requests by extracting the numbers to be added from either the URL path or from an HTTP query. The query string and path string can be retrieved from the MessageContext which is retrieved from the WebServiceContext wsContext that will be injected into the Calculator object. The following code can be used to retrieve the PATH_INFO from the URL and check to see if it is in the proper format. String path = (String)mc.get(MessageContext.PATH_INFO); if (path != null && path.contains("/num1") && path.contains("/num2")) { return prepareResultSource(path); }
The prepareResultSource(String str) method simply creates a Source object from a properly formatted MessageContext.PATH_INFO string, by extracting the two numbers to be added from the path and adding them together and calling the prepareResultSource(int sum)method. The source for these two methods is: private Source prepareResultSource(String str) { StringTokenizer st = new StringTokenizer(str, "=&/"); String token = st.nextToken(); int number1 = Integer.parseInt(st.nextToken()); st.nextToken(); int number2 = Integer.parseInt(st.nextToken()); int sum = number1+number2; return prepareResultSource(sum); } private Source prepareResultSource(int sum) { String body = "<ns:calculatorResponse xmlns:ns="http://java.duke.org"><ns:return>" +sum +"</ns:return></ns:calculatorResponse>"; Source source = new StreamSource( new ByteArrayInputStream(body.getBytes())); return source; }
So the example invokes method looks like the following. public Source invoke(Source source) { try { MessageContext mc = wsContext.getMessageContext(); // check for a PATH_INFO request String path = (String)mc.get(MessageContext.PATH_INFO); if (path != null && path.contains("/num1") && path.contains("/num2")) { return prepareResultSource(path); } throw new HTTPException(404); } catch(Exception e) { e.printStackTrace(); throw new HTTPException(500); } } You will notice that if the proper MessageContext.PATH_INFO is not found, the example throws a HTTPException(404). Instead of throwing this exception, the example endpoint can instead check the query string for the method arguments. Like the MessageContext.PATH_INFO, the query string can be retrieved from the MessageContext with the following code. String query = (String)mc.get(MessageContext.QUERY_STRING); Given this you can either pass the query string to the prepareResultSource(String str) method which will parse the parameters from the query string or you can use the standard ServletRequest object to extract the query arguments if you are deploying to a servlet container. If you were to deploy a Java SE based endpoint you should have to use the MessageContext.QUERY_STRING. The following code extracts the num1 and num2 query values, adds them together and invokes the prepareResultSource(int sum) method to create the Source object that will be returned from the invoke method. ServletRequest req = (ServletRequest)mc.get(MessageContext.SERVLET_REQUEST); int num1 = Integer.parseInt(req.getParameter("num1")); int num2 = Integer.parseInt(req.getParameter("num2")); return prepareResultSource(num1+num2); To finish off the Calculator, you need to declare some annotations on the class that instructs the JAX-WS runtime how to use this class. The @WebServiceProvider annotation specifies that this class is a Provider based endpoint rather than a service endpoint implementation class that would be annotated with @WebService. The final annotation to be added is @BindingType(value=HTTPBinding.HTTP_BINDING). This annotation specifies that Calculator endpoint should be published using the HTTPBinding.HTTP_BINDING as opposed to a SOAPBinding.SOAP11HTTP_BINDING or a SOAPBinding.SOAP12HTTP_BINDING binding
@WebServiceProvider @BindingType(value=HTTPBinding.HTTP_BINDING) public class CalculatorImpl implements Provider { @Resource protected WebServiceContext wsContext; public Source invoke(Source source) { try { MessageContext mc = wsContext.getMessageContext(); // check for a PATH_INFO request String path = (String)mc.get(MessageContext.PATH_INFO); if (path != null && path.contains("/num1") && path.contains("/num2")) { return prepareResultSource(path); } String query = (String)mc.get(MessageContext.QUERY_STRING); System.out.println("Query String = "+query); ServletRequest req = (ServletRequest)mc.get(MessageContext.SERVLET_REQUEST); int num1 = Integer.parseInt(req.getParameter("num1")); int num2 = Integer.parseInt(req.getParameter("num2")); return prepareResultSource(num1+num2); } catch(Exception e) { e.printStackTrace(); throw new HTTPException(500); } } private Source prepareResultSource(String str) { StringTokenizer st = new StringTokenizer(str, "=&/"); String token = st.nextToken(); int number1 = Integer.parseInt(st.nextToken()); st.nextToken(); int number2 = Integer.parseInt(st.nextToken()); int sum = number1+number2; return prepareResultSource(sum); } private Source prepareResultSource(int sum) { String body = "<ns:calculatorResponse xmlns:ns="http://java.duke.org"><ns:return>" +sum +"</ns:return></ns:calculatorResponse>"; Source source = new StreamSource( new ByteArrayInputStream(body.getBytes())); return source; } } To deploy the endpoint on a servlet container running with the JAX-WS RI you need to create a WAR file. The WAR file needs a very simple web.xml file to configure the JAX-WS RI servlet. The following will work.
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"> <listener> <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener </listener> <servlet> <servlet-name>restful-calculator</servlet-name> <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>restful-calculator</servlet-name> <url-pattern>/calculator/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>60</session-timeout> </session-config> </web-app> Next you can add a sun-jaxws.xml deployment descriptor to the WAR file. The following is an example. <endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0"> <endpoint name="restful-calculator" implementation="restful.server.calculatorImpl" wsdl="WEB-INF/wsdl/calculator.wsdl" url-pattern="/calculator/*" /> </endpoints>
You will notice that a wsdl file is specified sun-jaxws.xml deployment descriptor. This is currently necessary to tell the JAX-WS RI not to try to generate a WSDL for this endpoint. The contents of calculator.wsdl are simply the following. <?xml version="1.0" encoding="UTF-8"?> <definitions> </definitions> Once the calculator endpoint has been deployed, you can test it by entering the following URLs into a browser (slight modifications maybe necessary depending on your own configuration).
http://localhost:8080/jaxws-restful/calculator/num1/10/num2/20
http://localhost:8080/jaxws-restful/calculator?num1=10&num2=50
@POST @Path("/atom-count/") public List<Category> getCategories(JAXBElement<Category> cat) { ..... ..... ..... return categories; }
Conclusion
As we know Websevices are widely used over internet and its performance is became an important factor. REST only uses ripe standards such as HTTP or URLs, which are available already for some years. It takes advantage of well-known ideas used in the web such as hypertext and an unbounded, global address space. REST is designed to be stateless since HTTP is stateless. However there could be exceptional situations arise where the service has to maintain state to support specific architecture of an application. Here the decision to choose how to make it stateful has to be made elegantly considering its advantages and disadvantages.