Closed ops4j-issues closed 10 years ago
Harald Wellmann commented
I've locally tried a number of different approaches to make things work, and the PrimeFaces sample now runs successfully. Some of my changes are rather brute force and not ready to be comitted, but maybe they can give us some ideas how to solve this issue properly.
Summary of changes:
I derived a ResourceDelegatingBundleClassLoader
from the Pax Swissbox BundleClassLoader which delegates resource loading to the set of wired bundles of the given WAB, determined via ClassPathUtil.getBundlesInClassSpace()
. (See https://eclipse.googlesource.com/virgo/org.eclipse.virgo.web/+/3.6.0.M04/org.eclipse.virgo.web.tomcat.support/src/main/java/org/eclipse/virgo/web/tomcat/support/FindResourceDelegatingClassLoader.java)
This classloader is used by RegisterWebAppVisitorWC
and HttpServiceStarted
and thus ensures that META-INF
resources can be loaded from wired bundles. This is not yet sufficient to discover faces-config.xml and *.taglib.xml, probably because the scanning happens too early or doesn't use the TCCL.
To discover faces-config.xml
resources, I copied the scanning approach of WebAppParser.tldScan() and programmatically added an init parameter javax.faces.CONFIG_FILES
with the URLs found.
Similarly, I added another init parameter javax.faces.FACELETS_LIBRARIES
for the META-INF/*taglib.xml
resources. The JSF spec only mentions (lists of) paths as possible values for these init parameters, but URLs seem to work at least for MyFaces (tested). From reading the source code, I think URLs would also work for Mojarra (not tested).
These changes are sufficient to make the PrimeFaces sample work. I also tried using the ResourceDelegatingBundleClassLoader
to discover the MyFaces ServletContainerInitializer
, with only partial success, the META-INF/services resource was found, but the referenced MyFaces class could not be loaded.
All of this is based on the 3.0.x branch.
Open questions:
Does this make sense at all?
Are there any standards or existing solutions giving directions how to best combine JSF and OSGi? (I've looked at Jetty, Virgo and OSGi EEG drafts and could not find anything.)
How to avoid tying a WAB to a given JSF implementation? Import-Package: org.apache.myfaces.* is clearly not the preferred solution. Possible apporach: Add package imports for available JSF implementation via OSGi 4.3 weaving hook.
How to select the bundles to be considered by the ResourceDelegatingBundleClassLoader
? Should resources really be loaded from any wired bundle? Stand-alone Jetty-OSGi handles META-INF/resources only from required bundles with visibility:=reexport. Is this the way to go? Should we use bundle capabilities instead?
Finally, if we decide to work on this issue for Pax Web, should commits go into 3.x, master, or a feature branch?
Christoph Läubrich commented
> How to avoid tying a WAB to a given JSF implementation
Why must the WAB import the JSF implementation? That does not sounds "right". If it useses direct classe of the JSF impl by name than it is tied to this anyways...
> This classloader ... ensures that META-INF resources ... This is not yet sufficient
If you want to get resources From bundles you shoudl always use the Bundle#findEntries methods and not the classloader. This prevents you from finding resource you are not exspecting (e.g. from required bundles!) and this also works even if the bundle is just installed.
Achim Nierbeck commented
Hi thanks for finding :smile:, JSF has been a real PITA right from the beginning so I'm not really surprised that it doesn't work again.
Here some thoughts regarding your questions:
Harald Wellmann commented
Achim, thanks for your feedback! I've created a new branch PAXWEB-614 from master, adapted my changes to 4.x and pushed them, just to get this started. (BTW, I'll be on vacation and off-line for a week...)
I noticed that setting init parameters like javax.faces.CONFIG_FILES
to bundleresource:
URLs does not work in vanilla Jetty and seems to depend on PAXWEB-314 . Maybe we can find a better approach.
For loading resources from META-INF/resources
in other JARs, vanilla Jetty does not mess with the classloader but creates a ResourceCollection
used as base resource in the ServletContext. Maybe this approach can be adapted for Pax Web and tweaked to also cover other META-INF
stuff like config files.
Achim Nierbeck commented
I've finally had a chance to check your changes. +1 for them. :smile:
I can see that the bundleresource: URL isn't optimal, I like that idea of a specialized ResourceCollection for using this.
regarding Versions, I tend to just use it for the 4.0, since it's been quite a hassle with maintaining lots of the different versions available.
Achim Nierbeck commented
just as a note:
I just ran some tests with the PAXWEB-123 branch (doesn't contain these changes yet) and JSF worked like a charm, so you must have hit a "corner" case with this. Or be affected by something that troubled me now for more then a week, some tests when run with Pax-Exam-Karaf fail but work if you use it directly in Karaf without any stack traces.
Harald Wellmann commented
Well, I didn't say JSFdidn't work at all... Things are fine as long as all JSF resources are in your WAB.
But when you start working with component libraries in separate bundles, these components or tags are not rendered correctly. I wouldn't call that a corner case - most JSF applications use a component library like PrimeFaces, RichFaces, ICEFaces etc.
pax-shiro-faces is a small but instructive example. See FacesBundleTest
vs. Jetty9FacesBundleTest
in https://github.com/ops4j/org.ops4j.pax.shiro/tree/master/itest/itest-osgi/src/test/java/org/ops4j/pax/shiro/itest/osgi
FacesBundleTest
uses Pax Web 3.0.2 and has a failing test (marked as @Ignore
).
Jetty 9 in OSGi mode (without Pax Web) does not work out of the box either, but I added a small boot fragment which solves the issue - see Jetty9FacesBundleTest
.
Achim Nierbeck commented
It works for "std" jsp taglibs though, so it's more an issue of how JSF uses them ...
I'm with you that we need to improve this, and better in Pax-Web then in Jetty :grinning:
Harald Wellmann commented
What exactly do you mean by "standard JSP taglibs"? I'm mainly concerned with Facelet taglibs and XHTML views. JSP views are deprecated in JSF 2.1.
If you mean the JSTL tags from the http://java.sun.com/jsp/jstl/core
namespace or other namespaces defined by the JSF spec, then the point is that these tags do not come from a separate bundle but are part of the JSF implementation (at least with MyFaces, I didn't check Mojarra). This explains why these tags work out of the box, coming from the same bundle classloader.
Tags from any other bundle (i.e. neither from the JSF implementation nor from the web application bundle) don't work, i.e. they get rendered verbatim.
E.g. in my shiro tests, the rendered HTML contains tags like <shiro:guest>
, when the tag is really expected not to show up, but to hide or display its body content, depending on the current user.
Achim Nierbeck commented
yeah, call me "old-school" :smile: though a std. JSP without JSF extras does work and the taglib "crawler" which scans through all connected bundles does provide them.
This did work for PAXWEB-314 and to my knowledge it still does.
Does your test work with the 4.0.0-SNAPSHOT ( PAXWEB-614 branch)?
Achim Nierbeck commented
fix for trunk
Branch: refs/heads/master
Home: https://github.com/ops4j/org.ops4j.pax.web
Commit: 1e0c019a72733d9d4d8321f9d54c69d47d116ff2
https://github.com/ops4j/org.ops4j.pax.web/commit/1e0c019a72733d9d4d8321f9d54c69d47d116ff2
Date: 2013-10-29 (Tue, 29 Oct 2013)
Achim Nierbeck commented
Branch: refs/heads/pax-web-3.0.x
Home: https://github.com/ops4j/org.ops4j.pax.web
Commit: 771a23f7fca62e47d1c947ca6407d52ab629b0a8
https://github.com/ops4j/org.ops4j.pax.web/commit/771a23f7fca62e47d1c947ca6407d52ab629b0a8
Date: 2013-11-01 (Fri, 01 Nov 2013)
Achim Nierbeck commented
Merged the PAXWEB-614 branch to master and 3.0.x
Guillaume Nodet commented
Note that the OSGi/WAB spec is quite clear and I think the current pax-web implementation does not follow the spec.
It seems to me that the spec, paragraph 128.3.7 says that TLDs can only discovered in the bundle class space, so scanning all transitively wired bundles for tld seems wrong (though I fully understand the idea beneath).
Harald Wellmann created PAXWEB-614
JSF WABs using tag libraries from other bundles do not currently work out of the box.
See e.g. WarJSFPrimefacesIntegrationTest.
(The test misleadingly passes, but in fact it only checks that
<p:panelGrid>
gets rendered verbatim instead of being processed by PrimeFaces.)In particular, the following JSF 2.1 and Servlet 3.0 requirements do not work at the moment:
Affects: 3.0.2 Fixed in: 3.0.3, 4.0.0 Votes: 0, Watches: 4
Referenced issues
blocks: