Seam Plugins
jgilbert Oct 5, 2008 10:10 PMIn 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
- It does search the classpath for fine-grained viewid.page.xml files, but you will end up with too many of these files
- It does allow you to specify medium-grained pages.xml files in the components.xml file, but this requires a change to the master
- 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
- You can specify a bundle per page, but you also want the master home page menus to have access to the messages as well
- You can specifiy multiple bundles in the components.xml file, but this requires a change to the master
- 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.
- 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
- https://jira.jboss.org/jira/browse/JBSEAM-3509
- https://jira.jboss.org/jira/browse/JBSEAM-3510
- wiki://1130
- wiki://45078
- http://ocpsoft.com/opensource/create-common-facelets-jar