Estoy escribiendo un servicio web en Java y estoy tratando de encontrar la mejor manera de definir códigos de error y sus cadenas de error asociadas . Necesito tener un código de error numérico y una cadena de error agrupados. Tanto el código de error como la cadena de error se enviarán al cliente que accede al servicio web. Por ejemplo, cuando ocurre una SQLException, es posible que desee hacer lo siguiente:
// Example: errorCode = 1,
// errorString = "There was a problem accessing the database."
throw new SomeWebServiceException(errorCode, errorString);
El programa cliente puede mostrar el mensaje:
"Se ha producido el error nº 1: se ha producido un problema al acceder a la base de datos".
Mi primer pensamiento fue utilizar uno Enum
de los códigos de error y anular los toString
métodos para devolver las cadenas de error. Esto es lo que se me ocurrió:
public enum Errors {
DATABASE {
@Override
public String toString() {
return "A database error has occured.";
}
},
DUPLICATE_USER {
@Override
public String toString() {
return "This user already exists.";
}
},
// more errors follow
}
Mi pregunta es: ¿Existe una mejor manera de hacer esto? Preferiría una solución en código, en lugar de leer desde un archivo externo. Estoy usando Javadoc para este proyecto, y sería útil poder documentar los códigos de error en línea y hacer que se actualicen automáticamente en la documentación.
Respuestas:
Bueno, ciertamente hay una mejor implementación de la solución de enumeración (que generalmente es bastante buena):
Es posible que desee anular toString () para devolver la descripción en su lugar, no estoy seguro. De todos modos, el punto principal es que no necesita anular por separado para cada código de error. También tenga en cuenta que he especificado explícitamente el código en lugar de usar el valor ordinal; esto hace que sea más fácil cambiar el orden y agregar / eliminar errores más adelante.
No olvide que esto no está internacionalizado en absoluto, pero a menos que su cliente de servicio web le envíe una descripción de la configuración regional, no podrá internacionalizarlo fácilmente usted mismo de todos modos. Al menos tendrán el código de error para usar para i18n en el lado del cliente ...
fuente
En lo que a mí respecta, prefiero externalizar los mensajes de error en archivos de propiedades. Esto será realmente útil en caso de internacionalización de su aplicación (un archivo de propiedades por idioma). También es más fácil modificar un mensaje de error y no será necesario volver a compilar las fuentes de Java.
En mis proyectos, generalmente tengo una interfaz que contiene códigos de error (String o entero, no le importa mucho), que contiene la clave en los archivos de propiedades para este error:
en el archivo de propiedades:
Otro problema con su solución es la capacidad de mantenimiento: solo tiene 2 errores y ya 12 líneas de código. ¡Así que imagine su archivo de enumeración cuando tenga que gestionar cientos de errores!
fuente
La sobrecarga de toString () parece un poco asquerosa, parece un poco exagerada del uso normal de toString ().
Qué pasa:
me parece mucho más limpio ... y menos detallado.
fuente
En mi último trabajo, profundicé un poco más en la versión de enumeración:
@Error, @Info, @Warning se conservan en el archivo de clase y están disponibles en tiempo de ejecución. (Tuvimos un par de otras anotaciones para ayudar a describir la entrega de mensajes también)
@Text es una anotación en tiempo de compilación.
Escribí un procesador de anotaciones para esto que hizo lo siguiente:
Escribí algunas rutinas de utilidad que ayudaron a registrar errores, envolverlos como excepciones (si lo desea) y así sucesivamente.
Estoy tratando de que me dejen abrir el código ... - Scott
fuente
Te recomiendo que eches un vistazo a java.util.ResourceBundle. Debería preocuparse por I18N, pero vale la pena incluso si no lo hace. Exteriorizar los mensajes es una muy buena idea. Descubrí que era útil poder entregar una hoja de cálculo a los empresarios que les permitiera escribir el idioma exacto que querían ver. Escribimos una tarea Ant para generar los archivos .properties en tiempo de compilación. Hace que I18N sea trivial.
Si también usa Spring, mucho mejor. Su clase MessageSource es útil para este tipo de cosas.
fuente
Solo para seguir azotando a este caballo muerto en particular, hemos hecho un buen uso de los códigos de error numéricos cuando se muestran errores a los clientes finales, ya que con frecuencia olvidan o leen mal el mensaje de error real, pero a veces pueden retener e informar un valor numérico que puede dar usted una pista de lo que realmente sucedió.
fuente
Hay muchas formas de solucionar este problema. Mi enfoque preferido es tener interfaces:
Ahora puede definir cualquier número de enumeraciones que proporcionen mensajes:
Ahora tienes varias opciones para convertirlas en cadenas. Puede compilar las cadenas en su código (usando anotaciones o parámetros del constructor de enumeración) o puede leerlas desde un archivo de configuración / propiedad o desde una tabla de base de datos o una mezcla. Este último es mi enfoque preferido porque siempre necesitará algunos mensajes que pueda convertir en texto muy pronto (es decir, mientras se conecta a la base de datos o lee la configuración).
Estoy usando pruebas unitarias y marcos de reflexión para encontrar todos los tipos que implementan mis interfaces para asegurarme de que cada código se use en algún lugar y que los archivos de configuración contengan todos los mensajes esperados, etc.
Al usar marcos que pueden analizar Java como https://github.com/javaparser/javaparser o el de Eclipse , incluso puede verificar dónde se usan las enumeraciones y encontrar las que no se usan.
fuente
Yo (y el resto de nuestro equipo en mi empresa) preferimos generar excepciones en lugar de devolver códigos de error. Los códigos de error deben verificarse en todas partes, pasarse y tienden a hacer que el código sea ilegible cuando la cantidad de código aumenta.
La clase de error luego definiría el mensaje.
PD: ¡y también nos preocupamos por la internacionalización!
PPS: también puede redefinir el método de aumento y agregar registro, filtrado, etc. si es necesario (al menos en entornos, donde las clases de excepción y los amigos son extensibles / cambiables)
fuente
Un poco tarde, pero solo estaba buscando una solución bonita para mí. Si tiene un tipo diferente de error de mensaje, puede agregar una fábrica de mensajes simple y personalizada para poder especificar más detalles y el formato que le gustaría más adelante.
EDITAR: ok, usar enum aquí es un poco peligroso ya que altera una enumeración particular permanentemente. Supongo que lo mejor sería cambiar a clase y usar campos estáticos, pero ya no puede usar '=='. Así que supongo que es un buen ejemplo de lo que no se debe hacer (o hacerlo solo durante la inicialización) :)
fuente
enum para la definición de código / mensaje de error sigue siendo una buena solución, aunque tiene problemas de i18n. En realidad, podemos tener dos situaciones: el código / mensaje se muestra al usuario final o al integrador del sistema. Para el último caso, I18N no es necesario. Creo que los servicios web son probablemente el último caso.
fuente
Usar
interface
como constante de mensaje es generalmente una mala idea. Se filtrará en el programa del cliente de forma permanente como parte de la API exportada. Quién sabe, los programadores de clientes posteriores podrían analizar esos mensajes de error (públicos) como parte de su programa.Estará bloqueado para siempre para admitir esto, ya que los cambios en el formato de cadena pueden romper el programa cliente.
fuente
Siga el siguiente ejemplo:
};
En su código, llámelo como:
fuente
Utilizo PropertyResourceBundle para definir los códigos de error en una aplicación empresarial para administrar los recursos de códigos de error locales. Esta es la mejor manera de manejar códigos de error en lugar de escribir código (puede ser válido para algunos códigos de error) cuando el número de códigos de error es enorme y estructurado.
Consulte java doc para obtener más información sobre PropertyResourceBundle
fuente