Commandbutton nao chama metodo se nao alterar campos do form ou no excluir

Bem, tenho uma popup com dois botoes (excluir e salvar), apenas um ou o outro renderizado. Ambos num form dentro de um dialog. O problema acontece se eu chamar o botao do alterar sem alterar nenhum valor do estado (sigla ou descricao) ou quando chamo o excluir (alterando o disable dos campos no excluir para poder alterá-los não deu certo também). Bem, em ambos os casos, a acao do botao nao eh chamada, mas se eu alterar algum valor no alterar e clicar no botao alterar a acao de atualizar eh chamada. O escopo utilizado eh @ViewScoped. Alguem sabe o porque isso acontece ou como resolver?

popup:

<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:p="http://primefaces.org/ui">

<h:inputHidden value="#{controleEstado.entidade.id}" />
<h:panelGrid columns="2">

	<h:outputLabel value="Nome*" />
	<p:inputText id="dsc" value="#{controleEstado.entidade.dsc}"
		disabled="#{controleEstado.entidade.visualizar}" required="true"
		requiredMessage="Campo Obrigatório: Nome" size="20">
		<f:ajax />
	</p:inputText>

	<h:outputLabel value="Sigla*" />
	<p:inputText id="nome" value="#{controleEstado.entidade.sigla}"
		disabled="#{controleEstado.entidade.visualizar}" required="true"
		requiredMessage="Campo Obrigatório: Sigla">
		<f:ajax />
	</p:inputText>
</h:panelGrid>


</html>

Pagina de busca (a dialog com os botoes está no final e a chamada da dialog está no footer da datatable)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.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:p="http://primefaces.org/ui">

<ui:composition template="/layout.xhtml">

	<ui:define name="conteudo">
		<h:form id="form" styleClass="jsfcrud_list_form">
			<p:growl id="messages" showDetail="true" />
			<h:panelGroup id="messagePanel" layout="block">
				<h:messages errorStyle="color: red" infoStyle="color: green"
					layout="table" />
			</h:panelGroup>
			<h:panelGroup>

				<p:dataTable widgetVar="entidadeTable" paginator="true" rows="10"
					id="tabela" value="#{controleEstado.entidadeDataModel}" var="item"
					style="border:solid 1px" editable="true" rowKey="#{item.id}"
					selection="#{controleEstado.entidadeSelecionada}"
					selectionMode="single">
					<f:facet name="header">
						<p:outputPanel>
							<h:panelGrid columns="2">
								<h:outputLabel value="Estado" />
								<p:inputText id="dscConsulta"
									value="#{controleEstado.entidadeBusca.dsc}" size="20">
								</p:inputText>

								<h:outputLabel value="Sigla" />
								<p:inputText id="nomeConsulta"
									value="#{controleEstado.entidadeBusca.sigla}" />
							</h:panelGrid>
							<p:commandButton value="Pesquisar"
								action="#{controleEstado.listarEntidades}" ajax="true"
								update="tabela" />
						</p:outputPanel>
					</f:facet>
					<p:ajax event="rowEdit" listener="#{controleEstado.onEdit}"
						update=":form:messages" />
					<p:ajax event="rowEditCancel" listener="#{controleEstado.onCancel}"
						update=":form:messages" />
					<p:column>

						<f:facet name="header">
							<h:outputText value="Estado" />
						</f:facet>
						<h:outputText value="#{item.dsc}" />
					</p:column>
					<p:column headerText="Sigla">
						<p:cellEditor>
							<f:facet name="output">
								<h:outputText value="#{item.sigla}" />
							</f:facet>
							<f:facet name="input">
								<p:inputText value="#{item.sigla}" style="width:100%" />
							</f:facet>
						</p:cellEditor>
					</p:column>

					<p:column style="width:4%">
						<p:rowEditor />
					</p:column>
					<f:facet name="footer">
						<p:commandButton value="Alterar"
							actionListener="#{controleEstado.preparaAlterar}"
							oncomplete="dlgPagBusca.show();" update=":basicDialog">
						</p:commandButton>
						<p:commandButton value="Vizualizar"
							actionListener="#{controleEstado.preparaExcluir}"
							oncomplete="dlgPagBusca.show();" update=":basicDialog">
						</p:commandButton>
						<p:commandButton value="Cadastrar"
							action="#{controleEstado.preparaCadastrar}" ajax="false" />
					</f:facet>
				</p:dataTable>

			</h:panelGroup>
			<h:outputText id="txt_count" value="#{counterBean.hora}" />


			<p:notificationBar position="top" effect="slide" widgetVar="bar"
				styleClass="top">
				<h:outputText id="txt" value="#{counterBean.hora}" />
			</p:notificationBar>
		</h:form>

		<p:dialog id="basicDialog" header="Estado" widgetVar="dlgPagBusca"
			modal="true" appendToBody="true">
			<h:form styleClass="jsfcrud_list_form" id="form2">
				<ui:include src="/estado/CadastroEstadoPnl.xhtml"></ui:include>
				<p:commandButton rendered="#{controleEstado.entidade.visualizar}"
					action="#{controleEstado.excluir}" value="Excluir" immediate="true"
					update=":form:messagePanel :form:tabela" />
				<p:commandButton rendered="#{!controleEstado.entidade.visualizar}"
					action="#{controleEstado.atualizar}" value="Salvar"
					update=":form:messagePanel :form:tabela" />
				<p:commandButton value="Cancelar" ajax="true"
					onclick="dlgPagBusca.hide();" immediate="true" />
			</h:form>
		</p:dialog>

	</ui:define>
