Project Wonder 5.0

er.rest.entityDelegates
Class ERXRestRequestHandler

java.lang.Object
  extended by com.webobjects.appserver.WORequestHandler
      extended by er.rest.entityDelegates.ERXRestRequestHandler

public class ERXRestRequestHandler
extends com.webobjects.appserver.WORequestHandler

ERXRestRequestHandler is the entry point for REST requests. It provides support for registering an authentication delegate, a processing delegate, and a per-entity response writer.

If you just want to play around with REST, you can use the "unsafe" delegates. These delegates ARE NOT suitable for deployment (and in fact will not function in deployment). They are a major security hole, but exist just to provide wide-open access to developers who are interested in exploring the features of the ERRest framework.

Please note that the stock Apache adaptor shipped with WebObjects 5.3 is not capable of handling the PUT and DELETE HTTP methods, you will have to use the adaptor from WebObjects 5.4 or the one from Project Wonder.

Unsafe Development Setup Example

To use the unsafe development example delegates, you can add the following code to your application constructor:

 registerRequestHandler(ERXRestRequestHandler.createUnsafeRequestHandler(true, false), "rest");
 

Real-world Setup Example

In a real scenario you will not want to use the unsafe variants of the various delegates. Instead, you will want to provide custom implementations.

 ERXDefaultRestDelegate restDelegate = new ERXDefaultRestDelegate();
 restDelegate.addDelegateForEntityNamed(new CompanyRestEntityDelegate(), Company.ENTITY_NAME);
 restDelegate.addDelegateForEntityNamed(new PersonRestEntityDelegate(), Person.ENTITY_NAME);
 IERXRestAuthenticationDelegate authenticationDelegate = new MyCustomRestAuthenticationDelegate();
 IERXRestResponseWriter responseWriter = new ERXXmlRestResponseWriter();
 registerRequestHandler(new ERXRestRequestHandler(authenticationDelegate, restDelegate), "rest");
 

Once you have the request handler registered, you can explore the rest interface using an HTTP client like 'curl'. Note that the examples below will not work on your own application unless you provide entities with the same design.

Get a list of all the Site objects

 curl -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 200
 <Sites type = "Site">
   <Site id = "100">
     <title>Site #1</title>
     <bulletins type = "Bulletin">
       <Bulletin id = "200"/>
       <Bulletin id = "201"/>
       <Bulletin id = "202"/>
     </bulletins>
   </Site>
   <Site id = "101">
     <title>Site #2</title>
     <bulletins type = "Bulletin">
       <Bulletin id = "215"/>
       <Bulletin id = "230"/>
       <Bulletin id = "243"/>
     </bulletins>
   </Site>
 </Sites>
 

Get a single site from the Site list

 curl -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/100.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 200
 <Site id = "100">
   <title>Site #1</title>
   <bulletins type = "Bulletin">
     <Bulletin id = "200"/>
     <Bulletin id = "201"/>
     <Bulletin id = "202"/>
   </bulletins>
 </Site>
 

