Why doesn't JSF 2.0 RI (Mojarra) scan my class' annotations?
Solution 1:
Yes, I'm immediately answering my own question because I already spent a week banging my head on the table and I only figured out my problem after debugging through the JSF 2.0 RI (Mojarra) to see what it was doing.
Basically, the annotation scanner only consults the WAR's /WEB-INF/classes .class files for annotations (assuming you have a faces-config.xml in /WEB-INF). If you keep your code in separate Jar files and want your .class files you have in /WEB-INF/lib .jar files to be scanned for annotations, you must have a faces-config.xml in that Jar's META-INF folder. The faces-config.xml you plop into your jar can be empty, it just needs to be there or else the annotation scanner will passover your jar like it was leftover meatloaf.
Empty faces-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee /WEB-INF/schema/web-facesconfig_2_0.xsd"
version="2.0" metadata-complete="false">
<!-- This file must be present with our jar, even if it is empty. Otherwise, our Java annotations won't get scanned! -->
</faces-config>
I know a threw out a lot of -INF's there. So, just to recap. Your faces-config.xml in your War goes in WEB-INF. Your potentially empty, annotation scanner enabling, faces-config.xml in each of your Jar files goes in that Jar's META-INF.
If you're wondering why the behavior has to be so nutty, it's because the JSF configs can be decentralized and scattered across 1st and 3rd party libraries this way. And if you're wondering about the whole presence of the faces-config.xml in a jar being a factor, well, my opinion is that that is what marks a Jar as interesting to the engine - and the absence of a faces-config.xml means the annotation scanner can avoid that jar and save on processing at deployment time. It just would have been nice if those scanner semantics were a little more clearly explained somewhere, <expletives deleted>!
The following blog post was very useful in my understanding of what the code was doing:
http://one-size-doesnt-fit-all.blogspot.com/2007/01/using-multiple-faces-configxml-files-in.html
I really hope this saves someone from a week of pain like I had.
Solution 2:
A JAR contains both EJB & FacesBeans:
In the case that the JAR that contains Faces Beans is already bundled in an ear (because it contains EJBs), then you also have to put the same JAR in the WEB-INF/lib of the war (on top of adding the faces-config.xml in the META-INF directory), so that the container recognizes the JSF 2.0 Annotations.
In this case, it is probably better to create two JARS, one for the EJBs and one for the FacesBeans.