[RESOLVIDO] combos aninhados

Boa tarde galera, estou enfrentando uma dorzinha de cabeça tentando implementar esse combo com ajax.

Seguem o código.

Classes modelo:

@Entity
public class Sistema implements Serializable {

	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue
	private Long idSistema;
	private String nomeSistema;
	private String descricao;
	
	@ManyToMany
	@JoinTable(name="sistema_perfilusuario", 
			joinColumns = {@JoinColumn(name="idSistema")}, 
			inverseJoinColumns = {@JoinColumn(name="idUsuario")})
	private List<PerfilUsuario> usuarios;
@Entity
public class Servico implements Serializable {

	private static final long serialVersionUID = 1L;
	
	@Id 
	@GeneratedValue
	private Long id_servico;
	private String nome_servico;
	private String descricao;
	private String breveDesc;
	
	@Valid
	@ManyToOne
	private Sistema sistemaVinculado;

Pagina html:

		    		<h:outputLabel value="Sistema:" for="sistema" />  
					<h:selectOneMenu id="sistema" value="#{apropriacaoBean.sistemaId}" converter="converterSistema" >
						<f:selectItem itemLabel="Selecione" />
						<f:selectItems value="#{listaSistemasCadastrados.sistemas}" var="e" itemValue="#{e.idSistema}" itemLabel="#{e.nomeSistema}" />
						<f:ajax render="servico" event="change" listener="#{sistemaBean.listaServicos}" />
					</h:selectOneMenu>
		    		  
		    		<h:outputLabel value="Servi&#227;o:" for="servico" /> 
		    		<h:selectOneMenu id="servico" value="#{apropriacaoBean.servicoId}" converter="converterServico" >
						<f:selectItem itemLabel="Selecione" />
						<f:selectItems value="#{servicoBean.cadastroServicos}" var="c" itemValue="#{c.id_servico}" itemLabel="#{c.nome_servico} - #{c.breveDesc}" />
					</h:selectOneMenu>

Eu implementei também os converters:

[code]@FacesConverter(value = “converterServico”)
public class ConverterServico implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {

	if (value != null && !value.equals("")) {
		DAO<Servico> dao = new DAO<Servico>(Servico.class);
		return dao.buscaPorId(Long.valueOf(value));
	}

	return null;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {

	if (value instanceof Servico) {
		Servico servico = (Servico) value;
		return String.valueOf(servico.getId_servico());
	}

	return "";
}

}[/code]

@FacesConverter(value = "converterSistema")
public class ConverterSistema implements Converter {

	@Override
	public Object getAsObject(FacesContext context, UIComponent component, String value) {

		if (value != null && !value.equals("")) {
			DAO<Sistema> dao = new DAO<Sistema>(Sistema.class);
			return dao.buscaPorId(Long.valueOf(value));
		}

		return null;
	}

	@Override
	public String getAsString(FacesContext context, UIComponent component, Object value) {

		if (value instanceof Sistema) {
			Sistema sistema = (Sistema) value;
			return String.valueOf(sistema.getIdSistema());
		}

		return "";
	}

}

Meu Bean:

