5

I have a custom converter to select a Country in a SelectOneMenu component:

File: address.jar

@FacesConverter(value="CountryConverter", forClass=Country.class)
public class CountryConverter implements Converter {

private CountryBean countryBean = CountryBean.getCountryService();

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
    return countryBean.find(value);
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    if (value != null)
        return ((Country)value).getcc_fips();
    else
        return null;
}    

And this is the xhtml text:

File: Project root

  <h:selectOneMenu id="country" value="#{cc.attrs.addrEntity.country}">
     <f:selectItem itemLabel="Please select one..." 
             noSelectionOption="true" />
     <f:selectItems value="#{cc.attrs.addrBean.countries}"
                    var="model"
                    itemLabel="#{model.name}"
                    itemValue="#{model}"
                    noSelectionValue="&#8220;no selection&#8221;"/>
     <f:converter ConverterId="CountryConverter"/>        
 </h:selectOneMenu>

I have the converter in a file "address.jar" and when I try to open the page to write the address, then it responds saying "Expression Error: Object with name MyCustomCoverter not found.". Even thought when I copy the converter to the project where the xhtml files are, then it works ok. What can I do to solve this?

Why it doesn't work from a separated jar file?

Thanks.

Joe Almore
  • 4,036
  • 9
  • 52
  • 77

1 Answers1

17

You have to supply a JSF 2.0 compatible /META-INF/faces-config.xml file in the JAR file in order to get JSF to auto-scan the JAR file for classes with JSF annotations.

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

Without that file, JSF won't auto-scan the JAR file to save performance and thus your @FacesConverter won't be found nor registered.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    One additional but important detail is, that the JAR must be in the **lib-directory** of the WAR (web-application). If you have an EAR with a WAR in it and the JAR with the converter is only in the EAR but not in the WAR's lib, JSF won't find the converter. See also [this answer](http://stackoverflow.com/questions/2987266/why-doesnt-jsf-2-0-ri-mojarra-scan-my-class-annotations) for another detailed description of the problem. – Martin Höller Nov 04 '13 at 14:40
  • @Martin: EAR/lib is never intented for WAR-specific libraries. Not by the Java EE spec nor the Java EE tutorial. Anyone who puts WAR-specific libraries anyway in EAR is just doing it plain wrong. This is unrelated to whether the WAR-specific libraries contain JSF-specific artifacts or not. – BalusC Nov 04 '13 at 14:46
  • 2
    @BalusC: consider skinny WARs. What if I have an EAR with two WARs that both need the same converters. Would I have to provide the JAR with the converter-classes to both WARs? Shouldn't their be a way to provide the converters to the WARs through one JAR shared via the EAR? – Martin Höller Nov 04 '13 at 15:40
  • @Martin: Just give each WAR its own JAR. WARs shouldn't have any dependency on EAR. Or, register JAR in Java EE container itself as WAR-shared module. – BalusC Nov 04 '13 at 15:42
  • Giving each WAR its own JAR would work but is a very resource wasting approach. The idea of "WAR-shared module" sounds good. Could you provide some link/info? Should I better start a new question? – Martin Höller Nov 04 '13 at 15:56
  • @Martin: Resource wasting? This isn't 1990 anymore. And these days we have Maven which makes it less gruesome (no need to manually copypaste JARs nor to align/manage the versions). As to WAR-shared module, approach depends on Java EE container being used. Just refer its documentation/admin manual. – BalusC Nov 04 '13 at 16:03
  • I guess we are moving towards a question [I just asked the other day](http://stackoverflow.com/questions/19542214/how-to-put-jsf-provided-by-jboss-as7-on-the-classpath-of-a-jar-module) which was not yet answered. Maybe you could have a look :) – Martin Höller Nov 04 '13 at 16:26
  • @Martin: I can't answer that from top of head (simply because I've never done that before specifically on JBoss 7) and I usually only answer questions from top of head because I don't have that much spare time to research/experiment solutions (I really don't like halfbaked/shoot-in-the-dark answers). Only when there's a moderate bounty and nobody else has answered it so far, then there's a good chance that I will at some point spend (waste?) time researching and testing the solution so that I could post a valid and reliable answer based on true experience. – BalusC Nov 04 '13 at 16:33
  • @BalusC: Let's stop this here. We are getting off-topic. Thanks anyway for your help. You already provided me some insight on the topic. – Martin Höller Nov 04 '13 at 16:38
  • Adding to this answer: if you're using CDI in the JAR, you can also put in META-INF your beans.xml to load your beans also, had to do the same and thanks for all the answers helped me a lot!! – Simego Jul 23 '14 at 19:05