WebObject’s DirectAction for Rest

The ERRest framework uses DirectActions within WebObjects to handle REST requests. It registers a handler class (subclass of WODirectActionRequestHandler) for a specific part of the URI (“/ra”). It is called request handler key. We could set another key like “/api”, to differ client URIs and server URIs.

public class BaseRestRequestHandler extends WODirectActionRequestHandler {

   public static void register(BaseRestRequestHandler requestHandler) {
      WOApplication.application().registerRequestHandler(requestHandler, "api");
   }
}

Within the constructor of the Application class we will register our MessageRequestHandler, which is a subclass of BaseRestRequestHandler:

public class Application extends ERXApplication {

   public Application() {
      BaseRestRequestHandler requestHandler = new MessageRequestHandler();
      BaseRestRequestHandler.register(requestHandler);
      setDefaultRequestHandler(requestHandler);
   }
}

Now, all our requests to /api will be redirected to our MessageRequestHandler. And our application redirects all requests to our own handler per default (with setDefaultRequestHandler()). How does it work?

Request-Response-Loop

WebObjects handles requests during its Request-Response-Loop. There is a class WORequestHandler, which processes the request in its handleRequest(WORequest) method. It is an abstract class, which is used by a private class WOActionRequestHandler. This class implements the abstract method handleRequest(WORequest), which calls _handleRequest(WORequest) and returns a WOResponse object. The _handleRequest(WORequest) method implements the complete handling of the request, which subclasses can modify by overwriting the used methods. These are:

WO Request-Response-Loop

If we look into ERRest, the class ERXRouteRequestHandler overwrites the four blue colored methods. The first and second method will be re-implemented, so the default algorithm has been replaced. The third and fourth method extends the algorithm of the base-class WODirectActionRequestHandler. The latter only implements getRequestHandlerPathForRequest(), so we can focus us on the code of WOActionRequestHandler.

Excursion: What are ActionNames?

As you can see in the image above, the second method extracts a so called action name and the third blue method uses it to create an instance of a class. A normal direct action URI of a WebObjects application looks like:

http://127.0.0.1:10001/cgi-bin/WebObjects/DirectActionTest.woa/wa/queryLocation?filter=Leipzig

queryLocation is the ActionName. It will be enhanced by the term “Action”, so you need a method queryLocationAction() within your handler class. Per default, your handler class is named as DirectAction, which is registered for the key “/wa”. If your URI contains another key, you have to register an own class:

http://127.0.0.1:10001/cgi-bin/WebObjects/DirectActionTest.woa/testme/queryLocation?filter=Leipzig

/testme” needs another request handler (subclass of WODirectActionRequestHandler), which must be registered as direct action handler. It defines the class name which will execute the given action name (TestMeAction and queryLocationAction).

public class TestMeRequestHandler extends WODirectActionRequestHandler {

   public TestMeRequestHandler() {
      super("TestMeAction", "noOp", true);
   }

   @Override
   protected String defaultActionClassName() {
      return "TestMeAction";
   }

   @Override
   protected String defaultDefaultActionName() {
      return "noOp";
   }
}

public class TestMeAction extends ERXDirectAction {

   public DirectAction(WORequest request) {
      super(request);
   }

   public WOActionResults noOpAction() {
      // default action, if we don't define an action name in URI
      return pageWithName(Main.class.getName());
   }

   public WOActionResults queryLocationAction() {
      // TODO: query datastore and put data into page
      return pageWithName(Main.class.getName());
   }
}

public Application extends ERXApplication {
   public Application() {
      WODirectActionRequestHandler reqhandler = new TestMeRequestHandler();
      WOApplication.application().registerRequestHandler(reqHandler, "testme");
   }

As you can see, the DirectAction workflow needs always a class, which can handle the action and an action name, which is mapped to a method of this class.

Therefore the method getRequestActionClassAndNameForPath() of WOActionRequestHandler works with an array of two parameters: the class and the action name. Our own implementation must return such data.

Leave a Reply