Exposing existing API as a Web service

28,929

Solution 1

It depends on whether or not you are using SOAP or REST. SOAP is more restrictive; as a result, it's more expected that you'll have a WSDL file to generate the classes that interface with the API.

On the other hand, if you are using REST, just exposing a RESTful URI would be considered enough to meet the constraint of a RESTful web service having a uniform interface.

REST tends to be gaining more ground over SOAP since it is a permissive architectural style. I would prefer this method, and I would recommend this method if you're new to developing web services.

Depending on what language you are using, I'm assuming Java, you can use Restlets or Spring 3.0's REST framework to help you build a RESTful web service. These tools really make that job a lot easier and help you conform to the 6 Constraints of a RESTful Web Service and meet the 4 Key Goals.

UPDATE:

Assuming you already have existing, object-oriented code, and assuming you want to expose that code as a REST API, using Spring 3.0 MVC, create a Controller subclass that will wrap around your existing package:

Example GET:

Resource: Javadocs for Jackson's ObjectMapper POJO/JSON Marshaller

 // this is the wrapper around your existing Java packages.  
 @Controller
 public class UserController {

     protected static final DATA_TYPE = "json";

     // In REST, GET method is used to retrieve data with no side effects, 
         // meaning that no changes are made to the data on the server.
     @RequestMapping(value="/users/{username}", method=RequestMethod.GET)
     public void getUserData(@PathVariable("username") String userName, Model model) {

         // this is your existing class
         UserDataService userDataService = new UserDataService();

         // assume you have a class User, and getUserDetails gives you that POJO object.
         User user = userDataService.getUserDetails(username);


         // marshal the User object to JSON, using Jackson, and write as output in response
         ObjectMapper mapper = new ObjectMapper();
         mapper.writeValue(response.getWriter(), user);

     }
 }

 // assume you have an existing POJO class called User
 class User implements Serializable {

     String username;
     String age;
     String birthday;
     String mood;

     String getMood() { return this.mood; }
     String getBirthday() { return this.birthday; }
     String getAge() { return this.age; }
     String getUsername() { return this.username; }

     String setMood(String mood) { this.mood = mood; }
     String setBirthday(String birthday) { this.birthday = birthday; }
     String setAge(String age) { this.age = age; }
     String setUsername(String username) { this.username = username; }
}

Request:

http://api.example.com:8080/users/jmort253/

Response:

{ 
    "username":"jmort253",
    "mood":"good",
    "age":"not too old and not too young",
    "birthday","Jan 1, 1900"
}

XML instead of JSON:

The main difference between returning XML and returning JSON is in the marshaller used. Using javax.xml.bind.annotations, you can place annotations on the POJO class so the marshaller can convert it to XML, freeing you up from the details of having to manually code XML by hand:

Using javax.xml.bind.annotations to convert Java Objects to XML and XSD. This resource also explains how to generate the XML Schema, if you deem that as a requirement to your REST Web service.

 @XmlRootElement
 class User implements Serializable {

     String username;
     String age;
     String birthday;
     String mood;

     String getMood() { return this.mood; }
     String getBirthday() { return this.birthday; }
     String getAge() { return this.age; }
     String getUsername() { return this.username; }

     String setMood(String mood) { this.mood = mood; }
     String setBirthday(String birthday) { this.birthday = birthday; }
     String setAge(String age) { this.age = age; }
     String setUsername(String username) { this.username = username; }
}

Instead of using the Jackson API's ObjectMapper class to marshal the POJO class to JSON, use the javax.xml.bind.annotations package in place of ObjectMapper:

JAXBContext context = JAXBContext.newInstance(User.class);
Marshaller marshaller = context.createMarshaller();

// pretty print XML
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
marshaller.marshal(user, System.out);

Aside from the other resources, this article has a few examples that use JAXB to deserialize an ArrayList of POJO objects to XML.

My final suggestion when working on the REST Web service wrappers is to set your logging levels to "ALL" or "DEBUG". I find that this helps me more easily determine the root cause of any problems I face when setting up a Web service. The libraries themselves will output helpful debug messages to help you resolve configuration issues, such as missing dependencies, missing annotations, and other issues that you'll likely encounter when dealing with the conversion to XML/JSON process or in setting up Spring 3.0.

Once you're uniform interfaces are setup and you can make GET requests and receive responses, you can then set the logging levels back to the previous INFO or WARN levels.

Solution 2

First of all, I would hesitate before exposing an existing API as a web service on a one-for-one basis. Was the existing API written to be accessed over a network? If not, then it was probably not designed with networking constraints in mind.

It may include method calls which will involve larger numbers of small operations - the kind that cost nothing when used within a single process. Over a network, each call has an associated latency that is much larger than the overhead of caling a method within the same process.

Instead, I would design a service to meet the functional requirements of the API. The service would likely be designed to have a smaller number of operations which perform more work per operation, thereby minimizing the overhead associated with network traffic. The service would likely be implemented by calling on the API (assuming it is written to handle multi-threaded environments like a service).

In terms of WSDL, the toolkit you are using may very well construct a WSDL for you. I know that WCF in .NET does that, and I have done the same using IBM Rational Web Developer, so I know that the Java world can do the same.

Otherwise, it's not actually that hard to hand-write a WSDL and corresponding schema. In either case, they do need to be provided so that your clients can consume the service.

There's nothing wrong with using REST for this if your API can be cleanly expressed as a set of operations on resources. In this case, yes, provide the schema to make it easier for your clients to process the XML. I would beware of forcing your API to fit the REST model if it is not cleanly expressible as operations on resources.

Share:
28,929
Subramanian
Author by

Subramanian

Updated on August 17, 2020

Comments

  • Subramanian
    Subramanian almost 4 years

    I am currently working on a task to expose an API as a Web service. The idea here is to package the existing business logic in JAR files into a WAR file and expose the WAR file as a Web service that would return a free-form XML string. When we expose an existing API as a Web service, is it sufficient that we make available an XSD & WSDL file of the returned XML string data? Is that the convention or the standard practice?

  • Subramanian
    Subramanian over 13 years
    Thanks for the response. Are you saying use REST approach to return xml string and provide the xsd so that the clients can "work with" the xml data returned. I am typically looking at a coarse-grained xml data - around 50-100K (in txt file)
  • John Saunders
    John Saunders over 13 years
    care to give an example of exposing an existing API as a REST service? You make it sound so easy.
  • jamesmortensen
    jamesmortensen over 13 years
    @John Saunders - The easiest sounding things are oftentimes the toughest. But I have definitely been able to more quickly expose REST web services than SOAP.
  • John Saunders
    John Saunders over 13 years
    so, it should be easy to give an example. Don't just assert it - show it.
  • John Saunders
    John Saunders over 13 years
    thanks. This looks good if the API is oriented towards resources like users. Any examples of other API types?
  • Subramanian
    Subramanian over 13 years
    Thanks for your detailed reply. I a thinking of a coarse grained service - the API itself is coarse-grained. The object being coarse grained has to "fit in" the REST model. Anyways, i do think there is enough of a lead/reference in this post for me to proceed. Thanks once again.
  • Mahdi
    Mahdi almost 10 years
    Thanks for the post. I know it is quite some time since you wrote this, but the links have changed apparently and I do not see the 4 Key Goals in the Wikipedia page.
  • jamesmortensen
    jamesmortensen almost 10 years
    @Mahdi - Thanks for the comment. It looks like they edited that section out on November 20th, 2013. Here is a link to the November 20th, 2013 revision of REST - Key Goals. Hope this helps.