Deploying backing bean with composite component in separate jar - jsf

I have some difficulties deploying my web app on JBoss AS 6.1. My current Project is separated into the main web app (controller/managed beans & web frontend using JSF 2 facelets) and one jar with the composite components + backing beans. But when I try to access the page I got an error that the specified component type could not be instantiated.
Copying the backing bean into the main web app solves the problem, but this isn't what I want. So is there anything to pay attention to?
The backing bean looks like
#FacesComponent(value = "elementBase")
public class ElementBase extends UINamingContainer {
...
}
and the composite components interface
<composite:interface componentType="elementBase">
... some attributes
</composite:interface>
The structure of the jar is the following
-- META-INF
|-- resources
| |-- components
| |-- elementBase.xhtml
-- com
|-- example
| |-- ElementBase.class
I've also tried to add faces-config.xml within META-INF folder, with the component type, but the component type was still not found.

Through the BalusC's answer to the question JEE6> Packaging JSF facelets (xhtml) and ManagedBeans as JAR
As to the managed beans and other JSF classes like validators, converters, etc, just annotate them with #ManagedBean, #FacesValidator, #FacesConverter, etc and package them in the JAR the usual way. You only need to provide a JSF 2.0 compatible /META-INF/faces-config.xml file in the JAR.
<?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 http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
</faces-config>
This way JSF will be triggered to scan the classes in the JAR for JSF specific annotations. Alternatively you can also just register them in the JAR's faces-config.xml the JSF 1.x way.
and Java EE6 Tutorial: Application Configuration Resource File
You can have more than one application configuration resource file for an application. The JavaServer Faces implementation finds the configuration file or files by looking for the following:
A resource named /META-INF/faces-config.xml in any of the JAR files in the web application’s /WEB-INF/lib/ directory and in parent class loaders. If a resource with this name exists, it is loaded as a configuration resource. This method is practical for a packaged library containing some components and renderers. In addition, any file with a name that ends in faces-config.xml is also considered a configuration resource and is loaded as such.
A context initialization parameter, javax.faces.application.CONFIG_FILES, in your web deployment descriptor file that specifies one or more (comma-delimited) paths to multiple configuration files for your web application. This method is most often used for enterprise-scale applications that delegate to separate groups the responsibility for maintaining the file for each portion of a big application.
A resource named faces-config.xml in the /WEB-INF/ directory of your application. Simple web applications make their configuration files available in this way.
.. I could fix my problem.
Step by step solution
Create backing bean
#FacesComponent(value = "elementBase")
public class ElementBase extends UINamingContainer {
...
}
and a composite components with the following interface
<composite:interface componentType="elementBase">
... some attributes, value holder, ..
</composite:interface>
provide a faces-config.xml within the deployed jar, to indicate that the jar contains annotated classes. The structure of the deployed jar should look like
-- META-INF
|-- resources
| |-- components
| |-- elementBase.xhtml
|-- faces-config.xml
-- com
|-- example
| |-- ElementBase.class
deploy the jar within the /WEB-INF/lib folder of the web application.
Research/Related links and topics
JEE6> Packaging JSF facelets (xhtml) and ManagedBeans as JAR
Java EE6 Tutorial: Application Configuration Resource File
JSF facelets template packaging
How to create a modular JSF 2.0 application?

Related

java.lang.IllegalArgumentException: Multiple entries with same key: interface javax.validation.constraints.Min

