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.