Converter instances are under the covers created via Application#createConverter()
.
Converter converter = facesContext.getApplication().createConverter(idOrClass);
Like as many abstract artifacts in JSF API, the Application
follows the decorator (wrapper) pattern, like as you can find over all place in java.io.*
. You can provide a custom one via a <factory>
in faces-config.xml
as OmniFaces did below in its /META-INF/faces-config.xml
:
<factory>
<application-factory>org.omnifaces.application.OmniApplicationFactory</application-factory>
</factory>
The application factory implementation boils down to this:
public class OmniApplicationFactory extends ApplicationFactory {
private final ApplicationFactory wrapped;
public OmniApplicationFactory(ApplicationFactory wrapped) {
this.wrapped = wrapped;
}
@Override
public Application getApplication() {
return new OmniApplication(wrapped.getApplication());
}
@Override
public void setApplication(Application application) {
wrapped.setApplication(application);
}
@Override
public ApplicationFactory getWrapped() {
return wrapped;
}
}
(The actual implementation is a little bit more convoluted to work around broken application factories coming from older versions of 3rd party libraries such as Seam, Weld and Spring WebFlow (which are already for long fixed on their side by the way)).
The OmniApplication
implementation boils down to this:
public class OmniApplication extends ApplicationWrapper {
private final Application wrapped;
private final ConverterManager converterManager;
public OmniApplication(Application wrapped) {
this.wrapped = wrapped;
converterManager = BeanManager.INSTANCE.getReference(ConverterManager.class);
}
@Override
public Converter createConverter(String converterId) {
Converter converter = converterManager.createConverter(getWrapped(), converterId);
return (converter != null) ? converter : super.createConverter(converterId);
}
@Override
public Application getWrapped() {
return wrapped;
}
}
You see, there the delegation to ConverterManager
is happening.