info.sswap.api.servlet
Class AbstractSSWAPServlet

java.lang.Object
  extended by javax.servlet.GenericServlet
      extended by javax.servlet.http.HttpServlet
          extended by info.sswap.api.servlet.AbstractSSWAPServlet
All Implemented Interfaces:
java.io.Serializable, javax.servlet.Servlet, javax.servlet.ServletConfig
Direct Known Subclasses:
info.sswap.ontologies.exec.impl.ExecImpl, LegacyServiceWrapperServlet, SimpleSSWAPServlet

public abstract class AbstractSSWAPServlet
extends javax.servlet.http.HttpServlet

Handles HTTP GETs and POSTs to a SSWAP service point. This class is a bridge between handling a HTTP request and the SSWAP Java API that allows on-demand, transaction-time reasoning to satisfy the request.

Note: A simple way to implement a service without the constraints and subtleties of servlet programming is to use a servlet launcher to launch a regular Java class. For most developers this is the recommended way; see SimpleSSWAPServlet and MapsTo

To use, extend this abstract class and override the handleRequest method. When an Resource Invocation Graph ( RIG) is sent to the servlet, handleRequest will allow action on the RIG to create a Resource Response Graph ( RRG) to be returned back to the client. The RIG supports a translate method to allow semantic mapping of the RIG into the vocabulary and concepts of the service's Resource Description Graph (RDG).

Upon return from handleRequest, this class generates an RRG which is serialized back to the client.

The servlet responds to HTTP GETs and POSTs in the following manner:

