4
votes

We have a library that contains small additions to functionality provided by JSF (things like additional ResourceHandlers).

As it uses JSF classes (from javax.faces.* packages), it naturally must depend on the JSF API. The library is packaged as a Maven project, and depends on com.sun.faces:jsf-api.

This works fine for compiling, and for use in projects that use Mojarra. However, if we include the library in a JSF application that uses MyFaces, we get errors, as described in Exception: could not find Factory: javax.faces.context.FacesContextFactory .

Apparently, if an application uses MyFaces, it must use myfaces-api.jar and myfaces-impl.jar (or the corresponding Maven deps), and not jsf-api.jar or jsf-impl.jar.

This leaves me a bit confused.

  • Why do Mojarra and MyFaces use different API jars? Both implement the same API (JSF), so shouldn't they use the same API jars?
  • I thought the whole point of having seperate "api" and "impl" jars was that only the "impl" part has to be switched to use a different implementation. Did I misunderstand something?
  • More concretely: What is the right Maven dependency for a library that should only depend on the JSF API? Right now, we depend on jsf-api, and projects that use MyFaces must use <exclusions> to throw out jsf-api and include myfaces-api. That works, but surely there is a better way?
2
We're using the provided JSF jars from JBoss AS however there is a maven dependency for the jsf api that we're using for source code download. Here is its definition: <dependency> <groupId>org.jboss.spec.javax.faces</groupId> <artifactId>jboss-jsf-api_2.1_spec</artifactId> <scope>provided</scope> </dependency>Adrian Mitev

2 Answers

3
votes

Maybe they use different API jars because of some distribution / licensing issues. I dont know exactly. But the API is the same, your FacesContextFactory can be found in the myfaces-api jar as well.

I would try to create profiles (or even two separate modules) that define the according set of dependencies. Using profiles you would need to activate one of them manually to switch the dependencies. With modules both would be built but the question where to put your sources will arise but the dependencies can be set to compile so it will be easier to create a deliverable.

It may be worth looking at Gradle here - I always had issues with projects that need to adopt different sets of dependencies and I've seen some nice features there.

Sorry I have no good solution found yet for this setup either.

edit: while thinking: you may just create two branches in your SCM and merge changes between them? (beside the dependencies of course)

2
votes

Why do Mojarra and MyFaces use different API jars? Both implement the same API (JSF), so shouldn't they use the same API jars?

They are seperate implementations of JSF. JSF is a Specification. See this Question.

More concretely: What is the right Maven dependency for a library that should only depend on the JSF API? Right now, we depend on jsf-api, and projects that use MyFaces must use to throw out jsf-api and include myfaces-api. That works, but surely there is a better way?

What you are terming "The JSF API" is the Sun/Oracle implementation of it (Mojarra). The dependencies for these are:

<dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.1.2</version>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.1.2</version>
        </dependency>