Olá desenvolvedores, continuando com a parte 7 da implementação de “combos dependentes”, neste tutorial iremos proceder com a correção de alguns bugs. O que aliás, é normal acontecer no desenvolvimento de qualquer aplicação.
ERRO DE NULLPOINTEREXCEPTION
E neste tutorial irei ensiná-los a corrigir estes bugs. O primeiro bug ocorre tão logo o login é feito, um erro de “NullPointerException” é apontando para o método getAsString(), na classe EstadosConverter. Significa que o objeto que está sendo passado, está como nulo. O código correspondente ao erro é o mostrado abaixo:
return ((Estados) estado).getId().toString;
Este erro pode ser corrigido com a implementação de algumas verificações em uma estrutura de decisão. Dessa forma, se o objeto for igual a “null”, só precisaremos retornar “null”, impedindo assim que o fluxo de processamento prossiga e ocorra uma exceção.
Outra verificação que precisará ser feita é verificar se o objeto “estado” é uma instância de “Estados”, e isso porque pode tanto pode vir uma instância do objeto Estado como apenas uma String que representa o código da chave primária na base de dados. Assim, se o dado vir como objeto faremos a conversão de casting para obter o “id” e retornar uma String.
Mas se não, se o dado já for obtido em formato de String, então só será preciso retorná-lo.
O mesmo erro será exibido para o método getAsString(), da classe CidadesConverter, proceda do mesmo modo para implementar a correção. Para orientá-lo com a correção, as mesmas verificações deverão ser implementadas, substituindo onde é “estado por cidade”, e onde é “Estados por Cidades”.
ADENDOS AO CÓDIGO
Em “off” realizei algumas melhorias no código. Na anotação que precede a assinatura das classes EstadoConverter e CidadeConverter inseri um value. Este valor funcionará como uma referência a estas classes na tela JSF – JavaServer Faces, respectivamente. O valor atribuído será declarado por meio da propriedade “converter” no h:selectOneMenu que faz referência a classe.
@FacesConverter(forClasses = Estados.class, value = “estadoConverter”
@FacesConverter(forClasses = Estados.class, value = "cidadeConverter"
ADEQUANDO AO CONVERTER
O código que implementamos ainda não está compatível com o funcionamento do “comboBox”. Veja abaixo a imagem dos erros que ocorrem quando selecionamos uma “cidade” e clicamos em Salvar.
Os Erros são referentes aos combos “Estado” e Cidade”, porém observe que onde deveria estar escrito “comboEstado”, um código é exibido. Assim, o primeiro ajuste necessário é atribuir um “id” ao “comboBox” referente ao Estado.
Na primeiarpagina.xhtml, no componente h:selectOneMenu que implementa o combo dos Estados insira uma propriedade “id”. Observe que suprimimos as demais propriedades da “tag” por considerar que você já as tem implementadas. Porém, note o “converter” mencionado na sessão anterior. Da mesma forma você deverá adicionar a prioridade “converter” ao h:selectOneMenu do combo das Cidades.
< h:selectOneMenu converter= “converterEstado” id= “comboEstados” >
Feito isso podemos seguir com a correção dos erros que nos impede de gravar a “cidade” selecionada no banco de dados.
Entenda, quando clicamos em Salvar para submeter o formulário, o código que está no converter, neste caso, o Estado ou a cidade selecionada, será convertido em um objeto até chegar a classe e ser adicionado a base de dados. É justamente neste processo que o nosso código apresenta incompatibilidades que precisarão ser ajustadas.
1º AJUSTE
O primeiro ajuste é deletar o método toString() nas classes Cidades e Estados, porque agora iremos gerar o hashCode() and equals() para o id das duas classes. Assim, clique com o botão direito em uma área livre das respectivas classes >> Source >> Generate hashCode() and equals(), selecione apenas o “id”. Porque é pelo “id” que diferenciaremos os objetos.
2º AJUSTE
O segundo ajuste será no IDaoPessoaImpl. Onde a lista de Estados é carregada é preciso passar o “objeto inteiro” e não apenas o “id”. E para isso no método listaEstados(), dentro do laço de repetição que percorre a lista, só é preciso retirar o “.getId()” para que possamos enviar o “objeto inteiro”.
Da mesma forma deveremos proceder no método onde as cidades são carregadas no PessoaBean.
OBTENDO O OBJETO INTEIRO
Da forma como estava implementado anteriormente, para carregarmos a lista de cidades a partir do Estado selecionado, precisávamos apenas do “id”. Mas com as mudanças implementadas, e principalmente porque agora estamos passando não apenas o “id” mas o “objeto inteiro”, teremos que modificar o código para obter o “objeto inteiro”.
Assim, iremos substituir o código que recuperava o “id” para que possamos implementar um novo jeito de obter o “objeto inteiro”. Iremos chamar o objeto “event” do JSF e então por meio do “getSource” obter o objeto no qual o evento ocorreu inicialmente. E por fora obteremos o valor do componente JSF.
E assim não precisaremos mais verificar se o codigoEstado é diferente de “null” e realizar a consulta ao banco de dados, isto é, podemos apagar esta parte da implementação.
IMPORTANTE: não delete a verificação onde temos implementada a List<cidades> trazendo do banco as cidades de acordo com o código do Estado selecionado. Aliás, nesta parte do código, no createQuery, a consulta ao banco será feita a partir do “id” do Estado.
EM POUCAS PALAVRAS
Esta talvez seja o tipo de implementação mais complexa do JSF – JavaServer Faces mas é necessário que utilizemos o converter, o motivo de todos os ajustes que foram necessários. No entanto, agora temos o código funcionando redondo.