Seguem códigos das três partes envolvidas: página, MBean e classe de domínio.
Página
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="https://ajax4jsf.dev.java.net/ajax">
<ui:composition template="template-posgrad.xhtml">
<ui:define name="titulo">Cadastro de Turma - Horários</ui:define>
<ui:define name="links">
<script type="text/javascript" src="/posgrad/script/mascaras.js"></script>
</ui:define>
<ui:define name="conteudo">
<h:panelGroup rendered="#{!empty turma.turma.horarios}">
<p>
<h:dataTable value="#{turma.horariosDataModel}" var="horario">
<h:column>
<f:facet name="header">
<h:outputText value="Dia"/>
</f:facet>
<h:outputText value="#{horario.diaSemana}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Início"/>
</f:facet>
<h:outputText value="#{horario.horaInicio}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Término"/>
</f:facet>
<h:outputText value="#{horario.horaTermino}"/>
</h:column>
<h:column>
<h:commandLink value="Alterar" action="#{turma.editarHorario}" immediate="true"/>
</h:column>
<h:column>
<h:commandLink value="Excluir" action="#{turma.excluirHorario}" immediate="true"/>
<h:panelGroup rendered="#{turma.excluindoHorario}">
<label>Confirma?</label>
<h:commandButton value="Sim" action="#{turma.confirmarExclusaoHorario}" immediate="true"/>
<h:commandButton value="Não" action="#{turma.cancelarExclusaoHorario}" immediate="true"/>
</h:panelGroup>
</h:column>
</h:dataTable>
</p>
</h:panelGroup>
<p>
<a jsfc="h:commandLink" value="Novo Horário" action="#{turma.incluirHorario}"/>
</p>
<p>
<a jsfc="h:commandLink" value="Retornar à tela anterior" action="cadastrarTurma" immediate="true"/>
</p>
<h:panelGroup rendered="#{!empty turma.horarioDaVez}">
<fieldset>
<p>
<label jsfc="h:outputLabel" for="diaSemana">Dia da semana</label>
<select jsfc="h:selectOneMenu" id="diaSemana" value="#{turma.diaSemana}">
<option jsfc="f:selectItems" value="#{pato.diasSemanaItem}"/>
</select>
</p>
<p>
<label jsfc="h:outputLabel" for="horaInicio">Hora início</label>
<input jsfc="h:inputText" type="text" id="horaInicio" maxlength="5"
size="5" value="#{turma.horarioDaVez.horaInicio}"
required="true" requiredMessage="A hora de início é obrigatória"
onkeypress="mascaraHora(this, event)"/>
</p>
<p>
<label jsfc="h:outputLabel" for="horaTermino">Hora término</label>
<input jsfc="h:inputText" type="text" id="horaTermino" maxlength="5"
size="5" value="#{turma.horarioDaVez.horaTermino}"
required="true" requiredMessage="A hora de término é obrigatória"
onkeypress="mascaraHora(this, event)"/>
</p>
<p>
<a jsfc="h:commandLink" value="Registrar" action="#{turma.salvarHorario}"/>
</p>
</fieldset>
</h:panelGroup>
</ui:define>
</ui:composition>
</html>
O último link da página chama o método salvarHorario do MBean, transcrito abaixo:
@SuppressWarnings("unchecked")
public String salvarHorario()
{
List<Horario> lista = (List) horariosDataModel.getWrappedData();
if (horarioDaVez.getId() == null) // incluindo
{
lista.add(horarioDaVez);
turma.adicionaHorario(horarioDaVez);
}
horarioDaVez.setDiaSemana(diaSemana);
Map<Horario, Horario> concidencias = turma.verificaCoincidencias();
// TODO quando o problema do retorno for resolvido, remover o teste por nulo
if (coincidencias != null && coincidencias.size() > 0)
{
Horario horarioCoincidente = null;
if (coincidencias.containsKey(horarioDaVez))
horarioCoincidente = coincidencias.get(horarioDaVez);
else
{
for (Horario horario: coincidencias.keySet())
if (coincidencias.get(horario).equals(horarioDaVez))
{
horarioCoincidente = horario;
break;
}
}
JSFUtils.mostrarMensagem(
new StringBuilder()
.append("Este hor\u00E1rio \u00E9 coincidente com o hor\u00E1rio de ")
.append(horarioCoincidente.getHoraInicio())
.append(" \u00E0s ")
.append(horarioCoincidente.getHoraTermino())
.append(" n")
.append(horarioCoincidente.getDiaSemana().getArtigo())
.append(" ")
.append(horarioCoincidente.getDiaSemana())
.append(".")
.toString());
return "paginaTurmaHorario";
}
Collections.sort(lista, Horario.getHorarioComparator());
horariosDataModel.setWrappedData(lista);
horarioDaVez = null;
return "paginaTurmaHorario";
}
Abaixo, o código do método verificarCoincidencias() na classe Turma
public Map<Horario, Horario> verificaCoincidencias()
{
Map<Horario, Horario> coincidencias = new HashMap<Horario, Horario>();
// se a disciplina nao exige verificacao de horario, retorna mapa vazio
if (this.getDisciplina() != null && this.getDisciplina().getNaoVerificaCoincidencia())
return coincidencias;
List<Horario> horarios = new ArrayList<Horario>(this.getHorarios());
for (int i = 0; i < horarios.size() - 1; i++)
{
Horario horario = horarios.get(i);
for (int j = i+1; j < horarios.size(); j++)
{
Horario horario2 = horarios.get(j);
if (!horario.getDiaSemana().equals(horario2.getDiaSemana()))
continue;
boolean horaInicio1MenorQueHoraInicio2 = horario.getHoraInicio().compareTo(horario2.getHoraInicio()) < 0;
boolean horaTermino1MenorOuIgualAHoraInicio2 = horario.getHoraTermino().compareTo(horario2.getHoraInicio()) <= 0;
boolean horaInicio1MaiorOuIgualAHoraTermino2 = horario.getHoraInicio().compareTo(horario2.getHoraTermino()) >= 0;
boolean horaTermino1MaiorQueHoraTermino2 = horario.getHoraTermino().compareTo(horario2.getHoraTermino()) > 0;
if (!
((horaInicio1MenorQueHoraInicio2 && horaTermino1MenorOuIgualAHoraInicio2)
||
(horaInicio1MaiorOuIgualAHoraTermino2 && horaTermino1MaiorQueHoraTermino2)))
{
coincidencias.put(horario, horario2);
}
}
}
return coincidencias;
}
O método funciona perfeitamente nos testes de unidade. Porém, quando roda no servidor (Glassfish), retorna sempre null. Durante a depuração, o conteúdo do mapa se mostra um objeto válido até o retorno do método. No MBean, porém, o retorno é sempre nulo.
Agradeço qualquer ajuda.