In continuation to my previous post on REST-JSON Service Versioning here are my thoughts around service definition for REST-JSON.
Problem Statement:
As a service provider, one is obliged to document service contract (request/response) of the service exposed to consumers.
If you take SOAP/web-service world for an analogy, WSDL acts as a contract for the services exposed. This article is an attempt to see how a JSON schema can be exposed via a generic services/wrappers.
Note: I have chosen Spring MVC + Jackson Library as software stack for the solution approach.
Ex:
1. Let’s taken an example of Service below that returns an employee object, given an employee Id.
@Controller public class TestController { @RequestMapping(value="/employee", method=RequestMethod.GET) public ResponseEntityfetchEmployee(){ Employee employee = new Employee(); return new ResponseEntity (employee, HttpStatus.OK); } }
2. The Employee response object could look something like this,
public class Employee { private int employeeId; private String name; private long primaryNumber; public int getEmployeeId() { return employeeId; } public String getName() { return name; } public long getPrimaryNumber() { return primaryNumber; } }
Solution:
Based on the problem statement, the solution proposed below would seamlessly discover the REST-JSON services exposed in your application.
1. To do so, I have introduced an implementation/overridden class on top of Json Serialize/De-Serialize - DiscoverableService.java
/** * Extending DiscoverableService means the exposed service is enabled for auto * discovery. */ public abstract class DiscoverableService { /** * @return */ public ListgetAllExposedServiceInfo() { . . . . } }
2. Now any new service developed should extend DiscoverableService.java, to mark itself as exposed service for service discovery.
@Controller public class TestController extends DiscoverableService { @RequestMapping(value="/employee", method=RequestMethod.GET) public ResponseEntityfetchEmployee(){ Employee employee = new Employee(); return new ResponseEntity (employee,HttpStatus.O) } }
3. I have a controller/service exposed for the service discovery information, which is ServiceController.java.
Spring Auto wires all the controllers in the context that extend DiscoverableService to this controller class as shown below.
@Controller public class ServiceController { @Autowired protected ListdiscoverableServices; @RequestMapping(value = SERVICE_NAME, method = RequestMethod.GET) public synchronized ResponseEntity > fetchAllServiceInfo() { List
serviceInfos = new ArrayList (); for (DiscoverableService service : discoverableServices) { serviceInfos.addAll(service.getAllExposedServiceInfo()); } return new ResponseEntity >(serviceInfos, HttpStatus.OK); } }. . . .
4. Now comes the simple & final step, access your service information
http://localhost:8080/web-context/service/employee will return service definition for fetchEmployee service.
[{ "serviceURI": "/employee", "requestMethod": ["GET" ], "methodName": "class com.sample.controller.TestController.fetchEmployee()", "request": [ ], "response": { "employeeId": 0, "name": null, "primaryNumber": 0 }}]
5. http://localhost:8080/web-context/service - returns definition of all services exposed by the system.
Conclusion:
With the above approach, exposing service/contract definition to consumer will be seamless. Just sharing the service definition to the service consumer would do the trick.
2 comments:
Hi,
Can I ask why you didn't consider a mapping of WADL to JSON instead of creating your own description?
Also why you didn't make sure of the OPTIONS method to return a service definition and instead use an OOB URI to gather this information?
Thanks,
Gerard
Disclosure I have just been working on JSON/WADL and JSON-Schema generation for the Jersey project
Appreciate your comments.
As it sounds to me WADL is more of declarative, the approach I was trying to suggest is to pick the service definitions from the Annotations dynamically. And remove the hassles of .xml definition/declaration.
Post a Comment