Resultado Struts2 INPUT: ¿cómo funciona? ¿Cómo se manejan los errores de conversión / validación?

Pregunta principal

El flujo de trabajo debería ser así: si se ingresa una Cadena que no sea un número, primero debe pasar a través de un interceptor de excepción, y al pasar a través del interceptor param, mientras se convierte a tipo int, no podrá hacerlo utilizando Integer.parseInt y se produciría una excepción; ¿no debería esa excepción (que es NumberFormatException ) ser empujada a Value Stack? ¿Por qué no muestra NumberFormatException y muestra el resultado aunque el resultado no se debe imprimir en su lugar?

Pregunta lateral

Cada vez que agrego un alfabeto en el formulario, cambia a cero …? Porque ?

index.jsp

       

divide.java

 package actions; public class divide { int number1,number2,result; public String execute() throws Exception { result=number1/number2; return "success"; } public int getNumber1() { return number1; } public void setNumber1(int number1) { this.number1 = number1; } public int getNumber2() { return number2; } public void setNumber2(int number2) { this.number2 = number2; } public int getResult() { return result; } } 

result.jsp

   the result of division is    

manejador jsp

   following exception occured during the processing    

struts.xml

       /result.jsp /handler.jsp    

Pregunta principal:

El flujo de trabajo debería ser así, si se ingresa una cadena que no sea un número, primero debe pasar a través de un interceptor de excepción, y al pasar a través del interceptor param, mientras se convierte a tipo int, no podrá hacerlo utilizando Integer. parseInt y se produciría una excepción, esa excepción que es la excepción de formato numérico debe ser empujada a la stack de valores, entonces, ¿por qué no muestra numberformatexception y muestra el resultado aunque el resultado no se debe imprimir en su lugar?

Concepto

Struts 2 maneja los errores de conversión y de validación automáticamente: no genera una excepción, porque no están bloqueando errores , sino errores de entrada , por lo tanto, la mejor manera de proceder es notificar al usuario que la entrada enviada fue incorrecta, preguntándole para una entrada nueva y válida. Para lograr esto, se devuelve un resultado INPUT, mientras que la excepción se ignora.

Flujo de trabajo detallado

  1. El Parameters Interceptor intenta establecer los parámetros. Si se NumberFormatException una RuntimeException (como NumberFormatException ) y devMode es true , se agrega un mensaje de error a los Action Errors ; de lo contrario, la excepción es simplemente ingerida. Desde el código fuente:

     for (Map.Entry entry : acceptableParameters.entrySet()) { String name = entry.getKey(); Object value = entry.getValue(); try { newStack.setParameter(name, value); } catch (RuntimeException e) { if (devMode) { String developerNotification = LocalizedTextUtil.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{ "Unexpected Exception caught setting '" + name + "' on '" + action.getClass() + ": " + e.getMessage() }); LOG.error(developerNotification); if (action instanceof ValidationAware) { ((ValidationAware) action).addActionMessage(developerNotification); } } } } 
  2. El Conversion Errors Interceptor comprueba si se produjo algún error de conversión: por cada uno encontrado, agrega un Field Error ; también guarda los valores originales de modo que cualquier solicitud posterior para ese valor devuelva el valor original en lugar del valor de la acción . De la documentación:

    Este interceptor agrega cualquier error encontrado en el mapa conversionErrors de ActionContext como un error de campo (siempre que la acción implemente ValidationAware). Además, cualquier campo que contenga un error de validación tiene su valor original guardado de modo que cualquier solicitud posterior para ese valor devuelva el valor original en lugar del valor de la acción. Esto es importante porque si el valor “abc” se envía y no se puede convertir a un int, queremos mostrar la cadena original (“abc”) de nuevo en lugar del valor int (probablemente 0, lo que tendría muy poco sentido para el usuario).

  3. El Validation Interceptor realiza toda la validación solicitada (definida en XML, Anotaciones o validate() o validateXXX() métodos de la Acción), agregando uno o más mensajes de error a los Field Errors para cada campo que no pasa uno o más criterios de validación .

  4. El Workflow Interceptor comprueba si hay Field Errors (ambos provenientes de errores de conversión o de validación). Si no se encuentran errores, continúa la cadena al siguiente Interceptor. Si se encuentran uno o más errores, devuelve un resultado de ENTRADA.

Para garantizar que este mecanismo funcione, debe definir estos cuatro Interceptores en el orden correcto en su Pila personalizada, si no está utilizando la Pila de interceptores predeterminada (de lo contrario, no necesita hacer nada). Desde struts-default.xml :

   ^dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,^parameters\..*,^action:.*,^method:.*    input,back,cancel,browse   input,back,cancel,browse   

Pregunta lateral:

Cada vez que agrego un alfabeto en el formulario, cambia a cero …? ¿Porque?

La respuesta original fue: el marco no ha podido establecer un String en un campo int al publicar la solicitud en el servidor, y al recuperar el valor en la página resultante, invoca el Getter de esa variable; ya que definió un int y no un Integer , y un int no puede ser nulo, devolverá el valor predeterminado para int : 0 .

Pero no estaba recordando que el interceptor de conversión afirma (leer el punto n. ° 2) guardar los valores originales, para proporcionarlos en futuras solicitudes posteriores, en lugar de los valores de Acción (que serían nulos o 0). Esto también se menciona en el Manejo de errores de conversión de tipos :

El manejo de errores de conversión de tipo proporciona una manera simple de distinguir entre un problema de validación de entrada y un problema de conversión de tipo de entrada.

Cualquier error que ocurra durante la conversión de tipo puede o no desearse que se informe. Por ejemplo, informar que la entrada “abc” no se pudo convertir a un número podría ser importante. Por otro lado, informar que una cadena vacía, “”, no se puede convertir a un número podría no ser importante, especialmente en un entorno web donde es difícil distinguir entre un usuario que no ingresa un valor y un valor en blanco.

En cambio, estaba recordando bien el comportamiento descrito en tu pregunta. Entonces este caso ya se ha manejado … ¿por qué no está funcionando entonces? El culpable, en mi caso (y probablemente tu), era el atributo de value :

Esto le dará 0 al publicar abc :

  

porque ocurre un error de conversión adicional.

En su lugar, estos dos casos funcionan como se describe anteriormente, lo que le da abc al publicar abc :

   

Conclusiones

  • Asegúrese de que la stack del interceptor esté configurada correctamente, y
  • verifique cuidadosamente su código (que probablemente no sea el que se publicó aquí) para ver qué está haciendo con su atributo de value .

Para fines de prueba, trate de eliminar el atributo de value al principio, para ver que funciona correctamente, y luego comience a buscar el error.