35

I have two JSF projects that share a lot of code - java classes, xhtml files, tag libraries, css and javascript files etc. My dev environment/platform consists mainly of Eclipse, Ant, Perforce and Tomcat.

Has anyone found a way to create and organize the shared code so that the common code can stay within one set of folders?

Eclipse makes it easy to add external folders for java sources, but falls short on the other file types. I'd appreciate any ideas.

Heizenberg
  • 353
  • 1
  • 4
  • 5

1 Answers1

65

Create a new "Java Project" in Eclipse. Add it as another project to the Deployment Assembly property of the main dynamic web project. This way it will automatically end up as a JAR in /WEB-INF/lib of the build of the web project. Since newer Eclipse versions, you can also create the project as "Web Fragment Project". This way the Deployment Assembly step will be done automatically.

Put all those shared JSF2/Facelets resource files in /META-INF/resources folder of the Java project. Just treat it like WebContent/resources of the main web project. Tagfiles can just be kept in their own /META-INF/tags folder.

E.g.

CommonWebProject
 |-- META-INF
 |    |-- resources
 |    |    `-- common
 |    |         |-- css
 |    |         |    `-- some.css
 |    |         |-- js
 |    |         |    `-- some.js
 |    |         |-- images
 |    |         |    `-- some.png
 |    |         |-- components
 |    |         |    `-- somecomposite.xhtml
 |    |         `-- sometemplate.xhtml
 |    |-- tags
 |    |    `-- sometag.xhtml
 |    |-- beans.xml
 |    |-- faces-config.xml
 |    |-- some.taglib.xml
 |    |-- web-fragment.xml
 |    `-- MANIFEST.MF
 :

with

<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 />
<common:sometag />
<ui:include src="/common/sometemplate.xhtml" />
...

In case you're using Maven, the /META-INF folder has to be placed in src/main/resources and thus NOT src/main/java.

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, create a JSF2 compatible /META-INF/faces-config.xml file as well (it can even be kept empty).

<?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>

That's all.

See also:

Community
  • 1
  • 1
BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • 5
    Many thanks! I'm also honored by *your* response having frequented your blogs on a number of JSF issues on many occasions! – Heizenberg Nov 30 '11 at 03:58
  • 1
    @Heizenberg, if he helped, mark the reply as an answer and vote it up by clicking the up arrow on the side. Its the stack exchange way of saying thanks :) – Fredrik Nov 30 '11 at 08:57
  • 1
    Thanks Fredrik. I marked it as an answer with the "tick" mark. I now need to "build a reputation" so I can vote it up (needs "15 reputation" to vote up) – Heizenberg Nov 30 '11 at 14:17
  • @BalusC: Is this different if I'm using JSF 1.2? – Heizenberg Dec 01 '11 at 19:45
  • Yes, it is. You'd need to implement a facelets resource resolver: http://stackoverflow.com/questions/5587808/how-to-use-facelets-composition-with-files-from-another-context/5589173#5589173. But since you mentioned "xhtml" and JSF 1.2 is exit for 2 years, I automatically assumed JSF 2.0... So, you're using JSF 1.2? Sorry, my bad, I should not have assumed JSF 2.0. Is there any chance to upgrade it? This may be helpful then: http://stackoverflow.com/questions/4441713/migrating-from-jsf-1-2-to-jsf-2-0/4532870#4532870 – BalusC Dec 01 '11 at 19:48
  • Thanks... I've redone the resource resolver and fit it in... I'm missing the tag that actually includes the resource sitting in the jar file. Don't have access to h:outputStylesheet in 1.2. As for 1.2 to 2.0 migration, I have a ton of customizations with RichFaces that I've been using that will take time to migrate ... it's a hard sell at this point to my manager. – Heizenberg Dec 02 '11 at 03:53
  • Those tags are available since JSF 2.0 only. You'd need to create a servlet which does the streaming job. – BalusC Dec 02 '11 at 04:02
  • I tried a few options: threw a XML parse exception (I assume this is because it's trying to actually parse and interpret the contents of the CSS file) - this simply does not resolve the content and I see an http 404 error (The requested resource (/test-web/view/content/common/css/base.css) – Heizenberg Dec 02 '11 at 04:30
  • Those JSF 2.0 tags actually load those resources from the classpath, not from public web content. You cannot link to JAR-packaged resources by URL. You need to create a servlet which does essentially the same by `Thread.currentThread().getContextClassLoader().getResourceAsStream("/META-INF/resources" + request.getPathInfo())` and so on. Then, you invoke that servlet by URL instead like as `` – BalusC Dec 02 '11 at 04:32
  • Should `` not have `/resources` added as prefix? Both don't work for me if i move that resource into a shared jar in `src/META_INF/resources/common/sometemplate.xhtml` – djmj Oct 05 '12 at 19:35
  • @BalusC, if I have any dependencies of external libraries to compile such **Java Project**, I mean ***.jar** libraries, will it include them into compiled ***.jar**? What happened if I have same ***.jar** in a both projects, **Java Project** and **Dynamic Web Project**? Will it included twice? Thank you. – Anatoly Feb 04 '15 at 07:53
  • Where should I put my resource bundles (i.e. language properties files)? I have exactly the structure like described here. I've tried to put my language files in every possible directory and registered the resource bundle in faces-config, however, the texts are not resolved. – Filip Majernik Mar 12 '15 at 09:52
  • @Filip: They're looked up as classpath resources, not as web resources. So, just put them in a package like normal Java classes. See also the answers which you can find when you search on the error message you got. – BalusC Mar 12 '15 at 13:24
  • @BalusC: Thanks for a prompt answer as always. I have already figured it out. However, I think the behavior is like this: the resource bundle is first lookedup in the web application and if it is not found, it is lookedup in jar. My problem was that I had the files with the same name in the webapp and also in the shared lib but exposed as different vars in faces-config. I got no error message and even no ???key??? like errors. Just nothing. – Filip Majernik Mar 12 '15 at 13:29