	public void listaServicos(AjaxBehaviorEvent event) throws ParseException {
		
		if(apropriar != null){
			servicos = getServicos(1);
		}
	}
	
	
	public List<Servico> getServicos(long idSistema) throws ParseException{

		EntityManager em = new JPAUtil().getEntityManager();    
		em.getTransaction().begin();    

		String jpql = "select s from Servico s where s.sistemaVinculado.idSistema = ?";
		Query query = em.createQuery(jpql);  
		query.setParameter(1, idSistema);

		em.close();    
		return query.getResultList();    
	}

Obs.: O que acontece é que independente quantos registros ele traga na consulta getServicos no formulário ele acaba trazendo todos que eu possuo cadastrado. Sei que fico extenso mais coloquei tudo para talvez quem possa ajuda visualize melhor o que possa estar acontecendo. Ahhhhhhh, meus converters no xhtml está com warm, caso ajude algo também. Obrigado a todos!

Cara, analisando rapidamente, vi que você utilizou como value dos SelectOneMenus, os ids das entidades “Servico” e “Sistema”.
Porém, os seus converters convertem as Strings em objetos “Servico” e “Sistema” .

Não sei se isso é exatamente o problema que você quer resolver, mas acredito que a aplicação não esteja se comportando da forma correta.
Para solucionar, você pode trocar o value dos selectOneMenus para objetos que armazenem as instancias das classes “Sistema” e “Servico”, ou então corrigir o seu converter para retornar Id da classe convertida (em getAsObject).
Acho que a primeira solução seria mais correta, ficando algo ± assim:

@ManagedBean(name="apropriacaoBean")
public class ApropriacaoBean{
    private Sistema sistema;
    private Servico servico;

    //gets e sets omitidos

}

E, nos selectOneMenus, ficaria assim:

<h:selectOneMenu value="#{apropriacaoBean.sistema}" converter="sistemaConverter"...>
...
   <f:selectItems value="#{listaSistemasCadastrados.sistemas}" var="e" itemValue="#{e}" itemLabel="#{e.nomeSistema}" /> 
</h:selectOneMenu>

O mesmo vale para a outra entidade.
Já, quanto aos warnnings dos converters, acho que o problema é da IDE (acredito ser Eclipse) que não reconhece as anotações FacesConverter.
Comigo também fica assim, mas após a primeira execução no servidor, esses warnnings desaparecem.
Você pode incluir a configuração dos converteres no faces-config.xml (caso você tenha esse arquivo). Nele, a IDE reconhece a configuração e retira os warnnings.

Espero ter ajudado.

[quote=Richard Mendes Madureira]Cara, analisando rapidamente, vi que você utilizou como value dos SelectOneMenus, os ids das entidades “Servico” e “Sistema”.
Porém, os seus converters convertem as Strings em objetos “Servico” e “Sistema” .

Não sei se isso é exatamente o problema que você quer resolver, mas acredito que a aplicação não esteja se comportando da forma correta.
Para solucionar, você pode trocar o value dos selectOneMenus para objetos que armazenem as instancias das classes “Sistema” e “Servico”, ou então corrigir o seu converter para retornar Id da classe convertida (em getAsObject).
Acho que a primeira solução seria mais correta, ficando algo ± assim:

@ManagedBean(name="apropriacaoBean")
public class ApropriacaoBean{
    private Sistema sistema;
    private Servico servico;

    //gets e sets omitidos

}

E, nos selectOneMenus, ficaria assim:

<h:selectOneMenu value="#{apropriacaoBean.sistema}" converter="sistemaConverter"...>
...
   <f:selectItems value="#{listaSistemasCadastrados.sistemas}" var="e" itemValue="#{e}" itemLabel="#{e.nomeSistema}" /> 
</h:selectOneMenu>

O mesmo vale para a outra entidade.
Já, quanto aos warnnings dos converters, acho que o problema é da IDE (acredito ser Eclipse) que não reconhece as anotações FacesConverter.
Comigo também fica assim, mas após a primeira execução no servidor, esses warnnings desaparecem.
Você pode incluir a configuração dos converteres no faces-config.xml (caso você tenha esse arquivo). Nele, a IDE reconhece a configuração e retira os warnnings.

Espero ter ajudado.[/quote]

Bom dia Richard M. Madureira, em primeiro lugar obrigado pela ajuda.

Então está solução é para salvar os dados corretamentes certo ? Só que fiz da forma proposta é não obtive sucesso :frowning: . Em relação da listagem er dinamica estou quase conseguindo. Qualquer duvida posto aqui. Desde já, obrigado!

Alguem poderia dar uma luz. Estou fazendo desta forma aqui agora, só que na hora de salvar la no meu banco os ids do serviço e do sistema estão sendo null. Segue o codigo.

Bean:

public String gravar(){
		
		String messageCadastro = "Sistema "+sistema.getNomeSistema()+" cadastrado com sucesso.";
		String messageAlterar  = "Sistema "+sistema.getNomeSistema()+" alterado com sucesso.";
		FacesContext context = FacesContext.getCurrentInstance();
		
		DAO<Sistema> dao = new DAO<Sistema>(Sistema.class);
		usuarios = usuarioModel.getSource();
		usuariosSelecionados = usuarioModel.getTarget();
			
		sistema.setUsuarios(usuariosSelecionados);
		
		if(sistema.getIdSistema() == null){
			dao.adiciona(sistema);
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, messageCadastro, ""));			
		}else{
			dao.atualiza(sistema);
			context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, messageAlterar, ""));			
		}
		
		sistemas = new DAO<Sistema>(Sistema.class).listaTodos();
		this.sistema = new Sistema();
		
		return "sistema.xhtml?faces-redirect=true";
	}

