Is it possible to put JSF2 Facelets files with common content into a JAR to use it from other web applications inside e.g. <ui:composition template>, <ui:include src>, <cc:implementation>, etc? If yes, how can I achieve this? Is some extra configuration necessary?
You can put common resources in the /META-INF/resources folder of the JAR which is to be treated like as /WEB-INF/resources folder of the WAR.
E.g.
CommonWebProject
|-- META-INF
| |-- resources
| | `-- common
| | |-- css
| | | `-- some.css
| | |-- js
| | | `-- some.js
| | |-- images
| | | `-- some.png
| | |-- components
| | | `-- somecomposite.xhtml
| | |-- someinclude.xhtml
| | `-- sometemplate.xhtml
| |-- faces-config.xml
| `-- MANIFEST.MF
:
The resources of the JAR are then available as follows:
<... xmlns:common="http://xmlns.jcp.org/jsf/composite/common/components">
<h:outputStylesheet library="common" name="css/some.css" />
<h:outputScript library="common" name="js/some.js" />
<h:graphicImage library="common" name="images/some.png" />
<common:somecomposite />
<ui:include src="/common/someinclude.xhtml" />
<ui:composition template="/common/sometemplate.xhtml" />
...
If you want to trigger the JSF2 annotation scanner as well so that you can put #ManagedBean, #FacesValidator, #FacesConverter and consorts in that project as well, then create a JSF2 compatible /META-INF/faces-config.xml file:
<?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>
The Facelets resource resolver is only necessary if the resources are not in /META-INF/resources for some reason, or when you're not using Servlet 3.0 but 2.5, or when you're using an early JBoss/JSF version which has bugs in META-INF resource resolving. See also How to create a modular JSF 2.0 application? for a concrete example.
Yes, you can extend com.sun.faces.facelets.impl.DefaultResourceResolver to provide resources to JSF.
One generic solution is as follows:
In your pom.xml add:
<dependency>
<groupId>com.intersult</groupId>
<artifactId>jsf-desktop</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<repository>
<id>intersult-repo</id>
<name>Intersult Repository</name>
<url>https://intersult.com/svn/public/maven</url>
</repository>
Or simply add https://intersult.com/svn/public/maven/com/intersult/jsf-desktop/1.1-SNAPSHOT/jsf-desktop-1.1-SNAPSHOT.jar to your /WEB-INF/lib folder.
In your web.xml add:
<context-param>
<param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
<param-value>com.intersult.jsf_desktop.util.ClassPathResourceResolver</param-value>
</context-param>
In any JAR inside the WAR place XHTML-Files under /META-INF/resources/<file.xhtml>
Access it via "http://<domain>/<web-root>/<jsf-servlet>/resource/<file.xhtml>" (eg. http://localhost/faces/resource/test.xhtml) and it will be rendered.
First read here about the difference between war and jar in a similar question.
You will have to create EAR file and pack the wars together.
Maven
Note that, if you are using Maven to create a JAR, you should use the following folder to put your resources into:
src/main/resources/META-INF/resources/
Related
My JSF web application shows the following error:
/index.xhtml Not Found in ExternalContext as a Resource.
My directory structure is:
- Java Resource
-- src
--- br.com.k19.controle
---- NumeroAleatorioBean.java
--- resources
- JavaScript Resources
- build
- WebContent
-- META-INF
-- Web Pages
--- index.xhtml
--- formulario.xhtml
-- Web-Inf
Where do I need to put my /index.xhtml in this structure?
The WebContent folder represents the web content. You placed the index.xhtml file inside Web Pages subfolder so the right URL would be
http://localhost:8080/ProjectName/Web Pages/index.xhtml
and thus not
http://localhost:8080/ProjectName/index.xhtml
as you seemed to expect.
If you want to have it on the context root, just get rid of the Web Pages folder altogether and move those .xhtml files directly inside WebContent folder, in the same level as META-INF and WEB-INF:
ProjectName
|-- Java Resources
| `-- src
| `-- br.com.k19.controle
| `-- NumeroAleatorioBean.java
|-- resources
|-- JavaScript Resources
|-- build
`-- WebContent
|-- META-INF
|-- WEB-INF
| |-- faces-config.xml
| `-- web.xml
|-- index.xhtml
`-- formulario.xhtml
Note: Java is case sensitive. Web-Inf is definitely not the same as WEB-INF. Be careful or you'll have a security hole.
I faced this issue recently. I tried cleaning the Tomcat Work Directory, Clean, and Publish.
After that, when I started the server, the application was running smooth.
For independent tomcat server, clean dir --> temp, work, and inside webApp directory, remove all the existing unarchived project.
Restart the Tomcat, it worked for me.
What is wrong with my very very simple web app: web app successfully deployed to app server but hello bean did not inject to index.xhtml page
(page shows just Hello from Facelets: #{hello.value})?
(this is first time when I am working with JSF, so maybe this question is very easy, and also I used good article http://arjan-tijms.omnifaces.org/2011/08/minimal-3-tier-java-ee-app-without-any.html )
I have the next structure of war archive:
mywebapp
|
- WEB_INF
|
- classes
|
- Hello.class
- index.html
Hello.java has:
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
#Named
#RequestScoped
public class Hello {
private String value;
public String getValue() {
return "Hello JSF";
}
public void setValue(String value) {
this.value = value;
}
}
and also my index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>My Facelet Page Title</title>
</h:head>
<h:body>
Hello from Facelets: #{hello.value}
</h:body>
</html>
For building project I used pom.xml:
....
<packaging>war</packaging>
<name>Simple web app</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Taken from JavaServerFaces 2.0, The Complete Reference:
An entry in the Web application’s web.xml file enables the Faces Controller servlet
when a certain URL pattern is specified, such as /faces/. When running JSF 2.0 on
a Servlet 3.0 container, such as Sun’s Glassfish v3, the web.xml is optional. If no
web.xml is found, the Faces Controller servlet is automatically mapped to the most
popular URL patterns: /faces/, .jsf, and .faces.
So you should try with something like this:
localhost:8080/mywebapp/faces/index.xhtml.
According to the javadoc, FacesServlet will be automatically registered if any of the following conditions are true:
A faces-config.xml file is found in WEB-INF
A faces-config.xml file is found in the META-INF directory of a jar in the application's classpath.
A filename ending in .faces-config.xml is found in the META-INF directory of a jar in the application's classpath.
The javax.faces.CONFIG_FILES context param is declared in web.xml or web-fragment.xml.
The Set of classes passed to the onStartup() method of the ServletContainerInitializer implementation is not empty.
If you are using web.xml only for registering FacesServlet, then it would be optional if any of the above conditions are met.
I have added a common JAR to my project. The jar looks something like...
CommonWeb.jar
|-- META-INF
| |-- resources
| | `-- common
| | |-- css
| | | `-- my.css
| | |-- js
| | | `-- my.js
| | |-- images
| | | `-- my.png
| | |-- components
| | | `-- mycomposite.xhtml
| | `-- templates
| | `-- mytemplate.xhtml
| |-- faces-config.xml
| `-- MANIFEST.MF
:
Everything is working except that Netbeans will not recognise my composite component. The page trying to use the component looks something like this...
<ui:composition template="/resources/common/templates/mytemplate.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:cmn="http://java.sun.com/jsf/composite/common/components">
<ui:define name="content">
...
<cmn:mycomposite ... />
...
</ui:define>
</ui:composition>
The project will compile and run, no worries. But the IDE gives me red squiggly lines on <cmn:mycomposite ... /> and does not auto-complete, etc. It will all work fine if I copy the component into the project's own resources folder, so it seems netbeans just isn't looking to the jar.
There are quite a few questions around with similar problems, eg:
JSF Composite Component into JAR in NetBeans
JSF Composite Component Netbeans
Composite components in an external JAR are not recognized in
Netbeans
...but there are no satisfactory solutions or workarounds.
Also there have been a few netbeans bug reports on the matter but these all seem to be 'fixed'
Is there some configuration that I'm missing? Has anyone actually managed to get this working with the latest version of NetBeans (NetBeans 7.4 Patch 2 at time of writing)? Has anyone found a work-around that actually works?
UPDATE:
This problem continues to occur in NetBeans 8
This issue is an IDE only issue and continues in version 8.1. It stems from the bug identified in Netbeans bugzilla - specifically in the "JSF Editor for XHTML" module (org.netbeans.modules.web.jsf.editor)
I resolved the issue by downloading the version 8.1 source files for Netbeans and applying the suggested patch myself. I'm guessing it's a similar issue in earlier versions but I didn't check this.
To download and compile Netbeans you can follow the "How To" in here
Changes in summary:
CompositeComponentModel.java line 296 changed to:
if (parent != null && parent.getName().equalsIgnoreCase("META-INF")) { //NOI18N
JsfBinaryIndexer.java line 74 changed to:
namePattern = ".*\\.tld|.*\\.taglib\\.xml|.*\\.xhtml",
Indexer version incremented on line 81 changed to:
static final int INDEXER_VERSION = 11; //NOI18N
Given that the bug is being tracked hopefully it makes it into the next release.
My JSF web application shows the following error:
/index.xhtml Not Found in ExternalContext as a Resource.
My directory structure is:
- Java Resource
-- src
--- br.com.k19.controle
---- NumeroAleatorioBean.java
--- resources
- JavaScript Resources
- build
- WebContent
-- META-INF
-- Web Pages
--- index.xhtml
--- formulario.xhtml
-- Web-Inf
Where do I need to put my /index.xhtml in this structure?
The WebContent folder represents the web content. You placed the index.xhtml file inside Web Pages subfolder so the right URL would be
http://localhost:8080/ProjectName/Web Pages/index.xhtml
and thus not
http://localhost:8080/ProjectName/index.xhtml
as you seemed to expect.
If you want to have it on the context root, just get rid of the Web Pages folder altogether and move those .xhtml files directly inside WebContent folder, in the same level as META-INF and WEB-INF:
ProjectName
|-- Java Resources
| `-- src
| `-- br.com.k19.controle
| `-- NumeroAleatorioBean.java
|-- resources
|-- JavaScript Resources
|-- build
`-- WebContent
|-- META-INF
|-- WEB-INF
| |-- faces-config.xml
| `-- web.xml
|-- index.xhtml
`-- formulario.xhtml
Note: Java is case sensitive. Web-Inf is definitely not the same as WEB-INF. Be careful or you'll have a security hole.
I faced this issue recently. I tried cleaning the Tomcat Work Directory, Clean, and Publish.
After that, when I started the server, the application was running smooth.
For independent tomcat server, clean dir --> temp, work, and inside webApp directory, remove all the existing unarchived project.
Restart the Tomcat, it worked for me.
Ear file:
ear
+--lib
| +--API jar
| | +-- com.foobar.Greeter.class (interface)
| | (look, ma, no META-INF/beans.xml on purpose)
| |
| +--JAX-RS endpoint jar
| +-- com.foobar.GreeterResource.class (has #Inject Greeter greeter;)
| +-- META-INF/beans.xml
|
+--EJB jar
| +-- com.foobar.GreeterBean implements com.foobar.Greeter (#Stateless, #Local)
| +-- META-INF/beans.xml
|
+--JAX-RS skinny war (no libs)
+-- WEB-INF/beans.xml (maybe not necessary?)
+-- WEB-INF/classes/com.foobar.Application
(empty subclass of JAX-RS Application)
To recap in English:
API jar file. Contains Greeter interface. Present in lib directory.
EJB jar file. Contains a #Stateless #Local EJB that implements Greeter. Also contains a META-INF/beans.xml file. CDI says this is necessary to make this a bean archive.
Skinny war. Exists only to have an (empty) Application class in it to serve as the bootstrappy part of JAX-RS. Endpoints are NOT located within. Contains a WEB-INF/beans.xml file, though I confess I'm not sure this is necessary, since by definition WEB-INF/beans.xml marks only the classes directory (which here does not exist) as a bean archive.
JAX-RS endpoint jar file. This one's slightly weird. Present in the .ear lib directory, so on the classpath, but not in the .war file's lib directory (on purpose). Discovered—per the JAX-RS 1.1 specification—automatically by the JAX-RS application, so classes within it are probably in a kind of tug-of-war between JAX-RS and CDI. GreeterResource contains #Inject Greeter greeter;.
Deploying this in GlassFish 3.1.2.2 (Weld 1.1.8) yields an unsatisfied dependency error for the #Inject location. WTF?
Why? The only Greeter instance in the whole application is an EJB implementation, which is in a bean archive. The resource class is in a bean archive. I read the specification as saying that session beans automatically have their business local interfaces registered as bean types.