Estou escrevendo um serviço da web em Java e estou tentando descobrir a melhor maneira de definir códigos de erro e suas sequências de erro associadas . Preciso ter um código de erro numérico e uma string de erro agrupados. Tanto o código de erro quanto a string de erro serão enviados ao cliente que acessa o serviço da web. Por exemplo, quando ocorre uma SQLException, posso querer fazer o seguinte:
// Example: errorCode = 1,
// errorString = "There was a problem accessing the database."
throw new SomeWebServiceException(errorCode, errorString);
O programa cliente pode ver a mensagem:
"Ocorreu o erro nº 1: houve um problema ao acessar o banco de dados."
Meu primeiro pensamento foi usar um Enum
dos códigos de erro e substituir os toString
métodos para retornar as strings de erro. Aqui está o que eu descobri:
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
}
Minha pergunta é: existe uma maneira melhor de fazer isso? Eu preferiria uma solução em código, em vez de ler de um arquivo externo. Estou usando Javadoc para este projeto e seria útil documentar os códigos de erro in-line e atualizá-los automaticamente na documentação.
Respostas:
Bem, certamente há uma implementação melhor da solução enum (que geralmente é muito boa):
Você pode querer substituir toString () para retornar apenas a descrição - não tenho certeza. De qualquer forma, o ponto principal é que você não precisa substituir separadamente para cada código de erro. Observe também que especifiquei explicitamente o código em vez de usar o valor ordinal - isso torna mais fácil alterar a ordem e adicionar / remover erros posteriormente.
Não se esqueça de que isso não é internacionalizado de forma alguma - mas, a menos que seu cliente de serviço da web envie uma descrição de localidade, você não pode internacionalizá-la facilmente. Pelo menos eles terão o código de erro para usar para i18n no lado do cliente ...
fonte
No que me diz respeito, prefiro externalizar as mensagens de erro em arquivos de propriedades. Isso será muito útil no caso de internacionalização de sua aplicação (um arquivo de propriedades por idioma). Também é mais fácil modificar uma mensagem de erro e não precisa de nenhuma recompilação das fontes Java.
Em meus projetos, geralmente tenho uma interface que contém códigos de erros (String ou inteiro, não importa muito), que contém a chave nos arquivos de propriedades para este erro:
no arquivo de propriedades:
Outro problema com sua solução é a manutenção: você tem apenas 2 erros e já 12 linhas de código. Então imagine seu arquivo de Enumeração quando você terá centenas de erros para gerenciar!
fonte
Sobrecarregar toString () parece um pouco nojento - parece um pouco forçado do uso normal de toString ().
A respeito:
parece muito mais limpo para mim ... e menos prolixo.
fonte
No meu último trabalho, fui um pouco mais fundo na versão enum:
@Error, @Info, @Warning são retidos no arquivo de classe e estão disponíveis no tempo de execução. (Tínhamos algumas outras anotações para ajudar a descrever a entrega da mensagem também)
@Text é uma anotação em tempo de compilação.
Eu escrevi um processador de anotações para isso que fazia o seguinte:
Eu escrevi algumas rotinas de utilitários que ajudaram a registrar erros, agrupá-los como exceções (se desejado) e assim por diante.
Estou tentando fazer com que eles me deixem abrir o código ... - Scott
fonte
Eu recomendo que você dê uma olhada em java.util.ResourceBundle. Você deve se preocupar com o I18N, mas vale a pena mesmo se não o fizer. Externalizar as mensagens é uma ideia muito boa. Descobri que era útil poder dar uma planilha para o pessoal de negócios que lhes permitisse colocar no idioma exato que eles queriam ver. Escrevemos uma tarefa Ant para gerar os arquivos .properties em tempo de compilação. Isso torna o I18N trivial.
Se você também estiver usando o Spring, melhor ainda. Sua classe MessageSource é útil para esse tipo de coisa.
fonte
Apenas para continuar a açoitar este cavalo morto em particular - fizemos um bom uso de códigos de erro numéricos quando os erros são mostrados aos clientes finais, uma vez que eles freqüentemente esquecem ou interpretam mal a mensagem de erro real, mas às vezes podem reter e relatar um valor numérico que pode fornecer você uma pista do que realmente aconteceu.
fonte
Existem muitas maneiras de resolver isso. Minha abordagem preferida é ter interfaces:
Agora você pode definir qualquer número de enums que fornecem mensagens:
Agora você tem várias opções para transformá-los em Strings. Você pode compilar as strings em seu código (usando anotações ou parâmetros do construtor enum) ou pode lê-las de um arquivo de configuração / propriedade ou de uma tabela de banco de dados ou uma mistura. A última é minha abordagem preferida porque você sempre precisará de algumas mensagens que você pode transformar em texto muito cedo (ou seja, enquanto você se conecta ao banco de dados ou lê a configuração).
Estou usando testes de unidade e estruturas de reflexão para encontrar todos os tipos que implementam minhas interfaces para garantir que cada código seja usado em algum lugar e que os arquivos de configuração contenham todas as mensagens esperadas, etc.
Usando estruturas que podem analisar Java como https://github.com/javaparser/javaparser ou a do Eclipse , você pode até verificar onde as enums são usadas e encontrar as não usadas.
fonte
Eu (e o restante de nossa equipe em minha empresa) preferimos levantar exceções em vez de retornar códigos de erro. Os códigos de erro devem ser verificados em todos os lugares, repassados e tendem a tornar o código ilegível quando a quantidade de código se torna maior.
A classe de erro definiria a mensagem.
PS: e na verdade também prezamos pela internacionalização!
PPS: você também pode redefinir o método de aumento e adicionar registro, filtragem etc., se necessário (pelo menos em ambientes, onde as classes de exceção e amigos são extensíveis / alteráveis)
fonte
Um pouco tarde, mas, eu só estava procurando uma solução bonita para mim. Se você tiver diferentes tipos de mensagem de erro, poderá adicionar uma fábrica de mensagens simples e personalizadas para especificar mais detalhes e o formato que desejar posteriormente.
EDIT: ok, usar enum aqui é um pouco perigoso, pois você altera determinado enum permanentemente. Eu acho que seria melhor mudar para a classe e usar campos estáticos, mas você não pode mais usar '=='. Então eu acho que é um bom exemplo do que não fazer (ou fazer apenas durante a inicialização) :)
fonte
enum para código de erro / definição de mensagem ainda é uma boa solução, embora tenha uma preocupação com i18n. Na verdade, podemos ter duas situações: o código / mensagem é exibido para o usuário final ou para o integrador do sistema. Para o último caso, I18N não é necessário. Acho que os serviços da web são provavelmente o caso posterior.
fonte
Usar
interface
como constante de mensagem geralmente é uma má ideia. Ele vazará para o programa do cliente permanentemente como parte da API exportada. Quem sabe se os programadores de cliente posteriores podem analisar essas mensagens de erro (públicas) como parte de seu programa.Você ficará bloqueado para sempre para suportar isso, pois as alterações no formato da string podem / podem interromper o programa cliente.
fonte
Siga o exemplo abaixo:
};
Em seu código, chame-o assim:
fonte
Eu uso PropertyResourceBundle para definir os códigos de erro em um aplicativo corporativo para gerenciar recursos de código de erro local. Esta é a melhor maneira de lidar com códigos de erro em vez de escrever código (pode ser válida para alguns códigos de erro) quando o número de códigos de erro é enorme e estruturado.
Consulte o documento java para obter mais informações sobre PropertyResourceBundle
fonte