Converter:

[code]@FacesConverter(value=“converterSistema”)
public class ConverterSistema implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {

	if (value != null && !value.equals("")) {
		Sistema sistema = new Sistema();
		sistema.setIdSistema(Long.parseLong(value));
		
		return sistema;
	}

	return null;
}

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {

	if (value instanceof Sistema) {
		Sistema sistema = (Sistema) value;
		return String.valueOf(sistema.getIdSistema());
	}

	return "";
}[/code]

xHTML:

[code]<h:outputLabel value=“Sistema:” for=“sistema” />
<h:selectOneMenu id=“sistema” value="#{apropriacaoBean.sistema}" converter=“converterSistema” >
<f:selectItem itemLabel=“Selecione” />
<f:selectItems value="#{apropriacaoBean.sistemas}" var=“e” itemValue="#{e}" itemLabel="#{e.nomeSistema}" />
<f:ajax render=“servico” event=“change” listener="#{apropriacaoBean.listaServicos}" />
</h:selectOneMenu>

	    		<h:outputLabel value="Servi&#227;o:" for="servico" /> 
	    		<h:selectOneMenu id="servico" value="#{apropriacaoBean.servico}" converter="converterServico" >
					<f:selectItem itemLabel="Selecione" />
					<f:selectItems value="#{apropriacaoBean.servicos}" var="c" itemValue="#{c}" itemLabel="#{c.nome_servico} - #{c.breveDesc}" />
				</h:selectOneMenu>[/code]

Malz ai galera, consegui resolver, estava faltando eu setar os valores…rsrsrsrsr

Segue o código.

[code]public String gravar(){
SimpleDateFormat sp = new SimpleDateFormat(“dd/MM/yyyy”);

	String messageCadastro = "Horas apropriadas com sucesso na data "+sp.format(apropriar.getDataApropriacao())+"";
	String messageAlterar = "Apropriação da data "+sp.format(apropriar.getDataApropriacao())+" alterada com sucesso.";
	FacesContext context = FacesContext.getCurrentInstance();
	
	DAO<Apropriar> daoApropriar  = new DAO <Apropriar>(Apropriar.class);
	DAO<PerfilUsuario> daoPerfil = new DAO<PerfilUsuario>(PerfilUsuario.class);
	
	PerfilUsuario usuarioVinculado = daoPerfil.buscaPorId(idUsuario);
	apropriar.setApropriacaoPerfil(usuarioVinculado);
	
	apropriar.setSistemaVinculado(sistema);
	apropriar.setServicoVinculado(servico);
	
	if(apropriar.getIdApropriacao() == null){
		daoApropriar.adiciona(apropriar);
		context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, messageCadastro, ""));	

	}else{
		daoApropriar.atualiza(apropriar);
		context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, messageAlterar, ""));			

	}

	this.apropriacoes = new DAO<Apropriar>(Apropriar.class).listaTodos();
	this.apropriar = new Apropriar();
	return "menuUsuario.xhtml?faces-redirect=true";
}[/code]