2014-01-30 6 views
2

Я думаю, что я нашел ошибку во время выполнения Java с JSF 2.0 (с использованием Primefaces), в этом проекте я использую JSF 2.0 Primefaces и CDI.Список <Integer> принят Список <String>

Возобновление проблемы. У меня есть метод setter в моей бизнес-классе Роль, которая получила список, но JSF устанавливает для этого ArrayList. Должно ли java исключить или, по крайней мере, не найти метод, который соответствует? здесь:

public void setAcl(List<Integer> acl) { 
    this.acl = acl; 
    System.out.println("Received: " + this.acl); 
    for(Object i : this.acl) { 
     System.out.println(i.getClass() + " > " + i); 
    } 
} 

Выход этого метода:

 
Received: [1, 5] 
class java.lang.String > 1 
class java.lang.String > 5 

И когда я пытаюсь использовать в Еогеасп так:

for(Integer i : this.acl) { 
    System.out.println(i.getClass() + " > " + i); 
} 

Броски

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 

Можете ли вы объяснить, что здесь? Это ошибка в JSF или Java? Или меня неправильно поняли?

Сначала у меня есть UI JSF (.xhtml), который имеет p:selectManyCheckbox, этот manyCheckbox получает массив перечислений PontoSenha (используя значения метода перечисления()) из managedbean и определяет значения itemValue и itemLabel. Следуйте код manyCheckbox:

<p:selectManyCheckbox id="acl" value="#{roleController.role.acl}" layout="grid" columns="4" required="true" requiredMessage="Selecione pelo menos um ponto de senha" > 
    <f:selectItems value="#{roleController.pontosSenha}" var="pontoSenha" itemValue="#{pontoSenha.pontoSenha}" itemLabel="#{pontoSenha.descricao}" /> 
</p:selectManyCheckbox> 

Декларация перечислений PontoSenha:

package br.com.bsetechnology.atacadao.business; 
public enum PontoSenha { 
    CADASTRO_FORNECEDOR(1, "Cadastrar fornecedor"), 
    CADASTRO_LOJA(2, "Cadastrar loja"), 
    CADASTRO_PRODUTO(3, "Cadastrar produto"), 
    RELATORIO(4, "Gerar relatório"), 
    SEGURANCA_GRUPOS(5, "Gerenciar grupos de usuário"), 
    SEGURANCA_USUARIOS(6, "Gerenciar usuários"); 

    private int pontoSenha; 
    private String descricao; 

    private PontoSenha(int pontoSenha, String descricao) { 
     this.pontoSenha = pontoSenha; 
     this.descricao = descricao; 
    } 

    public int getPontoSenha() { 
     return pontoSenha; 
    } 

    public String getDescricao() { 
     return descricao; 
    } 

    @Override 
    public String toString() { 
     return String.format("%02d - %s", pontoSenha, descricao); 
    } 
} 

декларацию ManagedBean

package br.com.bsetechnology.atacadao.controller; 
import java.util.List; 
import javax.enterprise.context.RequestScoped; 
import javax.faces.application.FacesMessage; 
import javax.inject.Inject; 
import javax.inject.Named; 
import br.com.bsetechnology.atacadao.business.PontoSenha; 
import br.com.bsetechnology.atacadao.business.Role; 
import br.com.bsetechnology.atacadao.core.FacesUtil; 
import br.com.bsetechnology.atacadao.dao.RoleDAO; 

@Named("roleController") 
@RequestScoped 
public class RoleController { 

    @Inject 
    private RoleDAO roleDao; 
    private Role role; 

    public void setRoleDao(RoleDAO roleDao) { 
     this.roleDao = roleDao; 
    } 

    public Role getRole() { 
     if(role == null) 
      role = new Role(); 
     return role; 
    } 

    public void setRole(Role role) { 
     this.role = role; 
    } 

    public PontoSenha[] getPontosSenha() { 
     return PontoSenha.values(); 
    } 

    public List<Role> getAll() { 
     return roleDao.getAll(); 
    } 

    public void salva() { 
     System.out.println("Salvando"); 
     boolean resultAction = false; 

     if(role.getCodigo() > 0) { 
      resultAction = roleDao.update(role); 
     } else { 
      resultAction = roleDao.insert(role); 
     } 

     if(resultAction) { 
      role = new Role(); 
      FacesUtil.addMessage(FacesMessage.SEVERITY_INFO, "Grupo salvo com sucesso.", null); 
     } else { 
      FacesUtil.addMessage(FacesMessage.SEVERITY_WARN, "Grupo não foi salvo.", null); 
     } 
    } 
} 

Бизнес-класс Роль

package br.com.bsetechnology.atacadao.business; 
import java.util.ArrayList; 
import java.util.List; 