Get a single site from the Site list (that doesn't exist)

 curl -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/112.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 404
 There is no Site with the id '112'.
 

Get a single site from the Site list (that we can't see)

 curl -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/114.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 403
 You are not allowed to view the Site with the id '112'.
 

Get a list of the bulletins for that Site

 curl -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/100/bulletins.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 200
 <Bulletins type = "Bulletin">
   <Bulletin id = "200">
     <author type = "Person" id = "500"/>
     <title>Bulletin 1</title>
     <contents>Bulletin 1 Contents</title>
   </Bulletin>
   <Bulletin id = "201">
     <author type = "Person" id = "600"/>
     <title>Bulletin 2</title>
     <contents>Bulletin 2 Contents</title>
   </Bulletin>
   <Bulletin id = "202">
     <author type = "Person" id = "700"/>
     <title>Bulletin 3</title>
     <contents>Bulletin 3 Contents</title>
   </Bulletin>
 </Bulletins>
 

Get a single bulletin from the Bulletin list

 curl -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/100/bulletins/201.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 200
 <Bulletin id = "201">
   <author type = "Person" id = "600"/>
   <title>Bulletin 2</title>
   <contents>Bulletin 2 Contents</title>
 </Bulletin>
 

Update the title of a bulletin

 curl -X PUT -d '<Bulletin><title>Some random Bulletin!</title></Bulletin>' -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/100/bulletins/201.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 200
 

Try to break it -- Update a site with a bulletin document

 curl -X PUT -d '<Bulletin><title>Some random Bulletin Again!</title></Bulletin>' -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/100.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 403
 You tried to put a Bulletin into a Site.
 

Update the title of a site

 curl -X PUT -d '<Site><title>My Personal Site!</title></Site>' -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/100.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 200
 

Post a bulletin

 curl -X POST -d '<Bulletin><title>New Bulletin By Me</title><contents>This is the contents of my bulletin</contents></Bulletin>' -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/100/bulletins.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 201
 <Bulletin id = "7324">
   <title>New Bulletin By Me</title>
   <contents>This is the contents of my bulletin</contents>
 </Bulletin>
 

Delete a bulletin

 curl -X DELETE -s http://127.0.0.1/cgi-bin/WebObjects/YourApp.woa/rest/Site/100/bulletins/7324.xml?membershipTicket=someAuthToken
 
 HTTP Status Code: 200
 

Using it Programmatically

If you want to process the results of a REST call to a remote server on your local system (i.e. simple EO syncing), you can execute something like:
 EOEditingContext editingContext = ERXEC.newEditingContext();
 
 ERXDefaultRestDelegate restDelegate = new ERXDefaultRestDelegate();
 restDelegate.addDelegateForEntityNamed(new ERXUnsafeRestEntityDelegate(true), Manufacturer.ENTITY_NAME);
 ERXRestContext restContext = new ERXRestContext(context(), editingContext, restDelegate);
 
 String contentStr = ERXFileUtilities.stringFromURL(new URL("http://someserver/rest/Manufacturer.xml"));
 ERXRestRequest restRequest = new ERXXmlRestRequestParser().parseRestRequest(restContext, contentStr, "Manufacturer");
 ERXRestKey restResponse = restDelegate.process(restRequest, restContext);
 
 editingContext.saveChanges();
 
This assumes your PK match across systems, which means you should probably be using UUID PK's for syncing unless it's only one-way and read-only on the client.

Author:
mschrag

Field Summary
static java.lang.String Key
           
static org.apache.log4j.Logger log
           
 
Fields inherited from class com.webobjects.appserver.WORequestHandler
DidHandleRequestNotification
 
Constructor Summary
ERXRestRequestHandler(IERXRestAuthenticationDelegate authenticationDelegate, IERXRestDelegate delegate)
          Construct an ERXRestRequestHandler with a default response writer of ERXXmlRestResponseWriter.
ERXRestRequestHandler(IERXRestAuthenticationDelegate authenticationDelegate, IERXRestDelegate delegate, IERXRestResponseWriter defaultResponseWriter, IERXRestParser defaultRequestParser)
          Construct an ERXRestRequestHandler.
 
Method Summary
static ERXRestRequestHandler createUnsafeRequestHandler(boolean readOnly, boolean displayToMany)
          Creates an unsafe request handler for you to try out in development mode.
 IERXRestDelegate delegate()
           
 com.webobjects.appserver.WOResponse handleRequest(com.webobjects.appserver.WORequest request)
          Handle the incoming REST request.
protected  com.webobjects.eocontrol.EOEditingContext newEditingContext()
          Returns a new editing context.
static void register(ERXRestRequestHandler requestHandler)
          Registers an ERXRestRequestHandler with the WOApplication for the handler key "rest".
static ERXDefaultRestDelegate register(IERXRestAuthenticationDelegate authenticationDelegate)
          Registers an ERXRestRequestHandler with the WOApplication for the handler key "rest" and an ERXDefaultRestDelegate.
static ERXRestRequestHandler register(IERXRestAuthenticationDelegate authenticationDelegate, boolean displayAllProperties, boolean displayAllToMany)
          Registers an ERXRestRequestHandler with the WOApplication for the handler key "rest" using an ERXDefaultRestDelegate, ERXXmlRestResponseWriter, and ERXXmlRestRequestParser.
static void register(IERXRestAuthenticationDelegate authenticationDelegate, IERXRestDelegate delegate)
          Registers an ERXRestRequestHandler with the WOApplication for the handler key "rest".
 void removeRequestParserForType(java.lang.String type)
          Removes the request parser for the given entity.
 void removeResponseWriterForType(java.lang.String type)
          Removes the response writer for the given entity.
protected  IERXRestParser requestParserForType(java.lang.String type)
          Returns the request parser for the given entity name.
protected  IERXRestResponseWriter responseWriterForType(java.lang.String type)
          Returns the response writer for the given entity name.
 void setRequestParserForType(IERXRestParser requestParser, java.lang.String type)
          Sets the request parser for the request type.
 void setResponseWriterForType(IERXRestResponseWriter responseWriter, java.lang.String type)
          Sets the response writer for the request type.
 
Methods inherited from class com.webobjects.appserver.WORequestHandler
toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

log

public static final org.apache.log4j.Logger log

Key

public static final java.lang.String Key
See Also:
Constant Field Values
Constructor Detail

ERXRestRequestHandler

public ERXRestRequestHandler(IERXRestAuthenticationDelegate authenticationDelegate,
                             IERXRestDelegate delegate)
Construct an ERXRestRequestHandler with a default response writer of ERXXmlRestResponseWriter.

Parameters:
authenticationDelegate - the authentication delegate
delegate - the rest delegate

ERXRestRequestHandler

public ERXRestRequestHandler(IERXRestAuthenticationDelegate authenticationDelegate,
                             IERXRestDelegate delegate,
                             IERXRestResponseWriter defaultResponseWriter,
                             IERXRestParser defaultRequestParser)
Construct an ERXRestRequestHandler.

Parameters:
authenticationDelegate - the authentication delegate
delegate - the rest delegate
defaultResponseWriter - the default response writer to use
defaultRequestParser - the default request parser to use
Method Detail

delegate

public IERXRestDelegate delegate()

setResponseWriterForType

public void setResponseWriterForType(IERXRestResponseWriter responseWriter,
                                     java.lang.String type)
Sets the response writer for the request type.

Parameters:
responseWriter - the response writer to use
type - the type of request ("xml", "json", etc)

removeResponseWriterForType

public void removeResponseWriterForType(java.lang.String type)
Removes the response writer for the given entity.

Parameters:
type - the type to disassociate

responseWriterForType

protected IERXRestResponseWriter responseWriterForType(java.lang.String type)
Returns the response writer for the given entity name.

Parameters:
type - the type of request ("xml", "json", etc)
Returns:
the response writer to use

setRequestParserForType

public void setRequestParserForType(IERXRestParser requestParser,
                                    java.lang.String type)
Sets the request parser for the request type.

Parameters:
requestParser - the request parser to use
type - the type of request ("xml", "json", etc)

removeRequestParserForType

public void removeRequestParserForType(java.lang.String type)
Removes the request parser for the given entity.

Parameters:
type - the type to disassociate

requestParserForType

protected IERXRestParser requestParserForType(java.lang.String type)
Returns the request parser for the given entity name.

Parameters:
type - the type of request ("xml", "json", etc)
Returns:
the request parser to use

newEditingContext

protected com.webobjects.eocontrol.EOEditingContext newEditingContext()
Returns a new editing context. If you want to override how an editing context is created, extend ERXRestRequestHandler and override this method.

Returns:
a new editing context

handleRequest

public com.webobjects.appserver.WOResponse handleRequest(com.webobjects.appserver.WORequest request)
Handle the incoming REST request. REST requests can have session ids associated with them as cookies or wosid query string parameters. Right now rendering type is not supported, but ultimately the file extension of the request will determine which renderer is used to render the response.

Specified by:
handleRequest in class com.webobjects.appserver.WORequestHandler
Parameters:
request - the request

createUnsafeRequestHandler

public static final ERXRestRequestHandler createUnsafeRequestHandler(boolean readOnly,
                                                                     boolean displayToMany)
Creates an unsafe request handler for you to try out in development mode. THIS SHOULD NOT BE DEPLOYED (and in fact it will throw an exception if development mode is false).

Parameters:
readOnly - if true, the unsafe read-only delegate will be used
displayToMany - if true, to-many relationships will display by default
Returns:
an unsafe request handler

register

public static void register(ERXRestRequestHandler requestHandler)
Registers an ERXRestRequestHandler with the WOApplication for the handler key "rest".

Parameters:
requestHandler - the rest request handler to register

register

public static void register(IERXRestAuthenticationDelegate authenticationDelegate,
                            IERXRestDelegate delegate)
Registers an ERXRestRequestHandler with the WOApplication for the handler key "rest".

Parameters:
authenticationDelegate - the authentication delegate
delegate - the rest delegate

register

public static ERXDefaultRestDelegate register(IERXRestAuthenticationDelegate authenticationDelegate)
Registers an ERXRestRequestHandler with the WOApplication for the handler key "rest" and an ERXDefaultRestDelegate.

Parameters:
authenticationDelegate - the authentication delegate

register

public static final ERXRestRequestHandler register(IERXRestAuthenticationDelegate authenticationDelegate,
                                                   boolean displayAllProperties,
                                                   boolean displayAllToMany)
Registers an ERXRestRequestHandler with the WOApplication for the handler key "rest" using an ERXDefaultRestDelegate, ERXXmlRestResponseWriter, and ERXXmlRestRequestParser.

Parameters:
authenticationDelegate - the authentication delegate
displayAllProperties - if true, by default all properties are eligible to be displayed (probably should only be true in development, but it won't really hurt anything). Note that entity delegates will still control permissions on the properties, it just defaults to checking all of them.
displayAllToMany - if true, all to-many relationships will be displayed

Last updated: Tue, Feb 21, 2017 • 05:45 PM CET

Copyright © 2002 – 2007 Project Wonder.