I'm running an EAR with EJB + EJB + WAR deployment in JBoss WildFly 8.2.0.Final with JSF 2.2 and RichFaces 4.5.2.Final. My problem is, that all RichFaces resources fail to load properly in the client. The generated URL don't resolve and return with HTTP 404.
The deployment is build upon Maven und results in the following structure:
The reason for using <scope>compile</scope> in the EJB module and not the WAR is that I need to extend RichFaces classes from within my EJB module. We've build a dynamic form generator based on some of the components.
As soon as I add JARs to EAR/lib/ and WAR/WEB-INF/lib/ by using <scope>compile</scope> instead of <scope>provided</scope> in the WAR module I get the following stacktrace while starting the application server:
Caused by: java.lang.IllegalArgumentException: Multiple entries with same key: interface javax.validation.constraints.Min=org.richfaces.javascript.LibraryFunctionImplementation#c77af4e and interface javax.validation.constraints.Min=org.richfaces.javascript.LibraryFunctionImplementation#5a903150
at com.google.common.collect.ImmutableMap.checkNoConflict(ImmutableMap.java:150)
at com.google.common.collect.RegularImmutableMap.checkNoConflictInBucket(RegularImmutableMap.java:104)
at com.google.common.collect.RegularImmutableMap.<init>(RegularImmutableMap.java:70)
at com.google.common.collect.ImmutableMap$Builder.build(ImmutableMap.java:254)
at org.richfaces.javascript.ClientServiceConfigParser.parseConfig(ClientServiceConfigParser.java:75)
at org.richfaces.application.ValidatorModule.createClientScriptService(ValidatorModule.java:65)
at org.richfaces.application.ValidatorModule.configure(ValidatorModule.java:60)
at org.richfaces.application.ServicesFactoryImpl.init(ServicesFactoryImpl.java:60)
at org.richfaces.application.InitializationListener.createFactory(InitializationListener.java:110)
at org.richfaces.application.InitializationListener.onStart(InitializationListener.java:69)
at org.richfaces.application.InitializationListener.processEvent(InitializationListener.java:167)
at javax.faces.event.SystemEvent.processListener(SystemEvent.java:108)
at com.sun.faces.application.ApplicationImpl.processListeners(ApplicationImpl.java:2190)
at com.sun.faces.application.ApplicationImpl.invokeListenersFor(ApplicationImpl.java:2163)
at com.sun.faces.application.ApplicationImpl.publishEvent(ApplicationImpl.java:303)
at org.jboss.as.jsf.injection.weld.ForwardingApplication.publishEvent(ForwardingApplication.java:294)
at com.sun.faces.config.ConfigManager.publishPostConfigEvent(ConfigManager.java:692)
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:260)
... 9 more
How can I solve this problem?
Frontend artifacts don't belong in EAR's /lib. They belong in WAR's /WEB-INF/lib. It would otherwise make the backend (the EJB) totally unreusable on other frontends (other WARs), such as Spring MVC, JAX-RS RESTful, "Plain vanilla" JSP/Servlet, etc..etc.. Using/importing JSF FacesContext and friends such as Servlet's HttpServletRequest in an EJB class is already a seriously big red alert. You should not be doing that.
Move that code to WAR. Or, if you intend to make it reusable across various WARs, make it a web fragment project instead which can then end up as another JAR in /WEB-INF/lib.
See also:
JSF Service Layer

ExternalContext#getResourceAsStream() returns null, where to place the resource file?

