Valor inválido com SelectOneMenu

Boa tarde galera.

Estou trabalhando com CDI, JSF, PrimeFaces, Hibernate e PostGRE. Tenho um selectonemenu dinâmico (programaPosGraduacao), que é preenchido a partir do valor de um selectonebutton (modalidadeCurso). Porém, quando eu escolho uma opção desse selectonemenu e aperto em “salvar”, ele não passa na validação. Li que poderia ser algo relacionado ao Converter ou ao método Equals, mas depois de muito pesquisar não consegui achar a solução ideal. Por favor, me ajudem ! :slight_smile:

NovaLinhaDePesquisa.xhtml

<!DOCTYPE html>
<ui:composition template="/WEB-INF/template/LayoutAluno.xhtml"
	xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://xmlns.jcp.org/jsf/core"
	xmlns:h="http://xmlns.jcp.org/jsf/html"
	xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
	xmlns:p="http://primefaces.org/ui"
	xmlns:o="http://omnifaces.org/ui">
	
	<f:metadata>
		<o:viewParam name="id" value="#{cadastroLinhaPesquisaBean.linhaPesquisa}"/>
		<f:viewAction action="#{cadastroLinhaPesquisaBean.processar}"></f:viewAction>
	</f:metadata>
	
	<ui:define name="titulo">Nova Linha de Pesquisa - Fichas Catalográficas</ui:define>
	
	<ui:define name="pre-texto">
		Esta página tem como objetivo cadastrar novas linhas de pesquisa que não se encontram no sistema. <br />
		Certifique-se de que a linha de pesquisa realmente não está cadastrado para o programa de pós graduação escolhida. Caso contrário, o registro será duplicado. <br />
	</ui:define>
	
	<ui:define name="formulario">
		<h1>Cadastro de nova linha de pesquisa para programas de pós graduação</h1>
		
		<h:form id="frm" role="form" class="form-horizontal">
			<h:messages showDetail="false" showSummary="true" autoUpdate="true"
				errorStyle="color: red;" infoStyle="color: green;"
				warnStyle="color: orange;" fatalStyle="color: grey;"/>
		
			<div class="wizard-header">
              
            </div>
            <div class="wizard-content">
               	<div class="form-group">
               		<h:outputLabel value="Modalidade do curso:* " for="modalidade" styleClass="col-sm-3 control-label" />
               		<p:selectOneButton id="modalidade" 
                   		value="#{cadastroLinhaPesquisaBean.linhaPesquisa.programaPosGraduacao.modalidadeCurso}">
                   			<p:ajax event="change" update="programasPosGraduacao" process="@this"
								listener="#{cadastroLinhaPesquisaBean.modalidadeCursoAlterado}" />
                   			
                   			<f:selectItems 
                   				value="#{cadastroLinhaPesquisaBean.modalidadeCurso}" var="modalidadeCurso"
                   				itemLabel="#{modalidadeCurso.descricao}" itemValue="#{modalidadeCurso}" />
                   	</p:selectOneButton> 
               	</div>
               	
               	<div class="form-group">
               		<h:outputLabel value="Programa de pós graduação:* " for="programasPosGraduacao" styleClass="col-sm-3 control-label" />
               		<div class= "col-sm-9">
               			<h:selectOneMenu id="programasPosGraduacao" 
               					value="#{cadastroLinhaPesquisaBean.linhaPesquisa.programaPosGraduacao}" class="form-control">
               				<f:selectItem noSelectionOption="true" itemLabel="Selecione a modalidade do curso" itemValue="" />
               				<f:selectItems value="#{cadastroLinhaPesquisaBean.todosProgramas}" var="programas"
               					itemLabel="#{programas.programa}" itemValue="#{programas.id}"/>
               			</h:selectOneMenu>
               		</div>
               	</div>
               	
               	
               	<div class="form-group">
               		<h:outputLabel value="Nova linha de pesquisa:* " for="linhaDePesquisa" styleClass="col-sm-3 control-label" />
               		<div class="col-sm-9">
               			<h:inputText value="#{cadastroLinhaPesquisaBean.linhaPesquisa.linhaPesquisa}"
               				id="linhaDePesquisa" styleClass="form-control small-lg" />
               		</div>
           		</div>
               	
           		<div class="form-group">
              		<div class="col-sm-3" />
              		<div class="col-sm-9">
              			<p:commandButton action="#{cadastroLinhaPesquisaBean.salvar}" update="@form"
              				value="Cadastrar" styleClass="wizard-finish btn btn-primary" />
                  	</div>
              	</div>
           	</div>
		</h:form>
	</ui:define>
</ui:composition>	
</code>

CadastroLinhaPesquisaBean.java
<code>
package com.ufop.fichas.bean;

import java.io.Serializable;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.inject.Inject;
import javax.inject.Named;

import org.omnifaces.cdi.ViewScoped;

import com.ufop.fichas.enumerator.ModalidadeCurso;
import com.ufop.fichas.model.LinhaDePesquisa;
import com.ufop.fichas.model.ProgramaPosGraduacao;
import com.ufop.fichas.repository.ProgramaPosGraduacaoRepository;
import com.ufop.fichas.service.CadastroLinhaDePesquisa;
import com.ufop.fichas.service.NegocioException;

@Named
@ViewScoped
public class CadastroLinhaPesquisaBean implements Serializable {
	
	private static final long serialVersionUID = 1L;
	
	@Inject
	private CadastroLinhaDePesquisa cadastro;
	@Inject
	private ProgramaPosGraduacaoRepository programaRepository;
	
	private List<ProgramaPosGraduacao> todosProgramas;
	
	private LinhaDePesquisa linhaPesquisa = new LinhaDePesquisa();
	
	public void processar() {
		if (this.linhaPesquisa == null) {
			this.linhaPesquisa = new LinhaDePesquisa();
			this.linhaPesquisa.setProgramaPosGraduacao(new ProgramaPosGraduacao());
		}
	}
	
	public void salvar() {
		FacesContext context = FacesContext.getCurrentInstance();

		try {
			this.cadastro.salvar(linhaPesquisa);
			this.linhaPesquisa = new LinhaDePesquisa();
			this.linhaPesquisa.setProgramaPosGraduacao(new ProgramaPosGraduacao());
			context.addMessage(null, new FacesMessage("Programa de Pós Graduação cadastrado com sucesso !"));
		} catch (NegocioException e) {
			FacesMessage message = new FacesMessage(e.getMessage());
			message.setSeverity(FacesMessage.SEVERITY_ERROR);
			context.addMessage(null, message);
		}
	}
	
	public List<ProgramaPosGraduacao> getTodosProgramas() {
		return this.todosProgramas;
	}
	
	public LinhaDePesquisa getLinhaPesquisa() {
		return linhaPesquisa;
	}

	public void setlinhaPesquisa(LinhaDePesquisa linhaPesquisa) {
		this.linhaPesquisa = linhaPesquisa;
	}
	
	public ProgramaPosGraduacao getProgramaPosGraduacao() {
		return this.linhaPesquisa.getProgramaPosGraduacao();
	}
	
	public void setProgramaPosGraduacao(ProgramaPosGraduacao programaPosGraduacao) {
		this.linhaPesquisa.setProgramaPosGraduacao(programaPosGraduacao);
	}
	
	public ModalidadeCurso[] getModalidadeCurso() {
		return ModalidadeCurso.values();
	}
	
	public void modalidadeCursoAlterado(AjaxBehaviorEvent event) {
		this.todosProgramas = programaRepository.byModalidade(this.getLinhaPesquisa().getProgramaPosGraduacao().getModalidadeCurso());
	}
}
</code>

ProgramaPosGraduacaoConverter.java
<code>
package com.ufop.fichas.converter;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.inject.Inject;

import com.ufop.fichas.model.ProgramaPosGraduacao;
import com.ufop.fichas.repository.ProgramaPosGraduacaoRepository;

@FacesConverter(forClass = ProgramaPosGraduacao.class)
public class ProgramaPosGraduacaoConverter implements Converter {
	
	@Inject
	private ProgramaPosGraduacaoRepository programaPosGraduacao;
	
	@Override
	public Object getAsObject(FacesContext context,
			UIComponent component, String value) {
		
		if(value != null && !"".equals(value)) {
			return this.programaPosGraduacao.byId(new Long(value));
		}
		
		return null;
	}
	
	@Override
	public String getAsString(FacesContext context,
			UIComponent component, Object value) {
		
		if (value != null) {
			ProgramaPosGraduacao programa = ((ProgramaPosGraduacao) value);
			
			return programa.getId() == null ? null : programa.getId().toString();
		}
		
		return null;
	}
}
</code>

ProgramaPosGraduacao.java
<code>
package com.ufop.fichas.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import com.ufop.fichas.enumerator.ModalidadeCurso;
import com.ufop.fichas.validation.NotNullOrEmpty;

@Entity
@Table(name = "programaPosGraduacao")
public class ProgramaPosGraduacao implements Serializable {

	private static final long serialVersionUID = 1L;
	
	private Long id;
	private String programa;
	private ModalidadeCurso modalidade;
	
	@Id
	@GeneratedValue
	public Long getId() {
		return id;
	}
	
	public void setId(Long id) {
		this.id = id;
	}
	
	@NotNullOrEmpty
	@Size(max = 255, message = "Programa excede o tamanho permitido")
	@Column(length = 80, nullable = false)
	public String getPrograma() {
		return programa;
	}
	
	public void setPrograma(String programa) {
		this.programa = programa;
	}
	
	@NotNull
	@Enumerated(EnumType.STRING)
	@Column(nullable = false)
	public ModalidadeCurso getModalidadeCurso() {
		return modalidade;
	}
	
	public void setModalidadeCurso(ModalidadeCurso modalidade) {
		this.modalidade = modalidade;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (this == obj) return true;
		if (obj == null) return false;
		if (getClass() != obj.getClass()) return false;
		
		if (obj instanceof ProgramaPosGraduacao) {
			ProgramaPosGraduacao other = (ProgramaPosGraduacao) obj;
			
			return id == other.id
				&& programa == other.programa
				&& modalidade == other.modalidade;
		}
		
		return false;
	}
}

Alguém saberia como me ajudar a resolver esse problema?