</ui:composition>

</html>

bean genérico (so os metodos relevantes) (ps: funcionava normalmente antes de usar popups (mudando a pagina para alterar e vizualizar/excluir) e com o escopo de sessão, mas ficaria muito pesada a aplicação)

public abstract class Controle<Entidade> {
//...
	public void atualizar() {
		List<String> listaErros = new ArrayList<String>();
		// para evitar chamar o addAll numa lista nula
		List<String> errosTemp;
		try {
			errosTemp = salvarAlterarEspecifico();
			if (errosTemp != null) {
				listaErros.addAll(errosTemp);
			}
			errosTemp = salvarAlterarECadastrarEspecifico();
			if (errosTemp != null) {
				listaErros.addAll(errosTemp);
			}

			if (listaErros.size() <= 0) {
				jpa.atualizar(entidade);
				entidadeBusca = entidade;
				listarEntidades();
				limpaDadosBean();
				fechaDialog(DLG_PAG_BUSCA);
				enviaMensagemUsuario("Entidade salva com sucesso",
						FacesMessage.SEVERITY_INFO);
			} else {
				trataErro(listaErros);
			}
		} catch (Exception e) {
			trataErro(e);
		}
	}
//...
	public void excluir() {
		List<String> listaErros = new ArrayList<String>();
		// para evitar chamar o addAll numa lista nula
		List<String> errosTemp;
		errosTemp = excluirEspecifico();
		if (errosTemp != null) {
			listaErros.addAll(errosTemp);
		}
		if (listaErros.size() > 0) {
			trataErro(listaErros);
			return;
		}
		try {
			jpa.excluir(entidade);
			limpaDadosBean();
			fechaDialog(DLG_PAG_BUSCA);
			enviaMensagemUsuario("Entidade excluída com sucesso",
					FacesMessage.SEVERITY_INFO);
			listarEntidades();
		} catch (Exception e) {
			trataErro(e);
			entidadeSelecionada = jpa.buscarPorCampos(entidadeSelecionada).get(
					0);
			entidadeDataModel.replaceEntity(entidadeSelecionada);
		}
	}
/...

e o bean do estado

package rhoma.controle;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

import rhoma.entidades.Estado;

@ManagedBean
@ViewScoped
public class ControleEstado extends Controle<Estado> {

	void preparaCadastrarEspecifico() {
	}

	@Override
	void preparaBuscaEspecifica() {
	}

	@Override
	void preparaAlterarEspecifico() {
	}

	@Override
	List<String> salvarCadastrarEspecifico() {
		return null;
	}

	@Override
	List<String> salvarAlterarEspecifico() {
		return null;
	}

	@Override
	List<String> salvarAlterarECadastrarEspecifico() {
		return null;
	}

	@Override
	void preparaCadastrarEspecífico() {
		
	}

	@Override
	List<String> excluirEspecifico() {
		return new ArrayList<String>();
	}

	@Override
	public void limpaDadosBean() {
		entidade = new Estado();
		entidade.setAlterar(false);
		entidade.setVisualizar(false);
		entidadeBusca = new Estado();
	}

	@Override
	void resetaBeanSelecionadoBusca() {
		entidadeSelecionada = new Estado();
	}

	@Override
	void reinicializaCamposNulos() {
		
	}

	public List<Estado> getListaTodosEstadosSelecao() {
		ArrayList<Estado> listaEstado = new ArrayList<Estado>();
		listaEstado.add(new Estado(-1, "SELECIONE", "SELECIONE"));
		List<Estado> buscarPorCampos = jpa.selecionarTodos(new Estado());
		if (buscarPorCampos != null && buscarPorCampos.size() > 0) {
			listaEstado.addAll(buscarPorCampos);
		}
		return listaEstado;
	}

	@Override
	List<String> listarEntidadesVerificacaoEspecifica() {
		return null;
	}

	@Override
	void preparaExcluirEspecifico() {
		
	}

	@Override
	void preparaAlterarExcluirEspecifico() {
		
	}

}

A proposito, se eu colocar o mesmo botao fora do dialog sem mudar nada(testei com o excluir, bem, coloquei um ! na flag de rendered so pra ele aparecer), a action eh chamada normalmente