JSF + Primefaces - SelectOneMenu parou de funcionar sem explicação aparente

Boa tarde senhores,

Há alguns dias eu postei sobre dificuldades com Converters para p:selectOneMenu, onde fui gentilmente ajudado e troquei o converter que utilizava por outro que funcionou PERFEITAMENTE!

No entanto, agora, dias depois, todos os selectOneMenu da aplicação pararam de funcionar, sendo que todos eles apresentam o mesmo sintoma: Listam normalmente, porém não selecionam o objeto de fato.

Em modo debug nota-se que o converter está sendo chamado normalmente, mas o método getAsObject retorna null. Já tentei várias coisas, mas não consigo resolver.

Alguém já passou por isso?

Segue os códigos:

View:

<p:selectOneMenu id="selectEvento" value="#{bean.eventoSelecionado}" style="width: 95%;" converter="simpleIndexConverter" required="true" requiredMessage="A informação 'Evento' é obrigatória"> <f:selectItems value="#{bean.listaEventos}"/> </p:selectOneMenu>

Bean:


...

private List<SelectItem> listaEventos;

private Evento eventoSelecionado;

...

	private void geraListaEventos() {

		EventoDao evenDao = new EventoDao();

		List<Evento> lista = (List<Evento>) evenDao.getAll();

		listaEventos = new ArrayList<SelectItem>();

		listaEventos.add(new SelectItem(null, "Selecione"));

		for (Evento evento : lista) {
			listaEventos.add(new SelectItem(evento, evento.getEvento()));
		}

	}

Converter:

package utils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UISelectItem;
import javax.faces.component.UISelectItems;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.model.SelectItem;
import javax.faces.model.SelectItemGroup;

public class SimpleIndexConverter implements Converter {

	private int index = -1;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext
	 * , javax.faces.component.UIComponent, java.lang.String)
	 */
	public Object getAsObject(FacesContext ctx, UIComponent component,
			String value) {

		SelectItem selectedItem = this.getSelectedItemByIndex(component,
				Integer.parseInt(value));
		if (selectedItem != null)
			return selectedItem.getValue();

		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * javax.faces.convert.Converter#getAsString(javax.faces.context.FacesContext
	 * , javax.faces.component.UIComponent, java.lang.Object)
	 */
	public String getAsString(FacesContext ctx, UIComponent component,
			Object value) {
		index++;
		return String.valueOf(index);
	}

	/**
	 * Obtem o SelecItem de acordo com a opção selecionada pelo usuário
	 */
	protected SelectItem getSelectedItemByIndex(UIComponent component, int index) {

		List<SelectItem> items = this.getSelectItems(component);
		int size = items.size();

		if (index > -1 && size > index) {
			return items.get(index);
		}

		return null;
	}

	protected List<SelectItem> getSelectItems(UIComponent component) {

		List<SelectItem> items = new ArrayList<SelectItem>();

		int childCount = component.getChildCount();
		if (childCount == 0)
			return items;

		List<UIComponent> children = component.getChildren();
		for (UIComponent child : children) {
			if (child instanceof UISelectItem) {
				this.addSelectItem((UISelectItem) child, items);
			} else if (child instanceof UISelectItems) {
				this.addSelectItems((UISelectItems) child, items);
			}
		}

		return items;
	}

	protected void addSelectItem(UISelectItem uiItem, List<SelectItem> items) {

		boolean isRendered = uiItem.isRendered();
		if (!isRendered) {
			items.add(null);
			return;
		}

		Object value = uiItem.getValue();
		SelectItem item;

		if (value instanceof SelectItem) {
			item = (SelectItem) value;
		} else {
			Object itemValue = uiItem.getItemValue();
			String itemLabel = uiItem.getItemLabel();
			// JSF throws a null pointer exception for null values and labels,
			// which is a serious problem at design-time.
			item = new SelectItem(itemValue == null ? "" : itemValue,
					itemLabel == null ? "" : itemLabel,
					uiItem.getItemDescription(), uiItem.isItemDisabled());
		}

		items.add(item);
	}

	@SuppressWarnings("unchecked")
	protected void addSelectItems(UISelectItems uiItems, List<SelectItem> items) {

		boolean isRendered = uiItems.isRendered();
		if (!isRendered) {
			items.add(null);
			return;
		}

		Object value = uiItems.getValue();
		if (value instanceof SelectItem) {
			items.add((SelectItem) value);
		} else if (value instanceof Object[]) {
			Object[] array = (Object[]) value;
			for (int i = 0; i < array.length; i++) {
				if (array[i] instanceof SelectItemGroup) {
					resolveAndAddItems((SelectItemGroup) array[i], items);
				} else {
					items.add((SelectItem) array[i]);
				}
			}
		} else if (value instanceof Collection) {
			Iterator<SelectItem> iter = ((Collection<SelectItem>) value)
					.iterator();
			SelectItem item;
			while (iter.hasNext()) {
				item = iter.next();
				if (item instanceof SelectItemGroup) {
					resolveAndAddItems((SelectItemGroup) item, items);
				} else {
					items.add(item);
				}
			}
		} else if (value instanceof Map) {
			for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) value)
					.entrySet()) {
				Object label = entry.getKey();
				SelectItem item = new SelectItem(entry.getValue(),
						label == null ? (String) null : label.toString());
				if (item instanceof SelectItemGroup) {
					resolveAndAddItems((SelectItemGroup) item, items);
				} else {
					items.add(item);
				}
			}
		}
	}

	protected void resolveAndAddItems(SelectItemGroup group,
			List<SelectItem> items) {
		for (SelectItem item : group.getSelectItems()) {
			if (item instanceof SelectItemGroup) {
				resolveAndAddItems((SelectItemGroup) item, items);
			} else {
				items.add(item);
			}
		}
	}

}

vc usa esse converter para tudo?

eu gosto de criar separado
cada classe tem seu converter(caso precise)
e dependendo do componente que estou usando
o meu converter variar

mas nesse caso o componente OneMenu
não tem necessidade de ter um converter desse tipo

vc usa esse selectOneMenu apenas para selecionar
e gravar no banco?

[quote=tmvolpato]vc usa esse converter para tudo?

eu gosto de criar separado
cada classe tem seu converter(caso precise)
e dependendo do componente que estou usando
o meu converter variar

mas nesse caso o componente OneMenu
não tem necessidade de ter um converter desse tipo

vc usa esse selectOneMenu apenas para selecionar
e gravar no banco?
[/quote]

Sim… uso para todos os selectOneMenu do sistema, porém o mesmo não funciona pra autoComplete. Mas num seria melhor aproveitar a mesma classe pra tudo?

Uso isso para vários fins na verdade… e utilizo objetos no select, ao invés de apenas String… existe maneira de se fazer isto sem uso de converters?

Pessoal,

O problema está parcialmente resolvido, vejam.

Em busca da solução, comecei a desfazer tudo que tinha feito até dar problema, e surgiu algo muito estranho. Tenho um index.xhtml que tem um menu principal (p:megaMenu), um p:tabView com abas dinamicas, onde carrego as abas com as páginas de acordo com a seleção feita no megaMenu.

Ontem estava fazendo uns testes de escopos e mudei o escopo do index de View para Session… e embora a bean que controle o selectOneMenu não tenha sido mexida ( escopo View), por mudar isso no index, que fica sendo “pai” da view em questão, os selects param de funcionar… Não que NECESSARIAMENTE eu tenha que usar Session, mas gostaria ao menos de entender o porque disso, alguem sabe?

Abraços