GET query string parameters (e.g., http://.../MyService?property=value&prefix:property=value2) are converted into service parameters according to the following rules:

By default, property=value assignments are matched against statements on the RDG's SSWAPSubjects. To instead force a match against the SSWAPResource properties, prepend a tilde (~) immediately before the prefix or property: e.g., ~property=value or ~prefix:property=value. The tilde (~) is a query string flag only: it is not part of the property name.

To use the servlet, create a typical mapping in your servlet container's web.xml file, such as:

 <servlet>
   <servlet-name>MyServlet</servlet-name>
 
     <servlet-class>org.mySite.sswap.MyServlet</servlet-class>
 
     <!-- if not defined, will be derived from <url-pattern>
     <init-param>
       <param-name>RDGPath</param-name>
       <param-value>/pathTo/MyRDG</param-value>
     </init-param>
     -->
 </servlet>
 
 <servlet-mapping>
   <servlet-name>MyServlet</servlet-name>
   <url-pattern>/MyService/*</url-pattern> <!-- always end in /* -->
 </servlet-mapping>
 
 
Replace and customize the values for <servlet-name>, <servlet-class>, <param-value>, and <url-pattern> per usual web.xml practices. All other values should be as above. In the above example, MyServlet extends AbstractSSWAPServlet and defines handleRequest. The use and definition of RDGPath is optional but recommended. If it is not defined, then the RDG must reside at the request URI; if it is defined, then its value must be the path to a valid RDG on the local web server.

Error handling:
If an error is due to a client misconfigured RIG, then an error message is returned to the client and set in the HTTP header. An RRG is not returned to the client. But if the RIG passes validation--both syntactically as OWL RDF/XML, and semantically as being complaint with the RDG--but yet an error occurs on the server-side, then the RIG is returned to the client without semantic modification (still, no RRG).

Author:
Damian Gessler
See Also:
handleRequest(info.sswap.api.model.RIG), SimpleSSWAPServlet, MapsTo, RDG, RIG, RRG, SSWAPResource, SSWAPSubject, Serialized Form

Field Summary
protected  java.net.URI remoteServiceURI
          URI to be called to pass on service invocation to a remote service.
static java.lang.String RRG_RETRIEVAL_SUFFIX
          The suffix to the request string for RRG retrieval; that is, if a request ends with this suffix (attached to the regular service's URL), it indicates that the request is for retrieving a cached RRG, and not invoking the service.
 
Constructor Summary
AbstractSSWAPServlet()
           
 
Method Summary
protected  void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
          An HTTP GET equates to returning an RDG or creating a just-in-time RIG from the query string and invoking this service.
protected  void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response)
          An HTTP POST equates to a request service invocation.
 int getTimeout()
          The servlet timeout value, in milliseconds.
protected abstract  void handleRequest(RIG rig)
          Override this method to convert an incoming Resource Invocation Graph RIG into an outgoing Resource Response Graph RRG.
 void init(javax.servlet.ServletConfig servletConfig)
          Override this method (or GenericServlet.init() for custom servlet initialization code.
 void setTimeout(int timeout_ms)
          Set servlet timeout value, in milliseconds.
 
Methods inherited from class javax.servlet.http.HttpServlet
doDelete, doHead, doOptions, doPut, doTrace, getLastModified, service, service
 
Methods inherited from class javax.servlet.GenericServlet
destroy, getInitParameter, getInitParameterNames, getServletConfig, getServletContext, getServletInfo, getServletName, init, log, log
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

RRG_RETRIEVAL_SUFFIX

public static final java.lang.String RRG_RETRIEVAL_SUFFIX
The suffix to the request string for RRG retrieval; that is, if a request ends with this suffix (attached to the regular service's URL), it indicates that the request is for retrieving a cached RRG, and not invoking the service.

See Also:
Constant Field Values

remoteServiceURI

protected java.net.URI remoteServiceURI
URI to be called to pass on service invocation to a remote service. Only used when this servlet is extended, as by SSWAPProxyServlet, which sets the value to non-null.

Constructor Detail

AbstractSSWAPServlet

public AbstractSSWAPServlet()
Method Detail

init

public void init(javax.servlet.ServletConfig servletConfig)
          throws javax.servlet.ServletException
Override this method (or GenericServlet.init() for custom servlet initialization code. If overriding this method, overriding method MUST call super.init(servletConfig) as the first line of code. This method is called once at the end of all internal initialization and before any requests are serviced.

The method is passed the Servlet Configuration and may throw a ServletException. Thrown errors are not caught and will terminate servlet initialization.

Uses for this method are to set the servlet timeout (see setTimeout(int)), effect changes to URI caching (see SSWAP.getCache()), and so forth.

Specified by:
init in interface javax.servlet.Servlet
Overrides:
init in class javax.servlet.GenericServlet
Parameters:
servletConfig - the ServletConfig object of the servlet
Throws:
javax.servlet.ServletException - on a servlet configuration error
See Also:
SSWAP, ServletConfig

getTimeout

public int getTimeout()
The servlet timeout value, in milliseconds.

Returns:
the timeout value, or -1 on any error that precludes retrieving a value

setTimeout

public void setTimeout(int timeout_ms)
Set servlet timeout value, in milliseconds. Increase this value if the web service needs additional time to complete.

Timeout values less than 1000 (1 sec) are silently ignored.


doGet

protected final void doGet(javax.servlet.http.HttpServletRequest request,
                           javax.servlet.http.HttpServletResponse response)
                    throws javax.servlet.ServletException
An HTTP GET equates to returning an RDG or creating a just-in-time RIG from the query string and invoking this service.

This method is marked protected solely for package access purposes. It should not be called directly and cannot be overridden. The servlet handler will call this method automatically on an HTTP GET. To handle the request, override the method handleRequest().

An HTTP GET with no (extra) path info and no query string equates to a request for the RDG (Resource Description Graph).

An HTTP GET with a query string equates to an invocation, with measures taken to semantically resolve the query string parameters in terms of this RDG's semantics. A RIG is automatically generated from the query string and this service is invoked.

Overrides:
doGet in class javax.servlet.http.HttpServlet
Parameters:
request - HTTP Servlet request
response - HTTP Servlet response
Throws:
javax.servlet.ServletException - as thrown by the servlet container
See Also:
handleRequest(RIG rig), RDG, RIG, RRG

doPost

protected final void doPost(javax.servlet.http.HttpServletRequest request,
                            javax.servlet.http.HttpServletResponse response)
                     throws javax.servlet.ServletException
An HTTP POST equates to a request service invocation.

This method is marked protected solely for package access purposes. It should not be called directly and cannot be overridden. The servlet handler will call this method automatically on an HTTP POST. To handle the request, override the method handleRequest().

Overrides:
doPost in class javax.servlet.http.HttpServlet
Parameters:
request - HTTP Servlet request
response - HTTP Servlet response
Throws:
javax.servlet.ServletException - as thrown by the servlet container
See Also:
handleRequest(RIG rig)

handleRequest

protected abstract void handleRequest(RIG rig)
Override this method to convert an incoming Resource Invocation Graph RIG into an outgoing Resource Response Graph RRG. Edits to the RIG will be the foundation of the RRG returned from this service call. Sample code:
 public void handleRequest(RIG rig) {
 
 // if we need to check service parameters we could do it here
 //SSWAPResource translatedResource = rig.getTranslatedResource();
 
 // loop over every subject, across all matching graphs
 for ( SSWAPSubject translatedSubject : rig.getTranslatedSubjects() ) {
 
 	// "translation" maps types and properties in the RIG
 	// into the vocabulary we understand in the RDG.
 
 	// for all objects for which the current subject is already stating a mapping
 	for ( SSWAPObject sswapObject : translatedSubject.getObjects() ) {
 		// do something:
 		// edit object based on the type(s) and property values of the subject
 	}
 
 	// if and as necessary, add additional object mappings to subject
 	SSWAPObject sswapObject;
 	try {	// if and as appropriate
 		sswapObject = rig.createObject(new URI("http://mySite.org/someData"));
 	} catch ( Exception e ) {
 		sswapObject = rig.createObject();	// a "blank node"
 	}
 
 	// do something:
 	// edit object based on the type(s) and property values of the subject
 
 	// add it to the subject
 	translatedSubject.addObject(sswapObject);
 }
 
 // done
 
 // for testing, you may call getRRG()
 // if it throws a validation exception, the RRG will not be returned to the caller;
 // on error, the caller will get the original RIG returned unchanged
 boolean debugging = false;
 if ( debugging ) {
 	  try {
 		rig.getRRG();	// expensive
 	  } catch ( Exception e ) {
 		System.err.println("Failed to create a valid RRG:");
 		rig.serialize(System.err);
 	  }
  }
 
 }
 
 
Providers should do their best to satisfy the request of the RIG, but they are not required to be exhaustive. For example, SSWAPObjects should informatively satisfy the contract of the mapping from a SSWAPSubject, but they do not need themselves to extend a deep graph of relations. The decision on how much data to return is left to the provider. Regardless, what data is returned must satisfy the logical contract of the RDG.

If a request is larger than the provider wishes to satisfy (e.g., hundreds or thousands of SSWAPSubjects each requiring database calls), the provider may satisfy none, a few, or all at its choosing. If the provider wants to satisfy none--i.e., it handles requests on an all-or-none basis--and it wants the current state returned as an error to the client, it may return an HTTP 413 Request Entity Too Large response code by throwing the runtime exception RequestEntityTooLargeException. In this case no content (neither RIG nor RRG) is be returned to the client.

If the provider is unable to access data, it should fail silently and allow the RIG to be returned. If the problem is due to a client error, for example, a missing URL, then the provider may throw a ClientException to return an error to the client.

Parameters:
rig - RIG invoking the service. This RIG should be edited and will become the basis for the RRG returned by the service. Best practice is to leave most of the RIG untouched, modifying only the SSWAPObject subgraphs.
See Also:
RIG, RRG, RequestEntityTooLargeException, ClientException


Copyright (c) 2011, iPlant Collaborative, University of Arizona, Cold Spring Harbor Laboratories, University of Texas at Austin.