Wednesday 21 September 2011

OraFormsFaces Forms Servlet URL set dynamically by java code

I've recently had to integrate with Oracle Forms as part of an ADF Web Application. Of course, the framework of choice is OraFormsFaces. But, I got particularly annoyed with the HtmlFormRenderer and the way it looks up the value of the Forms Servlet URL. This renderer currently only looks at the Java Namespace in the JNDI Context of the Web Application (the recommended way to configure OraFormsFaces as per the developer guide; environment entry in the web.xml, which gets loaded into the namespace: java:comp/env) AND the Input Parameters of the ServletContext. Nothing wrong with this approach, but there is no allowed way to change this value after the initial configuration has been done (I mean the JEE spec does not allow change of these values after start-up of your app). Hence, no way around this!

Well, I wanted to change the Forms Servlet URL value dynamically as per the environment within which my Web Application gets deployed to. So, I extended the HtmlFormRenderer of OraFormsFaces to also lookup this value from an additional place as to the JNDI Context and the Servlet Context (input parameters). My extension allows a lookup from the accessible attributes of the Servlet Context. Hence, one can implement a ServletContextListener which can set this attribute key-value pair on successful initialization of the Servlet Context, by simply making use of the setAttribute()-method on the Servlet Context interface.
On the consumer side of the Servlet Context, the extended HtmlFormRenderer will then simply do a getAttribute() with the standard OraFormsFaces-key for the Forms Servlet URL.

I thought this solves the problem in the neatest way possible, as I only had to change the "faces-config.xml", which resides in the OraFormsFaces JAR file, to point to my custom HtmlFormRenderer instead of the standard one shipped with OraFormsFaces.

I've included code sniplets of my java code from both the ServletContextListener and the HtmlFormRenderer, respectively:

(ServletContextLister)
  public void contextInitialized(ServletContextEvent ctxEvent) {
    ServletContext servletCtx = ctxEvent.getServletContext();
    servletCtx.setAttribute(OraFormsFacesUtil.FORMS_SERVLET_URL_KEY,
      OraFormsFacesUtil.getFormsServletURL());
  }


(HtmlFormRenderer)
  public class MyHtmlFormRenderer extends HtmlFormRenderer {
    .

    .
    public String getFormsServletURL(FacesContext facesContext) {
      String url = null;   
      ServletContext servletContext = (ServletContext)
           facesContext.getExternalContext().getContext();
      url = (String) servletContext.getAttribute(
          OraFormsFacesUtil.FORMS_SERVLET_URL_KEY);
      if (url != null) {
        String result = url != null ? url.trim() : null;
        return result;     
      } else {
        return super.getFormsServletURL(facesContext);
      }
    }
  }
You'll notice I've used a helper class (OraFormsFacesUtil) to keep the Forms Servlet URL attribute key in one place and to implement the functionality which determines what the Forms Servlet URL value must be.

Currently, I'm thinking a better solution would be to implement the above solution similar to the way the FormsCredentialProvider configuration works. This way, you will also simply specify a class name in the web.xml of your Web Application which adheres to a given interface (i.e. FormsServletURLProvider, declaring a method with signature: String getFormsServletURL(), for example) which can then be used to retrieve the URL programmatically. Then the implementation can rely on configuration or java code; for the developer to decide.

No comments:

Post a Comment