Tech and Media Labs
This site uses cookies to improve the user experience.




Extending Butterfly Container Script With Instantiation Modes

Jakob Jenkov
Last update: 2016-05-20

It is possible to extend Butterfly Container Script (BCS) with custom instantiation modes, if the standard modes (new instance, singleton etc.) don't suffice. This text gives the following examples of custom instantiation modes:


Injecting Current HttpServletRequest and HttpSession

One situation in which the standard instantiation modes may not suffice is when processing HTTP requests in a web application.

When processing an HTTP request you may need to instantiate objects which have the current HttpServletRequest or HttpSession objects injected into them. Since the request and session objects change between requests you cannot use the singleton instantiation mode. Neither can you use the new instance mode, because the request object to obtain from a given factory should be the same for as long as the request is being processed.

The solution to this problem is to create a HttpRequestCache which associates the thread processing the HTTP request with the HttpServletRequest object representing the request being processed. In other words, maps the thread to the request it processes. Here is the HttpRequestCache class definition:

public class HttpRequestCache{
  
   Map requests = 
       new ConcurrentHashMap();

   public void set(HttpServletRequest request){
      requests.put(Thread.currentThread(), 
   }
   
   public HttpServletRequest get(){
      return requests.get(Thread.currentThread());
   }
   
   public void remove(){
      requests.remove(Thread.currentThread());
   }

By calling the set() method with the current request as parameter, the request is associated with the thread calling the set() method. By calling the get() method the request object associated with the calling thread can be obtained.

To integrate this into BCS and the container you will have to define three factories:

requestCache = 1 com.myapp.HttpRequestCache();
request      = * requestCache.get();
session      = * request.getSession();

The "requestCache" factory defines an instance of HttpRequestCache as a singleton. The "request" factory is defined as a call to the get() method on the product returned from the "requestCache" factory. In other words, as a call to the get() method on the HttpRequestCache singleton. The "session" factory is defined as a call to the getSession() method of the product returned by the "request" factory. In other words, as a call to the getSession() method on the request object obtained from the HttpRequestCache singleton, which is the request object associated with the calling thread.

Using the request and session factories in a script is like using any other factory. Here is an example:

myAction = * com.myapp.MyAction(request, session);

In order to make the the request and session factories return the correct objects you must first call the HttpRequestCache's set() method. After that you can obtain an instance from the myAction factory with the correct request and session objects injected. Here is how that looks in Java:

((HttpRequestCache) container.instance("requestCache")).set(request);

MyAction action = container.instance("myAction");

Finally it is probably a good idea to remove the request object from the cache when the request processing is done. That is done like this in Java:

((HttpRequestCache) container.instance("requestCache")).remove();

Jakob Jenkov




Copyright  Jenkov Aps
Close TOC