How Aranea Integration works: part I

October 24th, 2007 by Taimo Peelo

This is the first in the series of tutorial articles laying out the foundations of Aranea Integration in practical way. It introduces the base classes of Aranea Integration which form the core of server-side integration—handle sessions, requests and responses in a way that allows hosted components to function (keep this diagram open while reading!).

Base interface for Aranea components that host components/actions from whatever framework is called HostComponent.

/**
* Represents the Aranea {@link Component} that
* hosts some foreign framework component.
*/
public interface HostComponent extends Component {
  /**
  * This method must return the session attribute
  * <em>Map</em> specific to hosted component.
  * @return map that will be used for storing the
  *               session accessible to hosted foreign
  *               component
  */
  public Map getHostedSessionAttributes();
}

and has just one method — for retrieval of session attributes managed by the hosted component. The request and response are tuned to hosted components needs too, but since request and response in HTTP protocol are stateless, these need not be part of HostComponent interface but can be managed separately and statelessly. HostComponent base implementation is extremely simple:

/**
* Base class for Aranea widgets that host foreign
* components. Provides session storage for hosted
* foreign components.
*/
public class BaseHostWidget
extends BaseApplicationWidget implements HostComponent {
  private final Map sessionAttributeMap = new HashMap();

  public Map getHostedSessionAttributes() {
    return sessionAttributeMap;
  }
}

As one can see it completely lacks methods for actual management of session attributes.The class that manages session access is called SessionWrapper:

/* One and only constructor **/
public SessionWrapper(
    HttpSession session,
    HostComponent sessionHolder)

SessionWrapper ensures that the session modifications by hosted component will affect only the concrete hosted component. It is created anew at each request by IntegrationRequestWrapper (note that only way to access session in a web application is through current request).

Other base wrappers that make hosted component feel at home are already mentioned IntegrationRequestWrapper and IntegrationResponseWrapper. IntegrationRequestWrapper is created by some concrete HostComponent implementation, passing in the original request and itself.

new IntegrationRequestWrapper(
    HttpServletRequest original, HostComponent host);

The IntegrationResponseWrapper takes care that everything that is done to it only affects the wrapped instance — so that original request is left unchanged and can be passed to any number of other Aranea components or hosted components (in which case it is obviously wrapped in its own IntegrationRequestWrapper). Often some parts of original request are preprocessed in some way in IntegrationRequestWrapper extensions — i.e. the fully hierarchial component based request parameters that Aranea uses are converted into flat namespace for action-based frameworks, i.e.

public class BaseActionBasedRequestWrapper
(final HttpServletRequest request,
final HostComponent host) {
  super(request, host);
  preprocessRequestParameters();
}

where preprocessRequestParameters() takes all the ‘scoped’ data meant for hosted component and converts this into flat namespace parameters that action based frameworks expect. This allows to reuse actions many times on one page, as each action can receive separate data.

Foreign response itself is held in IntegrationResponseWrapper which allows HostComponent to post-process response when needed. Postprocessing is most often done to scope the request parameters expected by hosted component in a way that they will be unique. How exactly this is done is highly dependent on hosted framework. For action-based frameworks this might mean post-processing HTML forms, for component based frameworks the postprocessing might even be unnecessary when the hosted components’ ‘root’ component is given the right scope to begin with (i.e. with JSF NamingContainer).

Other crucial part of the IntegrationResponseWrapper is the overriden encodeURL(url) method. By servlet specification, all URLs that are to generate requests to (hosted) web application must go through this method before written out to response. IntegrationResponseWrapper overrides this method so that later incoming request can be identified as request to component hosted by Aranea. Identification is done by AraneaIntegrationFilter which is quite ordinary servlet filter, except it prevents the request from directly reaching the hosted framework and directs it to Aranea component hierarchy where it will be processed by all interested components including the HostComponent implementation which originally generated the request.

This briefly covers all current integration base classes. For more detailed information, one can take a look at org.araneaframework.integration.common package in the Aranea Integration project.

Leave a Reply