I'm trying to obtain a PNG file as InputStream in my managed bean as below:
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
InputStream input = externalContext.getResourceAsStream("/myFile.png");
// input is null.
However, the InputStream is always null. How is this caused and how can I solve it?
Apparently you placed the resource in physically the wrong location.
The ExternalContext#getResourceAsStream(), which delegates in case of servlet containers under the covers to ServletContext#getResoruceAsStream(), has its root in the web content of the WAR (the parent folder of /WEB-INF and /META-INF folders, thus the files therein are also available this way), and the /META-INF/resources folder of all JARs in /WEB-INF/lib. In case of a JSF web application it are usually XHTML, CSS, JavaScript and image files.
In other words, it returns web resources. It doesn't return a disk file system resource, for that you need new FileInputStream() instead. It also doesn't return a classpath resource, for that you need ClassLoader#getResourceAsStream() instead. The classpath has its root in a.o. /WEB-INF/classes, all JARs in /WEB-INF/lib, and some VM/server-configured folders depending on the runtime environment.
In an usual web content file structure, the resource file has to be placed exactly here in order to obtain it the desired way:
WebContent
|-- META-INF
|-- WEB-INF
| |-- faces-config.xml
| `-- web.xml
|-- myFile.png <-- Here.
:
getResourceAsStream() vs FileInputStream
Accessing properties file in a JSF application programmatically
Where to place and how to read configuration resource files in servlet based application?
How to get the root path of a web project in java EE

Inject jndi string resource on embedded glassfish using CDI not working

So I created a custom reference in the domain.xml
<custom-resource res-type="java.lang.String" jndi-name="jndi/myResource" factory-class="org.glassfish.resources.custom.factory.PrimitivesAndStringFactory">
<property name="value" value="myValue"/>
</custom-resource>
And referencing it through #Resource(lookup = "jndi/myResource") in a #ApplicationScoped bean.
I am also starting the server with the endorsed directory(containing the endorsed-api.jar). Still when I reference the resource, its not injecting and throwing a null.
Looks like everything is setup correctly, not sure what I am missing here.
And yes, I have beans.xml in the Meta-inf directory too.

Can the index.xhtml be stored in an external JAR file? What would be its URL?

I'd like to have all the facelets and managed bean into one external jar, but if I put de index.xhtml there I don't konw how to reference it.
If the jar structure is:
IndexManagedBean.class
META-INF/
resources/
pages/
index.xhtml
What is its URL?
Assuming that the JAR is placed in webapp's /WEB-INF/lib folder and that you're using JSF 2.x and that webapp's context path is /contextpath, and the FacesServlet is mapped on an URL pattern of *.xhtml then you can reference it by the following URL:
http://example.com/contextpath/pages/index.xhtml
See also
Structure for multiple JSF projects with shared code

Injecting EJB3.0 Beans into JSF2.0 Backing Beans... Impossible?

I'm working on a JSF project on Weblogic 11g, and our initial design is calling for JSF Backing Beans to invoke EJB3.0 beans to perform business logic and data access calls. The #EJB annotation doesn't seem to work in my project when I try to inject the EJB reference to the backing bean. Whenever I hit the class that I am testing, the constructor for my EJB is never called and I end up with a NPE. Is it possible to inject an EJB3.0 bean into a JSF backing bean? Is there another way I should be invoking an EJB through the JSF Backing bean? What is the best practice?
I googled somewhat and this indeed seems to be a known issue with Weblogic. Lot of similar topics are kept unanswered.
I found this blog which confirms that #EJB in Weblogic only works for resources definied by web.xml, not for JSF. The blog describes also in detail a workaround using ServletContextListener which is IMO not much better than using JNDI.
I also found this OTN topic which confirms that #EJB in Weblogic started to work when EJB modules are not included in subdirectories (see the answer posted at the bottom, Feb 15, 2011 5:44 PM).
It turns out that it is a Weblogic specific issue when deploying anything using JSF and EJB. I found this post on the Oracle forums that explains how to get the #EJB injection working in JSF Managed Beans using Weblogic 11g:
EJB3.0 Injection into JSF Managed beans
UPDATE:
After spinning my wheels for too long, I have to give up trying to inject an EJB into a JSF ManagedBean on Weblogic 11g. Seems to work fine in Tomcat. Maybe the EJB3 and JSF implementation will be better in 12G...
To make it work you need to follow two steps:
Deploy jsf-2.0.war as LIBRARY, you can find it /ORACLE_HOME/wlserver_10.3/common/deployable-libraries
In your web project, add the reference to the jsf-2.0.war library in WEB-INF/weblogic.xml
<?xml version="1.0" encoding="UTF-8"?>
<wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.1/weblogic-web-app.xsd">
<wls:weblogic-version>10.3.3</wls:weblogic-version>
<wls:context-root>your_context_app</wls:context-root>
<wls:library-ref>
<wls:library-name>jsf</wls:library-name>
<wls:specification-version>2.0</wls:specification-version>
<wls:implementation-version>1.0.0.0_2-0-2</wls:implementation-version>
<wls:exact-match>true</wls:exact-match>
</wls:library-ref>
</wls:weblogic-web-app>
I have successfully tested this in weblogic 10.3.3 and 10.3.5. If somehow this does not work, try to deploy the application as part of EAR file.
So here is the beat! There is a simple way to fix this.
Open up jsf-2.0.war under ...wlserver_10.3\common\deployable-libraries
Navigate to WEB-INF/lib and save wls.jsf.di.jar JAR somewhere
Place wls.jsf.di.jar JAR under lib folder of your WAR application.
Deploy
all should work now just by adding #EJB to property in your #ManagedBean.
There is an alternative for the #EJB annotation in order to get your local EJB bean accessible in your JSF ManagedBean web application. Considering that you have your EJB classes and your WAR packaged in the same EAR file, do the following:
configure your ejb-jar.xml to tell the weblogic expose the EJB beans to the external components;
<enterprise-beans>
<session>
<ejb-name>MyEJBBean</ejb-name>
<business-local>com.app.MyEJBBeanLocalInterface</business-local>
<ejb-class>com.app.MyEJBBeanLocalImpl</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBBeanLocal</ejb-ref-name>
<local>com.app.MyEJBBeanLocalInterface</local>
</ejb-local-ref>
</session>
<enterprise-beans>
Insert in the web.xml of your web application a reference to the EJB throught the ejb-link name. The ejb-ref-name is name visible for the JSF managed beans.
<ejb-local-ref>
<ejb-ref-name>ejb/MyEJBBeanLocal</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<local>com.app.MyEJBBeanLocalInterface</local>
<ejb-link>MyEJBBean</ejb-link>
</ejb-local-ref>
In your JSF Managed Bean call the EJB Bean through JNDI lookup as the following:
try {
Context context = new InitialContext();
MyEJBBeanLocalInterface myEJBBean =
context.lookup("java:comp/env/ejb/MyEJBBeanLocal");
} catch (NamingException e) {
e.printStackTrace();
}
In my case I was using the Weblogic 10.3.6 (11g), JSF 2.0 and EJB 3.0 with JPA (Eclipselink)

Resources