public class Role { 
    private int codigo; 
    private String descricao; 
    private List<Integer> acl; 

    public Role() { 
     acl = new ArrayList<Integer>(); 
    } 

    public Role(int codigo, String descricao, List<Integer> acl) { 
     setCodigo(codigo); 
     setDescricao(descricao); 
     setAcl(acl); 
    } 

    public int getCodigo() { 
     return codigo; 
    } 

    public void setCodigo(int codigo) { 
     this.codigo = codigo; 
    } 

    public String getDescricao() { 
     return descricao; 
    } 

    public void setDescricao(String descricao) { 
     this.descricao = descricao; 
    } 

    public List<Integer> getAcl() { 
     return acl; 
    } 

    public void setAcl(List<Integer> acl) { 
     this.acl = acl; 
     System.out.println("Received: " + this.acl); 
     for(Object i : this.acl) { 
      System.out.println(i.getClass() + " > " + i); 
     } 
    } 

    public void addPontoSenha(int pontoSenha) { 
     this.acl.add(pontoSenha); 
    } 

    public void remPontoSenha(int pontoSenha) { 
     this.acl.remove(pontoSenha); 
    } 
} 

для JSF страницы, которые я использую, чтобы зарегистрировать роли (template.xhtml только HTML и CSS):

<ui:composition template="/WEB-INF/template.xhtml" xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui"> 

    <ui:define name="body-content"> 
    <div class="row"> 
     <h:form id="formGrupo" class="form-horizontal"><fieldset> 
     <p:panel header="Edição de grupo de usuário" > 
      <div class="control-group"> 
       <h:outputLabel for="codigo" value="Código" readonly="" styleClass="control-label" /> 
       <div class="controls"> 
        <h:inputText id="codigo" class="form-control" value="#{roleController.role.codigo}" 
         style="width:100px;text-align:right;" /> 
       </div> 
      </div> 
      <div class="control-group"> 
       <h:outputLabel for="descricao" value="Descrição" styleClass="control-label" /> 
       <div class="controls"> 
        <h:inputText id="descricao" class="form-control" value="#{roleController.role.descricao}" 
         required="true" maxlength="20" requiredMessage="Descrição obrigatória" converterMessage="Descrição inválida" /> 
        <h:message for="descricao" class="error" /> 
       </div> 
      </div> 
      <div class="control-group"> 
       <h:outputLabel value="Pontos de senha" styleClass="control-label" /> 
       <div class="controls checkbox"> 
        <p:selectManyCheckbox id="acl" value="#{roleController.role.acl}" layout="grid" columns="4" 
         required="true" requiredMessage="Selecione pelo menos um ponto de senha" > 
         <f:selectItems value="#{roleController.pontosSenha}" var="pontoSenha" itemValue="#{pontoSenha.pontoSenha}" itemLabel="#{pontoSenha.descricao}" /> 
        </p:selectManyCheckbox> 
        <h:message for="acl" errorClass="error" /> 
       </div> 
      </div> 
      <div class="form-actions"> 
       <hr/> 
       <p:commandLink value="Salvar" styleClass="btn btn-primary" style="color:#fff;" action="#{roleController.salva}" update=":formGrupo,:formTable:tblRoles"> 
       </p:commandLink> 
      </div> 
      <p:messages globalOnly="true" showDetail="false" closable="true" /> 
     </p:panel> 
     </fieldset></h:form> 
    </div> 
    <br/> 
    <div class="row">    
     <h:form id="formTable" styleClass="form-horizontal"><fieldset> 
      <p:panel header="Grupos de usuários"> 
       <p:dataTable id="tblRoles" var="role" value="#{roleController.all}" rowKey="#{role.codigo}" stickheader="true" > 

        <p:column headerText="Código" width="20"> 
         <h:outputText value="#{role.codigo}" /> 
        </p:column> 
        <p:column headerText="Descrição"> 
         <h:outputText value="#{role.descricao}" /> 
        </p:column>     
        <p:column width="200">  
         <p:commandLink value="Editar" class="btn btn-success btn-sm" style="color:#fff;margin-left:5px;" update=":formGrupo"> 
          <f:setPropertyActionListener value="#{role}" target="#{roleController.role}" /> 
         </p:commandLink> 
         <p:commandLink value="Excluir" styleClass="btn btn-danger btn-sm" style="color:#fff;margin-left:5px;" /> 
        </p:column> 
       </p:dataTable> 

      </p:panel> 
     </fieldset></h:form> 
    </div> 
    </ui:define> 
</ui:composition> 

Полный стек печати след

