I have an application with a well defined interface. It uses CDI for resolution of the modules, (Specifically it uses Instance<> injection points on API interfaces to resolve modules) and passes various data back and fourth via the interfaces without issue. I've intentionally kept the API and implementation separate, and the modules only inherit from the API to avoid tight coupling, and the application only knows of the modules through runtime dependancies, and data passing accomplished via the APIs. The application runs fine without the modules, which can be added simply by dropping the jar into the WEB-INF/lib folder and restarting the app server.
Where I'm running into issues is that I want the modules to create a portion of the view, and I therefor want to invoke, in a portable way, either a JSF component, or do an include from the module in order to have it render its view. I already have resolved what module I want to invoke, and have references to the module's interface ready. The way I initially thought to do this was to do a ui:include that asks the module to supply where it's view template is, but I have no idea how to answer that query in a meaningful way, as view resolution is done from the application root, not the library root.
The executive summary is that I have no idea how to jump the gap from Application to Library using JSF for .xhtml (template/component) files.
Using a CC would be nice, but how do I specify that I want a particular CC instance at runtime, instead of having that hard coded into the page?
I can of course invoke the application code directly and ask it for markup, but this seems really brute force, and once I have the markup, I'm not sure exactly how to tell JSF to evaluate it. That said, I can imagine a component that would take the resource path, grab the markup and evaluate it, returning the completed markup, I just don't know how to implement that.
I'd rather avoid forcing module developers to go the heavy duty UIComponent approach if possible, which means either a dynamic way of doing ui:include (or some equivalent) or a dynamic way of invoking CCs. (I don't mind coding the UIComponent approach ONCE in the application if that's what it takes to make module developers' lives easier)
Any suggestions on where I should look to figure this out? (I'll post the answer here if I find it first)
By the way.. you can avoid implementing your own resource resolver when you're using seam solder (currently being integrated into apache deltaspike) which is a really useful library complementing CDI (your typical Java EE 6 component model)
I too experimented with modularity in jsf applications. Basically I built a template interface with a toolbar which gets filled with buttons provided by each module. Typically you will do this by providing a List of Strings as a Named Object:
Notice how each of the buttons may come from a different module of the jsf application. The template interface contains a panel where
you can use it in your markup the following way (at your own risk ;) ) :
This was the toolbar and the content panel.
a simple button or view definition may look like this:
lets name this artifact view1.xhtml
When this button is pushed (which doesn't trigger a postback using the actionListener, we want to reload the content using ajax) the switchContentMethod in your controller may change the string returned by getContentPath :
now you can change the view displayed in the panel using the button in the menubar which sort of gives you navigation without page reloads.
Some advice ( or 'what I've learned' ) :
I was looking for information on the same topic and came across this link: How-to: Modular Java EE Applications with CDI and PrettyFaces which worked really well for me.
I understand that your question basically boils down to How can I include Facelets views in a JAR?
You can do this by placing a custom
ResourceResolver
in the JAR.Configure this in webapp's
web.xml
as follows:Imagine that you've a
/META-INF/resources/foo/bar.xhtml
inrandom.jar
, then you can just include it the usual wayor even dynamically
Note: since Servlet 3.0 and newer JBoss/JSF 2.0 versions, the whole
ResourceResolver
approach is not necessary if you keep the files in/META-INF/resources
folder. The aboveResourceResolver
is only mandatory in Servlet 2.5 or older JBoss/JSF versions because they've bugs inMETA-INF
resource resolving.See also: