我工作的项目有一个共同的行为,即用户在使用任何系统功能之前必须选择一个或多个存储。
创建了一个复合组件,以满足负责业务规则的独特位置的要求。
最近我收到了修复问题的请求:当dev在受管Bean上使用了两次(或更多)组件时,它们共享同一个实例。
E.g:
@Named
@ViewScoped
public class MovVolumeManager implements Serializable {
@Inject
private SeletorLocalizacaoManager seletorLocalOrigem;
@Inject
private SeletorLocalizacaoManager seletorLocalOrigem;
在我的测试中,seletorLocalOrigem和seletorLocalOrigem将保持相同的值。
据我所知,当CDI发现同一个类被声明为两个不同的变量时,它们会在容器内存上共享相同的地址。我是CDI的新手,我不知道如何解决这个问题。
预期的行为是:bean可以有N" Seletor Local"在同一页上。
当有人想要使用" Seletor Local"时,他应该:
在Bean上注入组件并在后期构建阶段初始化
@Named
@ViewScoped
public class MovVolumeOrigemManager implements Serializable {
@Inject
@Getter @Setter
private SeletorLocalizacaoManager seletorLocal;
@PostConstruct
public void inicializar() {
seletorLocal.setSelecaoMultipla(true);
seletorLocal.setCodigosClasseExibicao(BeanUtil.adicionarClassesLocais());
seletorLocal.setCodigosClasseSelecao(BeanUtil.adicionarClassesLocais());
seletorLocal.setGruposSegurancaWeb(BeanUtil.adicionarGruposSeguranca());
seletorLocal.setRealizaAcaoAdicionalAposSelecao(false);
seletorLocal.criarArvoreHierarquica();
}
}
在标记
上传递必需的属性<sup:seletorLocalizacao id="seletorLocalizacaoDestino" mb="#{movVolumeDestinoBean.seletorLocal}" minQueryLength="2" />
环境
SeletorLocalizacao经理类
@Named
@ViewScoped
public class SeletorLocalizacaoManager implements Serializable {
private static final long serialVersionUID = -4705289709340063089L;
@Inject
private LocalizacaoRN localizacaoRN;
@Inject
private ArvoreUtil arvoreUtil;
private MetodoSelecaoLocalEnum controleExibicao;
private Boolean renderHierarquia;
private Boolean renderIncremental;
private boolean selecaoMultipla;
private String labelClasseLocal;
private boolean semRestricaoSelecao;
private List<ClasseLocalTO> codigosClasseExibicao;
private List<String> gruposSegurancaWeb;
private List<ClasseLocalTO> codigosClasseSelecao;
private List<LocalizacaoTO> locaisHierarquicosSelecionados;
private List<LocalizacaoTO> locaisClasseSelecionados;
private List<LocalizacaoTO> locaisSelecionados;
private List<LocalizacaoTO> historicoLocaisSelecionados;
private LocalizacaoTO localSelecionado;
private TreeNode localSelecionadoAnterior;
private TreeNode arvoreHierarquica;
private List<LocalizacaoTO> listaLocalClasseCadastrados;
private List<LocalizacaoTO> listaLocalCadastrados;
private NodeSelectEvent tbLocalNode;
private boolean realizaAcaoAdicionalAposSelecao;
@PostConstruct
public void init() {
if (controleExibicao == null) {
controleExibicao = MetodoSelecaoLocalEnum.HIERARQUICO;
}
controlarExibicao(controleExibicao);
}
public void criarArvoreHierarquica(){
arvoreHierarquica = arvoreUtil.montarArvoreLocalizacao(this.buscarHierarquia(),true);
}
public void alternarExibicao() {
controlarExibicao(controleExibicao);
}
public void alternarExibicao(AjaxBehaviorEvent event) {
controlarExibicao(controleExibicao);
}
public void controlarExibicao(MetodoSelecaoLocalEnum parametro) {
if (parametro == MetodoSelecaoLocalEnum.HIERARQUICO) {
setRenderHierarquia(true);
setRenderIncremental(false);
} else {
if(parametro == MetodoSelecaoLocalEnum.INCREMENTAL)
setRenderHierarquia(false);
setRenderIncremental(true);
}
}
public String gerarLabelClasse(boolean separador) {
StringBuilder labelClasse = new StringBuilder();
for(int i=0; i< codigosClasseSelecao.size(); i++) {
labelClasse.append(codigosClasseSelecao.get(i).getDescricaoClasseLocal());
if(i !=codigosClasseSelecao.size() -1) {
labelClasse.append("/");
}
}
if(separador) {
labelClasse.append("");
}
return labelClasse.toString();
}
public void selecionarLocalHierarquico() {
if(null == locaisHierarquicosSelecionados) {
locaisHierarquicosSelecionados = new ArrayList<LocalizacaoTO>();
}
if(localSelecionado != null) {
this.verificaRestricaoSelecao(localSelecionado);
if(semRestricaoSelecao) {
if(!selecaoMultipla){
locaisHierarquicosSelecionados.clear();
}
locaisHierarquicosSelecionados.add(localSelecionado);
localSelecionado = null;
RequestContext.getCurrentInstance().execute("PF('dlgSelecaoHierarquica').hide();");
} else {
MessageFormat msgFormat = new MessageFormat("A localização {0} não é uma classe de local autorizada. Favor selecionar um local da classe {1}.");
Object[] args = {localSelecionado.getDsLocalizacao(), gerarLabelClasse(false)};
String msg = msgFormat.format(args);
FacesContext.getCurrentInstance().addMessage("GROWL", new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erro", msg));
RequestContext.getCurrentInstance().update("mensagens");
}
}
}
public void onNodeSelect(NodeSelectEvent event) {
LocalizacaoTO local = null;
try {
if ( ! event.equals(tbLocalNode) ) {
if (tbLocalNode != null) {
tbLocalNode.getTreeNode().setSelected(false);
}
tbLocalNode = event;
}
local = ((LocalizacaoTO) event.getTreeNode().getData());
event.getTreeNode().setSelected(true);
if(null == localSelecionado) {
localSelecionado = new LocalizacaoTO();
historicoLocaisSelecionados = new ArrayList<LocalizacaoTO>();
}
localSelecionado = local;
historicoLocaisSelecionados.add(local);
if(localSelecionadoAnterior != null) {
localSelecionadoAnterior.setSelected(false);
localSelecionadoAnterior.setExpanded(false);
}
this.adicionarNiveisInferiores(local, event);
localSelecionadoAnterior = event.getTreeNode();
} catch (Exception e) {
}
}
private void adicionarNiveisInferiores(LocalizacaoTO local, NodeSelectEvent event) {
if(local.getNiveis() > 0 && event.getTreeNode().getChildCount() == 0) {
List<LocalizacaoTO> niveisInferiores = this.buscarHierarquia(local.getIdLocalizacao());
if(niveisInferiores != null && niveisInferiores.size() > 0) {
for(LocalizacaoTO localizacao : niveisInferiores) {
new DefaultTreeNode(localizacao, event.getTreeNode());
}
event.getTreeNode().setExpanded(true);
}
}
}
public void verificaRestricaoSelecao(LocalizacaoTO local) {
Long possuiClasseLocal = 0L;
if(null == codigosClasseSelecao || codigosClasseSelecao.size() == 0) {
semRestricaoSelecao = true;
} else {
for(ClasseLocalTO classeLocal : codigosClasseSelecao) {
if(classeLocal.getCodClasseLocal().equals(local.getCdClasseLocal())) {
possuiClasseLocal++;
}
}
if(possuiClasseLocal > 0) {
semRestricaoSelecao = true;
} else {
semRestricaoSelecao = false;
}
}
}
public List<LocalizacaoTO> buscarHierarquia() {
return localizacaoRN.buscarHieraquia(codigosClasseExibicao, null, gruposSegurancaWeb);
}
public List<LocalizacaoTO> buscarHierarquia(Long idLocalSuperior) {
return localizacaoRN.buscarHieraquia(codigosClasseSelecao, idLocalSuperior, gruposSegurancaWeb);
}
public List<LocalizacaoTO> completarClasseLocalizacao(String query) {
if (listaLocalClasseCadastrados == null || listaLocalClasseCadastrados.size() == 0) {
setListaLocalClasseCadastrados(new ArrayList<LocalizacaoTO>());
}
List<LocalizacaoTO> sugestoes = new ArrayList<LocalizacaoTO>();
sugestoes = localizacaoRN.buscarRegistrosAutocomplete(this.getCodigosClasseExibicao(), query.toUpperCase() + "%", null, gruposSegurancaWeb);
for (LocalizacaoTO localizacaoTO : sugestoes) {
getListaLocalClasseCadastrados().add(localizacaoTO);
}
return sugestoes;
}
public List<LocalizacaoTO> completarLocais(String query) {
if (listaLocalCadastrados == null || listaLocalCadastrados.size() == 0) {
setListaLocalCadastrados(new ArrayList<LocalizacaoTO>());
}
List<LocalizacaoTO> sugestoes = new ArrayList<LocalizacaoTO>();
sugestoes = localizacaoRN.buscarRegistrosAutocomplete(this.getCodigosClasseSelecao(), query.toUpperCase() + "%", locaisClasseSelecionados,gruposSegurancaWeb);
for (LocalizacaoTO localizacaoTO : sugestoes) {
getListaLocalCadastrados().add(localizacaoTO);
}
return sugestoes;
}
public void handleSelectClasseLocalizacao(SelectEvent event) {
LocalizacaoTO localRecebido = (LocalizacaoTO)event.getObject();
if(selecaoMultipla == false) {
if (locaisClasseSelecionados != null && locaisClasseSelecionados.size() > 0) {
locaisClasseSelecionados.clear();
locaisClasseSelecionados.add(localRecebido);
}
if (locaisSelecionados != null && locaisSelecionados.size() > 0) {
locaisSelecionados.clear();
}
}
}
public void handleUnSelectHierarquico(UnselectEvent event) {
LocalizacaoTO objetoRemovido = (LocalizacaoTO)event.getObject();
}
public void handleUnSelectClasseLocalizacao(UnselectEvent event) {
if (locaisSelecionados != null && locaisSelecionados.size() > 0) {
locaisSelecionados.clear();
}
}
public void handleSelectLocalizacao(SelectEvent event) {
LocalizacaoTO localRecebido = (LocalizacaoTO)event.getObject();
if(selecaoMultipla == false) {
if (locaisSelecionados != null && locaisSelecionados.size() > 0) {
locaisSelecionados.clear();
locaisSelecionados.add(localRecebido);
}
}
}
}
SeletorLocalizacao复合组件
<?xml version="1.0" encoding="UTF-8"?>
<html 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:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui"
xmlns:o="http://omnifaces.org/ui"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:su="http://java.sun.com/jsf/composite/selecao">
<cc:interface>
<cc:attribute name="id" required="true" />
<cc:attribute name="mb" required="true" type="br.com.usiminas.ipce.mb.SeletorLocalizacaoMB" />
<cc:attribute name="form" default="formPrincipal" />
<cc:attribute name="updateClasseLocalizacao" default="@this" />
<cc:attribute name="updateLocalizacao" default="@this" />
<cc:attribute name="updateItemSelectHierarquico"/>
<cc:attribute name="updateItemSelectIncremental"/>
<cc:attribute name="queryDelay" default="1000"/>
<cc:attribute name="minQueryLength" default="3" />
<cc:attribute name="bloqueiaModal" default="true" />
<cc:attribute name="nomeAcaoAdicional" />
<cc:attribute name="metodoAcaoAdicional" method-signature="void complementarSelecaoLocal()"/>
<cc:attribute name="updateAcaoAdicional" />
</cc:interface>
<cc:implementation>
<p:remoteCommand id="#{cc.attrs.id}BotaoRemoto"
name="complementar"
action="#{cc.attrs.metodoAcaoAdicional}"
update="#{cc.attrs.updateAcaoAdicional}"
async="true"/>
<h:outputText value="Seleção de local" styleClass="tituloFiltro"/>
<h:panelGrid columns="2">
<p:selectOneRadio id="#{cc.attrs.id}Radio" value="#{cc.attrs.mb.controleExibicao}" >
<p:ajax event="valueChange" listener="#{cc.attrs.mb.alternarExibicao}" update="#{cc.attrs.id}Conteiner" oncomplete="bloqueiaAutoMulti()"/>
<f:selectItem itemLabel="Hierarquica" itemValue="HIERARQUICO" />
<f:selectItem itemLabel="Incremental" itemValue="INCREMENTAL" />
</p:selectOneRadio>
</h:panelGrid>
<p:panelGrid id="#{cc.attrs.id}Conteiner" columns="1" styleClass="ui-custompanelgrid">
<h:panelGrid id="#{cc.attrs.id}GrdHierarquico" columns="1" rendered="#{cc.attrs.mb.renderHierarquia}">
<p:outputLabel value="#{cc.attrs.mb.labelClasseLocal}" />
<h:panelGrid columns="2">
<p:autoComplete id="#{cc.attrs.id}ACHierarquico"
scrollHeight="200" scrollable="true" styleClass="ui-autocomp ui-automulti-readonly #{cc.attrs.id}-auto-complete"
var="local" itemValue="#{local}" itemLabel="#{local.cdLocalCompleto}"
value="#{cc.attrs.mb.locaisHierarquicosSelecionados}"
multiple="true" converter="#{localizacaoTOHierarquicoConverter}"
minQueryLength="10"
>
<p:ajax event="itemUnselect"
update="@this"
listener="#{cc.attrs.mb.handleUnSelectHierarquico}"
oncomplete="bloqueiaAutoMulti()"/>
</p:autoComplete>
<p:commandLink id="#{cc.attrs.id}BtTreeHierarquia"
title="Abrir árvore"
global="false"
onclick="PF('dlgSelecaoHierarquica').show();">
<h:graphicImage style="cursor: pointer; width: 20px;"
title="Abrir Árvore"
library="imagens"
name="hierarchy.svg" />
</p:commandLink>
</h:panelGrid>
</h:panelGrid>
<h:panelGrid id="#{cc.attrs.id}GrdIncremental" columns="1" rendered="#{cc.attrs.mb.renderIncremental}">
<p:outputLabel value="#{cc.attrs.mb.labelClasseLocal}" />
<p:autoComplete value="#{cc.attrs.mb.locaisClasseSelecionados}"
scrollHeight="200"
scrollable="true"
multiple="true"
styleClass="ui-autocomp"
id="#{cc.attrs.id}ACPreFiltro" var="local"
completeMethod="#{cc.attrs.mb.completarClasseLocalizacao}"
itemLabel="#{local.cdLocalCompleto}"
itemValue="#{local}"
minQueryLength="#{cc.attrs.minQueryLength}"
converter="#{localizacaoTOPreFiltroConverter}"
emptyMessage="Não existem dados para apresentar."
queryDelay="#{cc.attrs.queryDelay}"
forceSelection="true"
>
<p:ajax event="itemSelect"
listener="#{cc.attrs.mb.handleSelectClasseLocalizacao}"
update="@parent" />
<p:ajax event="itemUnselect"
update="@parent"
listener="#{cc.attrs.mb.handleUnSelectClasseLocalizacao}"/>
<f:facet name="itemtip">
<h:panelGrid columns="2" cellpadding="5" styleClass="itemTips">
<f:facet name="header">
<h:outputText value="Hierarquia " />
<br />
<h:outputText value="#{local.hierarquia}" />
</f:facet>
</h:panelGrid>
</f:facet>
</p:autoComplete>
<p:autoComplete id="#{cc.attrs.id}ACFiltro" scrollHeight="200"
scrollable="true" styleClass="ui-autocomp" var="local"
itemValue="#{local}" itemLabel="#{local.cdLocalCompleto}"
value="#{cc.attrs.mb.locaisSelecionados}" multiple="true"
minQueryLength="#{cc.attrs.minQueryLength}"
queryDelay="#{cc.attrs.queryDelay}"
completeMethod="#{cc.attrs.mb.completarLocais}"
converter="#{localizacaoTOFiltroConverter}"
emptyMessage="Não existem dados para apresentar."
forceSelection="true">
<c:choose>
<c:when test="#{cc.attrs.mb.realizaAcaoAdicionalAposSelecao}">
<p:ajax event="itemSelect"
listener="#{cc.attrs.mb.handleSelectLocalizacao}"
update="@this"
oncomplete="complementar();" />
</c:when>
<c:otherwise>
<p:ajax event="itemSelect"
listener="#{cc.attrs.mb.handleSelectLocalizacao}"
update="@this" />
</c:otherwise>
</c:choose>
<f:facet name="itemtip">
<h:panelGrid columns="2" cellpadding="5" styleClass="itemTips">
<f:facet name="header">
<h:outputText value="Hierarquia" />
<br />
<h:outputText value="#{local.hierarquia}" />
</f:facet>
</h:panelGrid>
</f:facet>
</p:autoComplete>
</h:panelGrid>
</p:panelGrid>
<p:dialog header="Busca Hierarquica"
id="#{cc.attrs.id}ModalTree"
widgetVar="dlgSelecaoHierarquica"
showEffect="fade"
hideEffect="fade"
closeOnEscape="true"
modal="#{cc.attrs.bloqueiaModal}"
height="400px"
width="500px">
<h:panelGrid columns="2">
<c:choose>
<c:when test="#{cc.attrs.mb.realizaAcaoAdicionalAposSelecao}">
<p:commandButton id="#{cc.attrs.id}btnSelecao" value="Selecionar e Voltar" action="#{cc.attrs.mb.selecionarLocalHierarquico}"
update="@(.#{cc.attrs.id}-auto-complete)"
onsuccess="bloqueiaAutoMulti();"
oncomplete="complementar();"/>
</c:when>
<c:otherwise>
<p:commandButton id="#{cc.attrs.id}btnSelecao" value="Selecionar e Voltar" action="#{cc.attrs.mb.selecionarLocalHierarquico}"
update="@(.#{cc.attrs.id}-auto-complete)" oncomplete="bloqueiaAutoMulti();"/>
</c:otherwise>
</c:choose>
<p:commandButton value="Voltar" type="button" onclick="PF('dlgSelecaoHierarquica').hide();" />
</h:panelGrid>
<p:scrollPanel style="width:100%;height:350;" mode="native">
<p:tree id="#{cc.attrs.id}Tree"
style="width:100%;height:100%;"
styleClass="estilo-arvore"
value="#{cc.attrs.mb.arvoreHierarquica}"
var="local"
selectionMode="multiple"
dynamic="true"
animate="true">
<p:ajax event="select" listener="#{cc.attrs.mb.onNodeSelect}" update="@this"/>
<p:treeNode >
<h:outputText value="#{local.cdClasseLocal}: #{local.cdLocalizacao} (#{local.niveis})" />
</p:treeNode>
</p:tree>
</p:scrollPanel>
</p:dialog>
<script>
bloqueiaAutoMulti();
</script>
</cc:implementation>
</html>