Jan 29, 2014 10:59:43 PM com.sun.faces.context.AjaxExceptionHandlerImpl handlePartialResponseError 
SEVERE: javax.faces.component.UpdateModelException: javax.el.ELException: /seguranca/grupos.xhtml @27,87 value="#{roleController.role.acl}": Error writing 'acl' on type br.com.bsetechnology.atacadao.business.Role 
    at javax.faces.component.UIInput.updateModel(UIInput.java:867) 
    at javax.faces.component.UIInput.processUpdates(UIInput.java:749) 
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1286) 
    at org.primefaces.component.panel.Panel.processUpdates(Panel.java:288) 
    at javax.faces.component.UIForm.processUpdates(UIForm.java:281) 
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1286) 
    at javax.faces.component.UIComponentBase.processUpdates(UIComponentBase.java:1286) 
    at javax.faces.component.UIViewRoot.processUpdates(UIViewRoot.java:1254) 
    at com.sun.faces.lifecycle.UpdateModelValuesPhase.execute(UpdateModelValuesPhase.java:78) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:646) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at br.com.bsetechnology.atacadao.core.AccessControlFilter.doFilter(AccessControlFilter.java:31) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) 
    at java.lang.Thread.run(Thread.java:744) 
Caused by: javax.el.ELException: /seguranca/grupos.xhtml @27,87 value="#{roleController.role.acl}": Error writing 'acl' on type br.com.bsetechnology.atacadao.business.Role 
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:139) 
    at javax.faces.component.UIInput.updateModel(UIInput.java:832) 
    ... 30 more 
Caused by: javax.el.ELException: Error writing 'acl' on type br.com.bsetechnology.atacadao.business.Role 
    at javax.el.BeanELResolver.setValue(BeanELResolver.java:153) 
    at com.sun.faces.el.DemuxCompositeELResolver._setValue(DemuxCompositeELResolver.java:255) 
    at com.sun.faces.el.DemuxCompositeELResolver.setValue(DemuxCompositeELResolver.java:281) 
    at org.apache.el.parser.AstValue.setValue(AstValue.java:218) 
    at org.apache.el.ValueExpressionImpl.setValue(ValueExpressionImpl.java:253) 
    at org.jboss.weld.el.WeldValueExpression.setValue(WeldValueExpression.java:64) 
    at com.sun.faces.facelets.el.TagValueExpression.setValue(TagValueExpression.java:131) 
    ... 31 more 
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
    at br.com.bsetechnology.atacadao.business.Role.setAcl(Role.java:44) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at javax.el.BeanELResolver.setValue(BeanELResolver.java:142) 
    ... 37 more 
+0

Вы должны действительно уменьшить свой код и сосредоточиться на основах. Я попытался отредактировать подсветку синтаксиса, но сдался после 8 записей. – davidkonrad

+0

Извините. Я тоже пытался изменить, но XHTML не был отформатирован –

ответ

9

Это вызвано сочетанием нескольких технических ограничений и факты.

  • В Java дженерики составляют время синтаксического сахара. В конечном счете, когда класс Java скомпилирован, вся информация общего типа теряется. Таким образом, во время времени выполнения нет никаких сведений о каком-либо родовом типе в экземпляре .

  • Выражение языка (EL, #{}) выполняется во время выполнения с помощью Java Reflection API и видит в вашем конкретном случае только List, не List<Integer>.

  • Сгенерированный выход HTML и полученные параметры HTTP-запроса находятся в перспективе Java в основном String.

  • До тех пор, пока вы явно не указать JSF Converter между String до нужного типа, JSF позволит EL (читай: Reflection API) добавить непрореагировавшего представленный String значение в List.

Для того, чтобы получить поданную значение в конечном итоге, как Integer в модели, у вас есть 2 варианта:

  1. Явное задающие конвертер для String в Integer. К счастью, JSF имеет встроенный, IntegerConverter, который имеет идентификатор конвертера javax.faces.Integer. Поэтому все, что вам нужно сделать, это указать его в атрибуте входного компонента converter.

    <p:selectManyCheckbox ... converter="javax.faces.Integer"> 
    
  2. Использование Integer[] вместо List<Integer> как модель собственности.

    private Integer[] acl; 
    

    Таким образом, желаемый тип виден EL (см. Reflection API), и он будет выполнять автоматическое преобразование с использованием встроенного преобразователя.

+0

Правильно, я получил его. Большое спасибо!! Но об отражении во время выполнения это очень плохо, не так ли? Я имею в виду, что я мог бы использовать фреймворк, который использует коллекцию обобщений, и я мог бы использовать его неправильно, передавая некорректные коллекции, возможно, есть возможность разбить приложение, которое его использует. –

+0

Не уверен, что вы имеете в виду «очень плохо». Возможно, вы используете Java 1.2 на i586? – BalusC

Смежные вопросы