Retrieving XML response using Spring web client, demo with yahoo finance API client

As i am learning and exploring Spring framework i am sharing the knowledge i am gaining with you.

The steps involved in creating a request with the required format and getting the response in the expected format (XML in this example) is shown below. I am using Spring’s RestTemplate class to create request and retrieve response. To demonstrate this the below web client is issuing a RESTful query to yahoo.finance.quotes YQL(Yahoo Query Language) web server, to get quotes for a given symbol. As you would see below in the code we need to configure a unmarshaller/marshaller to be used by the client web application to convert the XML response into an Object representation (and marshaller for the reverse transformation). There are quite a few marshaller/unmarshaller available. The code below shows usage of 2 of them, JAXB(Java Architecture for XML Binding) and XStream.


@Autowired
RestTemplate rTemplate;

@RequestMapping(value="/getquotex", method=RequestMethod.GET)
public @ResponseBody Query retrievexml(String requestedSymbol) {
  String env = “store://datatables.org/alltableswithkeys”;
  String symbolString = “(” + requestedSymbol + ”)";
  String queryStr = "SELECT * from yahoo.finance.quotes where symbol in ";
  String restUrl = "http://query.yahooapis.com/v1/public/yql?q={qid}{symbol}&env={senv}";
  Query qresponse = rTemplate.getForObject(restUrl, Query.class, queryStr,symbolString,env);
  return qresponse;
}

The above piece of code requries these dependencies to be configured for it to work. Also shown later in this article is the classes that make up the Object that represent the XML data as retrieved from YQL server for the stock quote.

Add the following dependency (Maven dependency shown below) needed to use any OXM (Object to XML mapping) feature in Spring.


<!--Object-to-XML Mapping (OXM) abstraction and integration with JAXB, JiBX, Castor, XStream, and XML Beans  -->

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${org.springframework-version}</version>
</dependency>

//org.springframework-version - is the version of Spring that you are using.

Using JAXB2:

1) Define RestTemplate in the xml file that defines the client applications root application context. It is the xml file at the location “contextConfiguration” as mentioned in the web.xml file.

Marshall and Unmarshall using JAXB2 (Java Architecture for XML Binding)


<bean id="rTemplate">
  <property name="messageConverters">
    <list>
      <bean id="messageConverter">
        <property name="marshaller" ref="jaxb2Marshaller"/>
        <property name="unmarshaller" ref="jaxb2Marshaller"/>
      </bean>
    </list>
  </property>
</bean>

<!-- If using Jaxb2Marshaller as MarshallingHttpMessageConverter -->

<bean id="jaxb2Marshaller"class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  <property name="classesToBeBound">
    <list>
      <value>com.mytwocents.StockRestWeb.Query</value>
      <value>com.mytwocents.StockRestWeb.Result</value>
      <value>com.mytwocents.StockRestWeb.Quote</value>
    </list>
  </property>
</bean>

2) If using Maven (In STS – SpringSource Tool Suite for development add it to pom.xml)


<!-- JAXB2.x for XML binding -->

<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.3-1</version>
</dependency>

Using XStream:

1) The applications xml file defining the root context will have the below configuration if using XStream for marshalling and unmarshalling.


<bean id="rTemplate">
  <property name="messageConverters">
    <list>
      <bean id="messageConverter">
        <property name="marshaller" ref="xstreamMarshaller"/>
        <property name="unmarshaller" ref="xstreamMarshaller"/>
      </bean>
    </list>
  </property>
</bean>

<!-- If using XStream as MarshallingHttpMessageConverter -->

<bean id="xstreamMarshaller"class="org.springframework.oxm.xstream.XStreamMarshaller">
  <propertyname="annotatedClasses">
    <list>
      <value>com.mytwocents.StockRestWeb.Query</value>
      <value>com.mytwocents.StockRestWeb.Result</value>
      <value>com.mytwocents.StockRestWeb.Quote</value>
    </list>
  </property>
  <propertyname="autodetectAnnotations"value="true"></property>
</bean>

2) If using maven dependencies management


<!-- For HierarchicalStreamReader access in OXM -->

<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.2</version>
</dependency>

The xml returned has the following structure.


<query>
  <results>
    <quote symbol="FB">
      <LastTradeDate>7/10/2012</LastTradeDate>
      <PreviousClose>32.17</PreviousClose>
      <Ask>31.74</Ask>

....

    </quote>
  </results>
</query>

Classes that make up the Object that represent the XML data retrieved from YQL server for the stock quote:

NOTE: The below code shows annotations for both JAXB2 and XStream. However the annotations are active and are parsed only when their usage is configured to be used in the applications root context xml file. Otherwise they are not parsed. So, for example if the application is configured to use JAXB2 then only JAXB2 annotations are parsed and XStreamAnnotations are not parsed. The presence of XStreamAnnotations in that case is harmless in the code (and vice-versa is true as well.)


import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XmlRootElement(name="query")
@XStreamAlias("query")
public class Query {

@XStreamAlias("results")
private Result result;

Query() {

}

@XmlElement(name="results")
public Result getResult() {
  returnresult;
}

public void setResult(Result result) {
  this.result = result;
}

}

import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;

@XmlRootElement(name="results")
@XStreamAlias("results")
public class Result {

@XStreamImplicit(itemFieldName="quote")
private List<Quote> quote;

Result() {

}

@XmlElement
public List<Quote> getQuote() {
  returnquote;
}

publicvoid setQuote(List<Quote> quote) {
  this.quote = quote;
}

}

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;

@XmlRootElement(name="quote")
@XStreamAlias("quote")
public class Quote {

private String Symbol;
private String LastTradeDate;
private String Open;
private String PreviousClose;
private String Ask;

//more fields in the class goes here

Quote() {

}

@XmlAttribute(name="symbol")
public String getSymbol() {
  returnSymbol;
}

publicvoid setSymbol(String symbol) {
  Symbol = symbol;
}

@XmlElement(name="LastTradeDate")
public String getLastTradeDate() {
  returnLastTradeDate;
}

publicvoid setLastTradeDate(String lastTradeDate) {
  LastTradeDate = lastTradeDate;
}

@XmlElement(name="Open")
public String getOpen() {
  return Open;
}

public void setOpen(String open) {
  Open = open;
}

@XmlElement(name="PreviousClose")
public String getPreviousClose() {
  return PreviousClose;
}

public void setPreviousClose(String previousClose) {
  PreviousClose = previousClose;
}

@XmlElement(name="Ask")
public String getAsk() {
  return Ask;
}

public void setAsk(String ask) {
  Ask = ask;
}

//more getters/setters in the class goes here

}

2 Responses to Retrieving XML response using Spring web client, demo with yahoo finance API client

  1. Vijay says:

    Thanks. This is really helpful..

  2. Pingback: Live stock quote listing using GWT and Spring « mytwocentsads

Leave a comment