Alfresco Web Forms Integration - Mock JSF Faces Context

by Ron DiFrango

On my current project, we are using Alfresco and working on an integration with JBoss Portal. In particular, we were creating our own version of Alfresco WebFormseditor that is built into their web client. We had built all the Alfresco Web Scripts to fetch the appropriate WebForm for a given content item and a college of mine had built all the Portal magic to render and save the form in a fashion similar to Chiba. The last component I needed to build was the Webscript to generate the renditions of the web forms within Alfresco. I found the magic component with Alfresco that did this in AVMEditBean. But in order to utilize it, I had to cut and paste the following lines:

if (services.getAVMService().hasAspect(nodeRef.getVersion(), nodeRef.getPath(), WCMAppModel.ASPECT_FORM_INSTANCE_DATA)) {
  this.regenerateRenditions(nodeRef);
}
 
private void regenerateRenditions(AVMNode node) throws FormNotFoundException {
  final String avmPath = node.getPath();
  final FormInstanceData fid = formsService.getFormInstanceData(-1, avmPath);
  final List result = fid.regenerateRenditions();
 
  for (FormInstanceData.RegenerateResult rr : result) {
    if (rr.getException() != null) {
      Utils.addErrorMessage("error regenerating rendition using " + rr.getRenderingEngineTemplate().getName() + ": " + rr.getException().getMessage(), rr.getException());
    }
  }
}

The trouble, I ran into was all the utility classes that were called by this blurb of code required a static instances of the current Alfresco FacesContext. My first instinct was to start pulling apart each of these utility classes that were called and removing their dependence upon the FacesContext. I had done this effectively in the past when I was mimicking the Submit All functionality, but this time it was not going as well. I seem to keep digging myself a bigger and bigger hole of code that following the Cut And Paste Anti-Pattern. I was talking with my colleague Phil Kedy and he suggested that we create a Mock version of the FacesContext and just initialize it with the things that the Alfresco utility classes needed, mainly the Spring WebContext. He got to work on building the Mock class and I figured out to wire in Spring context. Wiring in the Spring context was fairly easy because all Alfresco Webscripts are declared in a Spring context file so I just had my Webscript implement the Spring interface ApplicationContextAware and we would be set. Mr. Kedy figured out how to create the mock class and now all I had to add in was the following:

MockFacesContext faces = new MockFacesContext((WebApplicationContext) ctx);

Now in conjunction with the MockFacesContext, he had to create 2 supporting classes a MockApplication class that implemented the method createValueBinding. This was necessary in order to process the el syntax that Alfresco used to locate the Alfresco Services. And in conjunction with that he had to implement a MockValueBinding object to handle the location of the services. And finally, we had to load in the message bundles to handle the word substitution.

Once all of this was done, we had a working version of the Web Forms upload and rendition generation that worked within the JBoss Portal.