Sunday, June 21, 2015

Custom Session implementation to make Application Module compatible for REST Services in ADF 11g.

Scenario -  We had a requirement where we had to use ADF BC (Am using 11g) for REST Services and also retain the  advantages of Application Module such as session affinity. It meant that we cannot use createRootApplicationModule, which looses the state every time it is invoked,  making it not suitable for transactions. So somehow we needed a  Custom Session implementation for Application Module (AM).

Solution - After some research we figured how AM maintains session affinity and used it in our custom implementation. Guess what, It worked :-)

Preface - Application Module uses SessionCookie(Not related to http cookie) to maintain  affinity with the user's session. In reality, This can be any unique identifier and not restricted to user/user's session.

Eg: If we use a string identifier, lets say "sample"   for two users who access the AM via Cookie sequentially, then both the users will get same application module state.

Since in our case we need affinity with user's session , we use http session ID.

Implementation - 
Lets dive into the code -

//This method is used to get SessionCookie for a user's session
 private SessionCookie _getUserSessionCookie(){

// finds an AM pool or creates one if it is the first time. 
ApplicationPool pool = PoolMgr.getInstance().findPool("com.webcenter.samples.model.applicationmodule.SampleAMLocal", "com.webcenter.samples.model.applicationmodule.", "SampleAMLocal", null);

//finds user's session from the pool or creates one for first //access. To maintain user's session affinity http SessionID is //used.

        SessionCookie cookie= pool.findOrCreateSessionCookie(ADFContext.getCurrent().getADFApplicationUID(),httpRequest.getSession().getId(), null);


        return cookie;
    }

// Sample REST method which shows how to get and release application //module
    @GET
    @Path("/sampleData")
    public Response getSampleData(){ 
//Gets the session cookie       
        SessionCookie sc =  _getUserSessionCookie();
//Use the application module associated with the session
        SampleAMLocal am = (SampleAMLocal) sc.useApplicationModule();
        String[] ret = am.getSampleData();  
//Release the application module in "MANAGED" state. You can also //use UNMANAGED and RESERVED release modes. 
   if(! sc.isApplicationModuleReleased())     
        sc.releaseApplicationModule(sc.SHARED_MANAGED_RELEASE_MODE);
        return Response.ok(ret).type(MediaType.APPLICATION_JSON).build();

    }



We did some load test with this code and the results were exactly same as if it were used in a normal application which uses  ADF-BC and ADF Faces.

Note : The Load test is done with minimum and maximum available size of AMs in the pool set to 1 so as to verify whether the checkin, checkout, removals and available AM Stats are functioning as expected.





The stats reveal that AM is properly used, released with session affinity.
Here is the link for more stats we captured
 Have a look at it, Happy learning!!