Full Stack Web Development Internship Program
- 29k Enrolled Learners
- Weekend/Weekday
- Live Class
A Web Service is an application deployed on a machine (server). Web services accept incoming requests from client and send response to client in either plain text, JSON or XML format.
The beautiful thing about web services is they are language independent. So a web service written in Python can be requested from a client written in Java, C#, Ruby etc.
Web services are classified into two categories:
Java provides API for creating both SOAP and REST-style web services
JAX-WS – JAX-WS (Java API for XML Web Services) is a Java API for creating both SOAP and REST-style web services. There is a common misconception that JAX-WS is only for SOAP-based services, which is not true. Using JAX-WS you can create both SOAP and REST-style services
JAX-RS – JAX-RS (Java API for RESTful Web Services) is a Java API to write RESTful web services easily
Note : Although JAX-WS can be used to write RESTful web services, it’s not the best way to create REST-style services. In a production mode you should probably use JAX-RS, Restlet framework etc.
Now, let’s see how to create a RESTful weather service using JAX-WS API.
We will write a weather service which takes a city name as parameter and returns the weather detail as an XML document. We will use weather service of Open Weather Map.
Now, let’s dive into the code.
Here is the Project structure in Eclipse IDE
RESTfulWeather class implements the weather service which will be published by WeatherPublisher class
@WebServiceProvider @ServiceMode(value = javax.xml.ws.Service.Mode.MESSAGE) @BindingType(value = HTTPBinding.HTTP_BINDING) public class RESTfulWeather implements Provider { @Resource protected WebServiceContext wsContext; @Override public Source invoke(Source request) { MessageContext msg_cxt = wsContext.getMessageContext(); String httpMethod = (String) msg_cxt .get(MessageContext.HTTP_REQUEST_METHOD); //System.out.println("Http Method : " + httpMethod); if (httpMethod.equalsIgnoreCase("GET")) { return doGet(msg_cxt); } return null; } private Source doGet(MessageContext msg_cxt) { String query_string = (String) msg_cxt.get(MessageContext.QUERY_STRING); StringBuffer text=new StringBuffer(""); String cityName=query_string.split("=")[1]; try { URL url = new URL( "http://api.openweathermap.org/data/2.5/weather?q="+cityName+"&mode=xml"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.connect(); BufferedReader bReader = new BufferedReader(new InputStreamReader( urlConnection.getInputStream())); String line = null; while ((line = bReader.readLine()) != null) { text=text.append(line); } } catch (Exception e) { e.printStackTrace(); } return new StreamSource( new StringReader(text.toString()) ); } }
Let’s drill down into the code line by line.
We have annotated the class with @WebServiceProvider, which means exchanged messages will be XML document. Weather service implements the generic provider interface rather than a customized Service Endpoint Interface (SEI).
The annotation @ServiceMode with value MESSAGE indicates that the service wants access to the entire message (For example, HTTP headers and body). BindingType annotation declares that this service deals with raw XML over HTTP instead of SOAP over HTTP.
In the invoke method, we first retrieve the MessageContext from WebServiceContext. We then check the request method for the incoming request and if it is GET, we call it the doGet method passing the MessageContext. Then we extract the value of the city parameter from the query string and call it the OpenWeatherMap service which returns an XML document.
Note: We store the returned XML document in a StringBuffer.
How to get a source type from a StringBuffer
return new StreamSource( new StringReader(text.toString()) );
The above line will return a StreamSource from a StringBuffer instance text.
We are all done with the weather service. Now let’s publish the service.
WeatherPublisher.java
import javax.xml.ws.Endpoint; public class WeatherPublisher { public static void main(String[] args) { System.out.println("Publishing Weather Service"); Endpoint.publish("http://127.0.0.1:8700/weather",new RESTfulWeather()); } }
Accessing the Web Service
Let’s access the weather service giving it a city name. We can check the weather for Seoul
We get an XML document as the response with information on latitude, longitude, temperature, humidity , wind, clouds etc.
As our weather service is up and running, it’s time to write a client which will use this service.
Writing a client against weather service
Since weather service returns an XML document as a response, any client that uses the web service will have to parse that XML document. Below is the Java client written against the weather service
import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class WeatherClient { public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException { // GET requests URL url=new URL("http://127.0.0.1:8700/weather?city=seoul"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.connect(); String xml = ""; BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); String next = null; while ((next = reader.readLine()) != null) xml += next; SAXParser parser =SAXParserFactory.newInstance().newSAXParser(); SaxParserHandler handler=new SaxParserHandler(); parser.parse(new ByteArrayInputStream(xml.getBytes()),handler); System.out.println("-------------------------------------------------------------------"); System.out.println(handler.city+" weather update on "+handler.lastUpdate); System.out.println("-------------------------------------------------------------------"); System.out.println("City : "+handler.city); System.out.println("Latitude : "+handler.latitude); System.out.println("Longitude : "+handler.longitude); System.out.println("Mininum Temperature (Celsius) : "+handler.minTemperature); System.out.println("Maximum Temperature (Celsius) : "+handler.maxTemperature); System.out.println("Wind : "+handler.wind); System.out.println("Clouds : "+handler.clouds); } } class SaxParserHandler extends DefaultHandler{ String city; String latitude; String longitude; float minTemperature; float maxTemperature; String wind; String clouds; String lastUpdate; public void startElement(String namespaceURI,String localName,String qname,Attributes attributes){ if(qname.equals("city")){ city=attributes.getValue("name"); }else if(qname.equals("coord")){ latitude=attributes.getValue("lat"); longitude=attributes.getValue("lon"); } else if(qname.equals("temperature")){ String minKelvin=attributes.getValue("min"); minTemperature=Math.round(Float.parseFloat(minKelvin)) - 272; String maxKelvin=attributes.getValue("max"); maxTemperature=Math.round(Float.parseFloat(maxKelvin)) - 272; } else if(qname.equals("speed")){ wind=attributes.getValue("name"); } else if(qname.equals("clouds")){ clouds=attributes.getValue("name"); } else if(qname.equals("lastupdate")){ lastUpdate=attributes.getValue("value").split("T")[0]; } } }
Note : WeatherClient uses SAX parser to parse the response from the service. If you are not very familiar with parsing XML files in Java, here is an article that explains how to parse XML files using SAX parser.
You can also use a DOM or StAX parser for parsing the XML document.
Output
Below is the output that you will get on executing the WeatherClient class
A Word of Caution :
Let’s iterate through what we said earlier, JAX-WS is not the right choice for implementing real-world RESTful services. For writing real-world RESTful web services JAX-RS, Restlet or Spring framework is the way to go.
Curious to try the code yourself? Download the code.
[buttonleads form_title=”Download Code” redirect_url=https://edureka.wistia.com/medias/jqusavrxbs/download?media_file_id=79202719 course_id=44 button_text=”Download Code”]
Getting java.net.BindException: If you are trying to publish the web service on a port that is already in use you will get java.net.BindException
Caused by: java.net.BindException: Address already in use: bind
To get rid of the exception just use some other port for publishing the web service.
Got a question for us? Please mention it in the comments section and we will get back to you.
Related Posts:
Course Name | Date | Details |
---|---|---|
Java Course Online | Class Starts on 7th December,2024 7th December SAT&SUN (Weekend Batch) | View Details |
edureka.co
Hi can you explain server connections