0 Replies Latest reply on Apr 13, 2006 2:56 PM by abunginabru

    access to externalContext in WebApplicationContext?

    abunginabru

      Hi All,

      This is a bit of a long question, but it's solution might prove interesting, so please bear with me..

      I'm trying to work up a new solution to an old problem - how to transfer data from the web application configuration (web.xml) into the ejb container.
      Traditionally this has been done using the init method of a start-up servlet (with "load-on-startup" set) and web-client style connections to session ejbs.

      Now, the same pattern could be followed in the SEAM environment, I've tried implementing it this way, but it's as inelegant as ever and it only works up to a point. There are problems with the visibilty of the SEAM contexts. In particular, the FacesContext isn't available to the session bean called by the start-up servlet (irrespective of the order of "load-on-startup" value of the Faces Servlet) and neither is the SEAM ApplicationContext.

      I can access the ServletContext in the session bean by passing it as a method parameter, but having generated my beans intended for Application scope, I can't either outject them or set them as attributes of the SEAM Application context.

      Not good..

      I thought I'd try a different approach based on the @Startup and @Create annotations in SEAM.

      A Start-Up SEAM action scoped in org.jboss.seam.ScopeType.APPLICATION will surely have visibility of the ApplicationContext...

      Here is an outline of what I have:

      In web.xml:

      <context-param>
      <param-name>webContext</param-name>
      <param-value>demo</param-value>
      </context-param>


      My SEAM StartUpAction.java:

      @Stateless
      @Startup
      @Name( "startup" )
      @Scope( APPLICATION )

      public class StartUpAction implements StartUp {

      @Create
      public void create() {
      Context applicationContext = Contexts.getApplicationContext();
      Thing thing = new Thing();
      applicationContext.set( "thing", thing );
      }

      public void start( ServletContext servletContext ) {
      String webContext = ( String )servletContext.getInitParameter( "webContext" );
      WebContextyThing contextyThing = new WebContextyThing( webContext );
      Context applicationContext = Contexts.getApplicationContext();
      applicationContext.set( "contextyThing", contextyThing );
      }
      }


      The create call occurs first and works beautifully!

      BUT.. When the servlet later calls the start method the applicationContext isn't visible, causing a NPE!

      How come the now you see it now you don't behaviour? Do I need some "@Unwrap"ing?

      The work-around I've used looks like this:

      @In
      @Out
      private transient Context applicationContext;

      @Create
      public void create() {
      applicationContext = Contexts.getApplicationContext();
      // gets org.jboss.seam.contexts.WebApplicationContext
      // wraps org.apache.catalina.core.ApplicationContextFacade
      }

      public void start( ServletContext servletContext ) {
      // etc
      }

      This looks as if it may cause side-effects - can anyone think of any?



      While we're on this subject - how about this?

      Internally, Contexts.getApplicationContext() returns WebApplicationContext which contains ServletContext as externalContext, but this is private.

      Now, if we had an accessor, namely:

      In WebApplicationContext.java:

      public class WebApplicationContext implements Context {
      ...
      private ServletContext externalContext;
      ...
      public ServletContext getExternalContext() {
      return externalContext;
      }
      ...

      Then the following would be possible:

      In web.xml:

      <context-param>
      <param-name>webContext</param-name>
      <param-value>demo</param-value>
      </context-param>


      In StartUpAction.java:

      @Create
      public void create() {
      Context applicationContext = Contexts.getApplicationContext();
      WebApplicationContext webApplicationContext = ( WebApplicationContext )applicationContext;
      ServletContext servletContext = webApplicationContext.getExternalContext();
      WebContextyThing contextyThing = new WebContextyThing( webContext );
      applicationContext.set( "contextyThing", contextyThing );
      }

      Now we no longer the servlet at all!

      Can I raise this as a suggestion? Include an accessor for the externalContext in WebApplicationContext? Or is this heretical?

      Cheers,

      Abung