2 Replies Latest reply on Oct 2, 2008 3:20 PM by 7rond

    ContextualHttpServletRequest and class loading

    7rond

      Hello


      I've gotten into a problem with the ContextualHttpServletRequest class, specifically when it comes to class loading.


      My application structure is as follows;




      • core.ear - the core of the app, with code shared amongst the webapps deployed as standalone wars. no loader repository configured in jboss-app.xml, and no seam jars are bundled, they are all located in server/default/lib

      • app1.war - a webapp using code from core.ear

      • app2.war - a webapp using code from core.ear, but which also have a component overriding a component in core.ear





      The overridden component mentioned is a SiteContext class that contains context info about the current site (loaded from the database on seam initialization and stored in a APPLICATION-scoped component, as such;



      @Name("siteContext")
      @Install(precedence = Install.FRAMEWORK)
      @Scope(ScopeType.APPLICATION)
      public class SiteContext implements Serializable {
      }
      



      This class is placed inside the ear and loaded by the UnifiedClassLoader for the ear itself, which I've verified running heaps of tests around this to try to localize the problem.


      Then I have a class overriding the SiteContext for that specific application, located in WEB-INF/classes in app2.war. This class is loaded by the URLClassLoader for the app2.war, as expected;



      @Name("siteContext")
      @Install(precedence = Install.APPLICATION)
      @Scope(ScopeType.SESSION)
      public class AdminSiteContext extends SiteContext {
      }



      Now, for the problem. Anything, anywhere, that requests a SiteContext as such;


      @In private SiteContext siteContext



      Will get the proper SiteContext instance. Everything residing in app1.war gets the SiteContext.class instance, everything residing in app2.war gets the AdminSiteContext.class instance.


      The problem arises when I try to load the SiteContext component in a method wrapped by the ContextualHttpServletRequest class. What I'm trying to accomplish is a Seam Resource Servlet provider that checks for access rules and such against the resources it's going to provide before showing them to the client. The class is placed inside the ear, and I've implemented the provider as such;


      public class MyCustomResource extends AbstractResource {
      
          @Override
          public void getResource(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
              new ContextualHttpServletRequest(request) {
                  @Override
                  public void process() throws IOException {
                      serveResource(request, response);
                  }
              }.run();
          }
      
          public void serveResource(HttpServletRequest request, HttpServletResponse response) {
              SiteContext siteContext = Component.getInstance("siteContext");
          }
      
      }



      This is where it starts to go haywire. Any webapp (both app1 and app2) get a instance of the AdminSiteContext.class here, and it's loaded by the URLClassLoader of app2.


      How did this make it into my resource provider from both apps, and not just app2 which should be the only app ever to see this class? I've tested and reproduced the same result with a custom, basic servlet extending from HttpServlet instead of AbstractResource and I get exactly the same result. I have configured the context filter in my components.xml for both applications to cover both the test servlet and the seam resource servlet. Both webapps are loaded within their own loader repository, which I've also validated that's properly configured by going through debug log data from the JBoss logs.


      Also, I started a thread yesterday about another issue which presumably was this issue all along. I started a new thread to get it more on track since I cannot comprehend this is a issue with anything but the ContextualHttpServletRequest class as it's working as intended in every other aspect of Seam. :)

        • 1. Re: ContextualHttpServletRequest and class loading
          pmuir

          Trond Arve Nordheim wrote on Oct 02, 2008 04:10:


          My application structure is as follows;



          • core.ear - the core of the app, with code shared amongst the webapps deployed as standalone wars. no loader repository configured in jboss-app.xml, and no seam jars are bundled, they are all located in server/default/lib

          • app1.war - a webapp using code from core.ear

          • app2.war - a webapp using code from core.ear, but which also have a component overriding a component in core.ear





          This structure isn't supported or recommended.

          • 2. Re: ContextualHttpServletRequest and class loading
            7rond

            So the only supported/recommended way is to:



            • Deploy the jars in the ear bundled inside the webapp together with the Seam jars

            • Deploy all wars inside the ear




            Is that correct? Just have to figure out a more proper way to do it then I guess, I just found this structure to be pretty decent when it comes to having a easy way to update both the entire application core, or more commonly, a small change in one of the webapps without having to redeploy the entire, huge ear.


            Guess my choice will be number 1 then, even though it makes the system update somewhat of a pain having to redeploy all wars, but it's the only way to achieve a somewhat simplistic development process with hot deploying in testing and such.


            I'd appreciate some input on this, I kinda figured the structure I had would work since this seems absolutely fine for all aspects of Seam I'm touching - except the stuff wrapped in a ContextualHttpServletRequest.