Después de leer el comentario de BalusC, estoy actualizando esta publicación nuevamente.
Creé una pequeña aplicación de demostración y para ver las fases y cuándo ocurren la conversión y la validación.
Vista:
<h:form>
<h:inputText value="#{demoBean.field}">
<f:converter converterId="demoConverter"/>
<f:validator validatorId="demoValidator"/>
</h:inputText>
<h:commandButton value="Submit" action="#{demoBean.demoAxn()}"/>
</h:form>
bean administrado:
@ManagedBean
@SessionScoped
public class DemoBean implements Serializable {
private String field;
public DemoBean() {
System.out.println(Thread.currentThread().getStackTrace()[1]);
}
public String getField() {
System.out.println(Thread.currentThread().getStackTrace()[1]);
return field;
}
public void setField(String field) {
System.out.println(Thread.currentThread().getStackTrace()[1]);
this.field = field;
}
public String demoAxn() {
System.out.println(Thread.currentThread().getStackTrace()[1]);
return null;
}
}
Convertidor:
@FacesConverter(value="demoConverter")
public class DemoConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
System.out.println(Thread.currentThread().getStackTrace()[1]);
return value;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
System.out.println(Thread.currentThread().getStackTrace()[1]);
return (String) value;
}
}
Validador:
@FacesValidator(value="demoValidator")
public class DemoValidator implements Validator {
@Override
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
System.out.println(Thread.currentThread().getStackTrace()[1]);
}
}
Fase oyente:
public class DemoPhaseListener implements PhaseListener {
@Override
public void afterPhase(PhaseEvent event) {
System.out.println(Thread.currentThread().getStackTrace()[1]);
System.out.println("PhaseId: " + event.getPhaseId() + " ===============================\n\n");
}
@Override
public void beforePhase(PhaseEvent event) {
System.out.println("\n\nPhaseId: " + event.getPhaseId() + " ===============================");
System.out.println(Thread.currentThread().getStackTrace()[1]);
}
@Override
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
}
registró el detector de fase:
<lifecycle>
<phase-listener>pkg.DemoPhaseListener</phase-listener>
</lifecycle>
Con esa configuración cuando el "Enviar" se hace clic en el botón, la salida es:
INFO: PhaseId: RESTORE_VIEW 1 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: RESTORE_VIEW 1 ===============================
INFO: PhaseId: APPLY_REQUEST_VALUES 2 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: APPLY_REQUEST_VALUES 2 ===============================
INFO: PhaseId: PROCESS_VALIDATIONS 3 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoConverter.getAsObject(DemoConverter.java:13)
INFO: pkg.DemoValidator.validate(DemoValidator.java:14)
INFO: pkg.DemoBean.getField(DemoBean.java:17)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: PROCESS_VALIDATIONS 3 ===============================
INFO: PhaseId: UPDATE_MODEL_VALUES 4 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoBean.setField(DemoBean.java:22)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: UPDATE_MODEL_VALUES 4 ===============================
INFO: PhaseId: INVOKE_APPLICATION 5 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoBean.demoAxn(DemoBean.java:27)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: INVOKE_APPLICATION 5 ===============================
INFO: PhaseId: RENDER_RESPONSE 6 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoBean.getField(DemoBean.java:17)
INFO: pkg.DemoConverter.getAsString(DemoConverter.java:20)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: RENDER_RESPONSE 6 ===============================
Pero cuando el cambio de marca para lanzar un NPE en el convertidor de la siguiente manera:
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
System.out.println(Thread.currentThread().getStackTrace()[1]);
throw new NullPointerException();
}
la salida es:
INFO: PhaseId: RESTORE_VIEW 1 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: RESTORE_VIEW 1 ===============================
INFO: PhaseId: APPLY_REQUEST_VALUES 2 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: APPLY_REQUEST_VALUES 2 ===============================
INFO: PhaseId: PROCESS_VALIDATIONS 3 ===============================
INFO: pkg.DemoPhaseListener.beforePhase(DemoPhaseListener.java:17)
INFO: pkg.DemoConverter.getAsObject(DemoConverter.java:13)
INFO: pkg.DemoPhaseListener.afterPhase(DemoPhaseListener.java:10)
INFO: PhaseId: PROCESS_VALIDATIONS 3 ===============================
INFO: pkg.DemoBean.getField(DemoBean.java:17)
Pero el StackTrace se visualiza en la vista resultante.
Gracias @BalusC. A pesar de venir mucho más tarde y básicamente resumir la larga conversación adjunta a la respuesta de βнɛƨн Ǥʋяʋиɢ (que yo había aceptado), preferiría que la respuesta más útil fuera la que se marcó como aceptada para el beneficio de otros que se encuentran con esta pregunta. Lo siento βнɛƨн Ǥʋяʋиɢ :( –
De nada, tenga en cuenta que actualicé la respuesta después de haber examinado de cerca la implementación de su validador, lo que también es esencialmente incorrecto. – BalusC
@BalusC: Gracias por corregirme. Dado que, totalmente engañoso, estoy editando mi respuesta. –