4 Replies Latest reply on Mar 9, 2010 5:01 AM by wuhaixing.wuhaixing.gmail.com

    Seam Plugins

    jgilbert

      In large enterprise applications it is important to break applications down into decoupled subsystems. To this end it is desireable to compose a seam application from a set of plugins. You could envision the following architecture:


      Main Portal-like Application



      This is the master web application which contains common horizontal features:



      • the web.xml file

      • master components.xml and pages.xml files

      • home.xhtml

      • login.xhtml

      • menuing

      • themes, tags, and templates

      • admin components

      • etc



      All these features would be part of the WAR per usual.


      Plugins



      From here it would be nice to be able to package a subsystem in a jar and add it to the classpath of the master web application and have the subsystem merged into the master. The subsystem jar would contain the following:



      • java components per usual

      • xhtml facelets files

      • messages.properties

      • page and navigation rules



      Some of this is already possible:



      • Obviously it is already possible to package java components in a jar with a seam.properties file

      • Seam will already search the classpath for META-INF/components.xml files and merge them

      • JSF will already search the classpath for META-INF/faces-config.xml files and merge them



      But some of it needs a few tweaks:



      • Seam needs to search the classpath for META-INF/pages.xml files and merge them




      1. It does search the classpath for fine-grained viewid.page.xml files, but you will end up with too many of these files

      2. It does allow you to specify medium-grained pages.xml files in the components.xml file, but this requires a change to the master

      3. Here is a link to the JIRA feature request and patch: JBSEAM-3509




      • Seam does have a unified resource bundle but it needs a few configuration enhancements




      1. You can specify a bundle per page, but you also want the master home page menus to have access to the messages as well

      2. You can specifiy multiple bundles in the components.xml file, but this requires a change to the master

      3. Here is a link to the JIRA feature request and patch: JBSEAM-3510




      • Probably the biggest question is how do you access facelets that are packaged in a jar.




      1. This just requires a custom facelets resource resolver and a change to the master web.xml



      public class ClasspathResourceResolver extends DefaultResourceResolver
                implements ResourceResolver {
           @Override
           public URL resolveUrl(String resource) {
                URL resourceUrl = super.resolveUrl(resource);
                if (resourceUrl == null) {
                     if (resource.startsWith("/")) {
                          resource = resource.substring(1);
                     }
                     resourceUrl = Thread.currentThread().getContextClassLoader()
                               .getResource(resource);
                }
                return resourceUrl;
           }
      }




           <context-param>
                <param-name>facelets.RESOURCE_RESOLVER</param-name>
                <param-value>net.taylor.jsf.ClasspathResourceResolver</param-value>
           </context-param>
      





      Of cource all of this isn't very useful if you can't access the subsystems from the home page and menus. This can be handled by storing the menus in the database and having each subsystem register its menus on startup by listening for the @Observer(org.jboss.seam.postInitialization) event.


      Your menus facelet might look something like this:



          <c:forEach items="#{menubar.menus}" var="menu">
              <rich:dropDownMenu
                  value="#{menu.value}">
                  <c:forEach items="#{menu.children}" var="item">
                      <rich:menuItem
                          value="#{item.value}"
                          rendered="#{item.rendered}"
                          action="#{item.action}">
                      </rich:menuItem>
                  </c:forEach>
              </rich:dropDownMenu>
          </c:forEach>
      



      Seam Wiki has a plugin concept. This posting adds a few additional ideas to help ensure that a plugin is decoupled from the master app.



      Related Links



        • 1. Re: Seam Plugins
          pmuir

          John, I suggest you make this into a knowledge base article.


          For the message bundle loading issue - I'm not happy with your proposed solution, but I agree it could be better. I'll try to think about a way of doing this that is consistent.

          • 2. Re: Seam Plugins
            jgilbert

            I agree with you regarding the message bundle. I couldn't find a semantically correct way for additively adding elements to a collection in the components.xml file.


            Not sure I like this either, but maybe turning it around the other direction, such that you define bundle components and then wire them to the resource loader component. The setter on the bundle component would add itself to the resource loader. Or maybe a create method on the bundle component would add itself to the resource loader.


            Let me know if you come up with an approach you like and I'll put it together.



            I'll let this topic evolve a bit and then move it to the knowledge base.

            • 3. Re: Seam Plugins
              pmuir

              John Gilbert wrote on Oct 06, 2008 17:55:


              I agree with you regarding the message bundle. I couldn't find a semantically correct way for additively adding elements to a collection in the components.xml file.

              Not sure I like this either, but maybe turning it around the other direction, such that you define bundle components and then wire them to the resource loader component. The setter on the bundle component would add itself to the resource loader. Or maybe a create method on the bundle component would add itself to the resource loader.




              I'm much happier with this approach.

              • 4. Re: Seam Plugins
                wuhaixing.wuhaixing.gmail.com

                I just found http://www.devproof.org/ build on wicket,spring and hibernate just like what you described Main Portal-like Application,and it's structure is managed by maven.Is there any similar thing in the seam?