Project Wonder 5.0

er.extensions.appserver
Class ERXComponentActionRedirector

java.lang.Object
  extended by er.extensions.appserver.ERXComponentActionRedirector

public class ERXComponentActionRedirector
extends java.lang.Object

Allows you to develop your app using component actions while still providing bookmarkable URLs. It should be considered highly experimental and it uses a few very dirty shortcuts, but no private API to work it's magic. The main problems may be garbage collection or space requirements. You might be better off to compress the responses.
The mode of operation is as follows; given a component action in a typical page:

  public WOComponent myAction() {
      WOComponent nextPage = pageWithName("Main");
      nextPage.takeValueForKey(new Integer(100), "someValue");
      return nextPage;
  }
 
  
then Main could be implemented something like this:
  public class Main extends WOComponent implements ERXComponentActionRedirector.Restorable {
      static Logger log = Logger.getLogger(Main.class);
 
      public Integer someValue = new Integer(10);
 
      public Main(WOContext aContext) {
          super(aContext);
      }
      
      // this page has a "Increment Some Value" link to itself which just doubles the current value
      public WOComponent addAction() {
          someValue = new Integer(someValue.intValue()*2);
          log.info(someValue);
          return this;
      }
 
      public String urlForCurrentState() {
          return context().directActionURLForActionNamed("Main$Restore", new NSDictionary(someValue, "someValue"));
      }
      public static class Restore extends WODirectAction {
          public Restore(WORequest aRequest) {
              super(aRequest);
          }
          public WOActionResults defaultAction() {
              WOComponent nextPage = pageWithName("Main");
              Number someValue = context().request().numericFormValueForKey("someValue", new NSNumberFormatter("#"));
              if(someValue != null) {
                  nextPage.takeValueForKey(someValue, "someValue");
              }
              return nextPage;
          }
      }
  }
  
But this is just one possibility. It only locates all the code in one place.
The actual workings are: When you click on a link, the request-response loop gets executed, but instead of returning the response, we save it in a session-based cache and return a redirect instead. The current page is asked for the URL for the redirect when it implements the Restorable interface.
So the users browser receives redirection to a "reasonable" URL like "/article/1234/edit?wosid=..." or "../wa/EditArticle?__key=1234&wosid=...". This URL is intercepted and looked up in the cache. If found, the stored response is returned, else the request is handled normally.
The major thing about this class is that you can detach URLs from actions. For example, it is very hard to create a direct action that creates a page that uses a Tab panel or a collapsible component because you need to store a tremendous amount of state in the URL. With this class, you say: "OK, I won't be able to totally restore everything, but I'll show the first page with everything collapsed."
For all of this to work, your application should override the request-response loop like:
  public WOActionResults invokeAction(WORequest request, WOContext context) {
      WOActionResults results = super.invokeAction(request, context);
      ERXComponentActionRedirector.createRedirector(results);
      return results;
  }
 
  public void appendToResponse(WOResponse response, WOContext context) {
      super.appendToResponse(response, context);
      ERXComponentActionRedirector redirector = ERXComponentActionRedirector.currentRedirector();
      if(redirector != null) {
          redirector.setOriginalResponse(response);
      }
  }
 
  public WOResponse dispatchRequest(WORequest request) {
      ERXComponentActionRedirector redirector = ERXComponentActionRedirector.redirectorForRequest(request);
      WOResponse response = null;
      if(redirector == null) {
          response = super.dispatchRequest(request);
          redirector = ERXComponentActionRedirector.currentRedirector();
          if(redirector != null) {
              response = redirector.redirectionResponse();
          }
      } else {
          response = redirector.originalResponse();
      }
      return response;
  }
 
If you are using ERXApplication, you should set the er.extensions.ERXComponentActionRedirector.enabled=true property instead.

Author:
ak

Nested Class Summary
static class ERXComponentActionRedirector.Observer
          Observer class manages the responses cache by watching the session.
static interface ERXComponentActionRedirector.Restorable
          implemented by the pages that want to be restorable
 
Field Summary
protected static org.apache.log4j.Logger log
          logging support
protected  com.webobjects.appserver.WOResponse originalResponse
          the original response
protected  com.webobjects.appserver.WOResponse redirectionResponse
          the redirection response
protected static com.webobjects.foundation.NSMutableDictionary responses
          static cache to hold the responses.
protected  java.lang.String sessionID
          the session id for the request
protected  java.lang.String url
          the url for the redirected request
 
Constructor Summary
ERXComponentActionRedirector(ERXComponentActionRedirector.Restorable r)
          contructs the redirector from the Restorable.
 
Method Summary
static void createRedirector(com.webobjects.appserver.WOActionResults results)
          Creates and stores a Redirector if the given results implement Restorable.
static ERXComponentActionRedirector currentRedirector()
          Uses ERXThreadStorage with the key "redirector".
 com.webobjects.appserver.WOResponse originalResponse()
           
 com.webobjects.appserver.WOResponse redirectionResponse()
           
static ERXComponentActionRedirector redirectorForRequest(com.webobjects.appserver.WORequest request)
           
 java.lang.String sessionID()
           
 void setOriginalResponse(com.webobjects.appserver.WOResponse value)
          Sets the original response.
protected static void storeRedirector(ERXComponentActionRedirector redirector)
          stores the redirector in the cache.
 java.lang.String url()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

log

protected static final org.apache.log4j.Logger log
logging support


originalResponse

protected com.webobjects.appserver.WOResponse originalResponse
the original response


redirectionResponse

protected com.webobjects.appserver.WOResponse redirectionResponse
the redirection response


sessionID

protected java.lang.String sessionID
the session id for the request


url

protected java.lang.String url
the url for the redirected request


responses

protected static final com.webobjects.foundation.NSMutableDictionary responses
static cache to hold the responses. They are stored on a by-session basis.

Constructor Detail

ERXComponentActionRedirector

public ERXComponentActionRedirector(ERXComponentActionRedirector.Restorable r)
contructs the redirector from the Restorable.

Parameters:
r - - Restorable component used to construct a redirector
Method Detail

storeRedirector

protected static void storeRedirector(ERXComponentActionRedirector redirector)
stores the redirector in the cache.

Parameters:
redirector - The redirector to store.

redirectorForRequest

public static ERXComponentActionRedirector redirectorForRequest(com.webobjects.appserver.WORequest request)
Parameters:
request - The request
Returns:
the previously stored redirector for the given request

createRedirector

public static void createRedirector(com.webobjects.appserver.WOActionResults results)
Creates and stores a Redirector if the given results implement Restorable.

Parameters:
results -

currentRedirector

public static ERXComponentActionRedirector currentRedirector()
Uses ERXThreadStorage with the key "redirector".

Returns:
the currently active Redirector in the request-response loop.

redirectionResponse

public com.webobjects.appserver.WOResponse redirectionResponse()
Returns:
the redirection response.

url

public java.lang.String url()
Returns:
the URL with which the component can be restored.

sessionID

public java.lang.String sessionID()
Returns:
the session ID for the Redirector.

originalResponse

public com.webobjects.appserver.WOResponse originalResponse()
Returns:
the original response.

setOriginalResponse

public void setOriginalResponse(com.webobjects.appserver.WOResponse value)
Sets the original response.

Parameters:
value - the original response.

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

Copyright © 2002 – 2007 Project Wonder.