4

У меня есть управляемый бин CDI (bean, аннотированный с @Named, который используется в JSF), в который вводится бит состояния Sessionful Session. Этот сеансовый компонент похож на службу, у него есть менеджер сущностей (аннотируется с @PersistenceContext (type = PersistenceContextType.EXTENDED)) и выставляет методы прихода для управления некоторыми объектами. Эти объекты находятся на управляемом компоненте, который является ConversationScoped. Затем JSF вызывает метод управляемого компонента, а управляемый компонент вызывает некоторый метод «службы» (сеансовый компонент состояния). Я не знаю, был ли это лучший дизайн, но он работал хорошо. Но есть Сущность, у которой есть некоторые коллекции, которые нужно получить с LAZY. И в первый раз, когда я открываю страницу, она работает хорошо, но когда я пытаюсь нажать любую кнопку или сделать какое-либо действие, у меня есть исключение LazyInitializationException. У кого-нибудь есть подсказка? Я не знаю, если что-то не так. Я поставил сессионный bean-компонент как stateful и расширенный контекст persistence. Этот сеансовый компонент вводится внутри управляемого компонента, который имеет сущности. Почему это бросает это исключение? Как может быть закрыт менеджер объекта?LazyInitializationException с управляемым бином бина и активным сеансом связи с CDI

Это код объекта, который находится в беде:

@Entity 
public class ParametrosVingentes implements Serializable { 

    public static final String ID = "settings"; 

    private static final long serialVersionUID = 1L; 

    @Id 
    private String id; 
    @OneToOne 
    private ValorHora valorHora; 
    @OneToMany 
    @JoinTable(
      name="BuscaSistecVingentes", 
      joinColumns = @JoinColumn(name="parametros_vingentes_fk"), 
      inverseJoinColumns = @JoinColumn(name="agendamento_fk") 
    ) 
    private List<AgendamentoBuscaSistec> agendamentosBuscaSistec; 
    @OneToMany 
    @JoinTable(
      name="ExportacaoZeusVingentes", 
      joinColumns = @JoinColumn(name="parametros_vingentes_fk"), 
      inverseJoinColumns = @JoinColumn(name="agendamento_fk") 
    ) 
    private List<AgendamentoExportacaoZeus> agendamentosExportacaoZeus; 
    @OneToMany 
    @JoinTable(
      name="ImportacaoZeusVingentes", 
      joinColumns = @JoinColumn(name="parametros_vingentes_fk"), 
      inverseJoinColumns = @JoinColumn(name="agendamento_fk") 
    ) 
    private List<AgendamentoImportacaoZeus> agendamentosImportacaoZeus; 

    public ParametrosVingentes() { 
    this.id = ID; 
    } 
// getters and setters... 

Это Stateful Session Bean:

@Stateful 
@LocalBean 
@TransactionAttribute(TransactionAttributeType.REQUIRED) 
public class ParametrosService implements Serializable { 

    @PersistenceContext(type= PersistenceContextType.EXTENDED) 
    private EntityManager entityManager; 

    public void cadastrar(ValorHora valorHora){ 
     ValorHoraDao valorHoraDao = new ValorHoraDao(entityManager); 
     valorHoraDao.salvar(valorHora); 
    } 

    @TransactionAttribute(TransactionAttributeType.SUPPORTS) 
     public List<ValorHora> listarValorHora(){ 
     ValorHoraDao valorHoraDao = new ValorHoraDao(entityManager); 
     return valorHoraDao.getAll(); 
    } 

    public boolean excluir(ValorHora valorHora){ 
     if(valorHora.getRemessas() != null && !valorHora.getRemessas().isEmpty()){ 
      return false; 
     } 
     ValorHoraDao valorHoraDao = new ValorHoraDao(entityManager); 
     valorHoraDao.remover(valorHora); 
     return true; 
    } 

    public void cadastrar(AgendamentoBuscaSistec agendamentoBuscaSistec){ 
     AgendamentoBuscaSistecDao agendamentoBuscaSistecDao = new AgendamentoBuscaSistecDao(entityManager); 
     agendamentoBuscaSistecDao.salvar(agendamentoBuscaSistec); 
    } 

    @TransactionAttribute(TransactionAttributeType.SUPPORTS) 
    public List<AgendamentoBuscaSistec> listarAgendamentoBuscaSistec(){ 
     AgendamentoBuscaSistecDao agendamentoBuscaSistecDao = new AgendamentoBuscaSistecDao(entityManager); 
     return agendamentoBuscaSistecDao.getAgendamentos(); 
    } 

    public void excluir(AgendamentoBuscaSistec agendamentoBuscaSistec){ 
     AgendamentoBuscaSistecDao agendamentoBuscaSistecDao = new AgendamentoBuscaSistecDao(entityManager); 
     agendamentoBuscaSistecDao.remover(agendamentoBuscaSistec); 
    } 

    public void cadastrar(AgendamentoExportacaoZeus agendamentoExportacaoZeus){ 
     AgendamentoExportacaoZeusDao agendamentoExportacaoZeusDao = new AgendamentoExportacaoZeusDao(entityManager); 
     agendamentoExportacaoZeusDao.salvar(agendamentoExportacaoZeus); 
    } 

    @TransactionAttribute(TransactionAttributeType.SUPPORTS) 
     public List<AgendamentoExportacaoZeus> listarAgendamentoExportacaoZeus(){ 
     AgendamentoExportacaoZeusDao agendamentoExportacaoZeusDao = new AgendamentoExportacaoZeusDao(entityManager); 
     return agendamentoExportacaoZeusDao.getAgendamentos(); 
    } 

    public void excluir(AgendamentoExportacaoZeus agendamentoExportacaoZeus){ 
     AgendamentoExportacaoZeusDao agendamentoExportacaoZeusDao = new AgendamentoExportacaoZeusDao(entityManager); 
     agendamentoExportacaoZeusDao.remover(agendamentoExportacaoZeus); 
    } 

    public void cadastrar(AgendamentoImportacaoZeus agendamentoImportacaoZeus){ 
     AgendamentoImportacaoZeusDao agendamentoImportacaoZeusDao = new AgendamentoImportacaoZeusDao(entityManager); 
     agendamentoImportacaoZeusDao.salvar(agendamentoImportacaoZeus); 
    } 

    @TransactionAttribute(TransactionAttributeType.SUPPORTS) 
    public List<AgendamentoImportacaoZeus> listarAgendamentoImportacaoZeus(){ 
     AgendamentoImportacaoZeusDao agendamentoImportacaoZeusDao = new AgendamentoImportacaoZeusDao(entityManager); 
     return agendamentoImportacaoZeusDao.getAgendamentos(); 
    } 

    public void excluir(AgendamentoImportacaoZeus agendamentoImportacaoZeus){ 
     AgendamentoImportacaoZeusDao agendamentoImportacaoZeusDao = new AgendamentoImportacaoZeusDao(entityManager); 
     agendamentoImportacaoZeusDao.remover(agendamentoImportacaoZeus); 
    } 

    @TransactionAttribute(TransactionAttributeType.SUPPORTS) 
    public ParametrosVingentes getParametrosVingentes(){ 
     return ParametrosUtil.getParametrosVingentes(entityManager); 
    } 

    public void atualizarParametrosVingentes(ParametrosVingentes parametrosVingentes){ 
     ParametrosVingentesDao parametrosVingentesDao = new ParametrosVingentesDao(entityManager); 
     parametrosVingentes = parametrosVingentesDao.atualizar(parametrosVingentes); 
    } 

} 

управляемый компонент вызывает метод getParametrosVingentes() из сессионного компонента , Я использую статический метод ParametrosUtil для получения (если он существует) или создания (если он не существует) параметра ParametrosVingentes. Это связано с тем, что в приложении есть только один ParametrosVingentes. Это компонент, который имеет параметры, используемые другими компонентами. Это код ParametrosUtil:

public class ParametrosUtil { 

    public static synchronized ParametrosVingentes getParametrosVingentes(EntityManager entityManager){ 
     ParametrosVingentesDao parametrosVingentesDao = new ParametrosVingentesDao(entityManager); 
     ParametrosVingentes parametrosVingentes = parametrosVingentesDao.buscar(ParametrosVingentes.ID); 
     if(parametrosVingentes == null){ 
      parametrosVingentes = new ParametrosVingentes(); 
     } 
     return parametrosVingentes; 
    } 

    public static synchronized ParametrosVingentes atualizarParametrosVingentes(ParametrosVingentes parametrosVingentes, EntityManager entityManager){ 
     ParametrosVingentesDao parametrosVingentesDao = new ParametrosVingentesDao(entityManager); 
     return parametrosVingentesDao.atualizar(parametrosVingentes); 
    } 
} 

Это управляемый компонент:

@Named(value = "parametros") 
@ConversationScoped 
public class Parametros implements Serializable { 

    public static final int VISAO_PARAMETROS_VINGENTES = 1; 
    public static final int VISAO_VALOR_HORA = 2; 
    public static final int VISAO_AGENDAMENTO_SISTEC = 3; 
    public static final int VISAO_AGENDAMENTO_EXPORTACAO_ZEUS = 4; 
    public static final int VISAO_AGENDAMENTO_IMPORTACAO_ZEUS = 5; 

    private int visaoAtual; 

    @EJB 
    private ParametrosService parametrosService; 

    @Inject 
    private Conversation conversation; 

    private ValorHora valorHora; 
    private AgendamentoBuscaSistec agendamentoBuscaSistec; 
    private AgendamentoExportacaoZeus agendamentoExportacaoZeus; 
    private AgendamentoImportacaoZeus agendamentoImportacaoZeus; 

    private List<ValorHora> listaValorHora; 
    private boolean listaValorHoraModificada; 
    private List<AgendamentoBuscaSistec> listaAgendamentoBuscaSistec; 
    private boolean listaAgendamentoBuscaSistecModificada; 
    private List<AgendamentoExportacaoZeus> listaAgendamentoExportacaoZeus; 
    private boolean listaAgendamentoExportacaoZeusModificada; 
    private List<AgendamentoImportacaoZeus> listaAgendamentoImportacaoZeus; 
    private boolean listaAgendamentoImportacaoZeusModificada; 

    private ParametrosVingentes parametrosVingentes; 

    public Parametros() { 
     this.visaoAtual = VISAO_PARAMETROS_VINGENTES; 
    } 

    @PostConstruct 
    public void init(){ 
     this.conversation.begin(); 
     this.parametrosVingentes = this.parametrosService.getParametrosVingentes();  
    } 

    public ParametrosVingentes getParametrosVingentes() { 
     return parametrosVingentes; 
    } 

    public List<ValorHora> getListaValorHora(){ 
     if(this.listaValorHora == null || this.listaValorHoraModificada){ 
      this.listaValorHoraModificada = false; 
      this.listaValorHora = this.parametrosService.listarValorHora(); 
     } 
     return this.listaValorHora; 
    } 

    public List<AgendamentoBuscaSistec> getListaAgendamentoBuscaSistec(){ 
     if(this.listaAgendamentoBuscaSistec == null || this.listaAgendamentoBuscaSistecModificada){ 
      this.listaAgendamentoBuscaSistecModificada = false; 
      this.listaAgendamentoBuscaSistec = this.parametrosService.listarAgendamentoBuscaSistec(); 
     } 
     return this.listaAgendamentoBuscaSistec; 
    } 

    public List<AgendamentoExportacaoZeus> getListaAgendamentoExportacaoZeus(){ 
     if(this.listaAgendamentoExportacaoZeus == null || this.listaAgendamentoExportacaoZeusModificada){ 
      this.listaAgendamentoExportacaoZeusModificada = false; 
      this.listaAgendamentoExportacaoZeus = this.parametrosService.listarAgendamentoExportacaoZeus(); 
     } 
     return this.listaAgendamentoExportacaoZeus; 
    } 

    public List<AgendamentoImportacaoZeus> getListaAgendamentoImportacaoZeus(){ 
     if(listaAgendamentoImportacaoZeus == null || this.listaAgendamentoImportacaoZeusModificada){ 
      this.listaAgendamentoImportacaoZeusModificada = false; 
      this.listaAgendamentoImportacaoZeus = this.parametrosService.listarAgendamentoImportacaoZeus(); 
     } 
     return this.listaAgendamentoImportacaoZeus; 
    } 

    public void atualizarParametrosVingentes(){ 
     this.parametrosService.atualizarParametrosVingentes(this.parametrosVingentes); 
    } 

    // Other methods 

И это JSF:

<p:fieldset> 
    <h:panelGrid columns="2"> 
     <h:outputLabel value="Valor da hora:" for="valorHoraVingente" /> 
     <p:selectOneMenu id="valorHoraVingente" value="#{parametros.parametrosVingentes.valorHora}"> 
      <f:selectItem itemLabel="Selecione" itemValue="#{null}" /> 
      <f:selectItems value="#{parametros.listaValorHora}" /> 
     </p:selectOneMenu> 
     <h:outputLabel value="Agendamento da Busca do Sistec:" for="agendamentoBuscaSistecVingente" /> 
     <p:selectManyCheckbox id="agendamentoBuscaSistecVingente" value="#{parametros.parametrosVingentes.agendamentosBuscaSistec}"> 
      <f:selectItem itemLabel="Selecione" itemValue="#{null}" /> 
      <f:selectItems value="#{parametros.listaAgendamentoBuscaSistec}" /> 
     </p:selectManyCheckbox> 
     <h:outputLabel value="Agendamento da Exportação para o Zeus:" for="agendamentoExportacaoZeusVingente" /> 
     <p:selectManyCheckbox id="agendamentoExportacaoZeusVingente" value="#{parametros.parametrosVingentes.agendamentosExportacaoZeus}"> 
      <f:selectItem itemLabel="Selecione" itemValue="#{null}" /> 
      <f:selectItems value="#{parametros.listaAgendamentoExportacaoZeus}" /> 
     </p:selectManyCheckbox> 
     <h:outputLabel value="Agendamento da Importação para o Zeus:" for="agendamentoImportacaoZeusVingente" /> 
     <p:selectManyCheckbox id="agendamentoImportacaoZeusVingente" value="#{parametros.parametrosVingentes.agendamentosImportacaoZeus}"> 
      <f:selectItem itemLabel="Selecione" itemValue="#{null}" /> 
      <f:selectItems value="#{parametros.listaAgendamentoImportacaoZeus}" /> 
     </p:selectManyCheckbox> 
    </h:panelGrid> 
    <p:commandButton value="Atualizar" action="#{parametros.atualizarParametrosVingentes}" update="@form" /> 
</p:fieldset> 

Как вы можете видеть, что есть поля связываются с коллекции, которые должны быть получены с LAZY.

И это трассировка стека:

WARNING: failed to lazily initialize a collection, no session or session was closed 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed 
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383) 
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375) 
    at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122) 
    at org.hibernate.collection.PersistentBag.isEmpty(PersistentBag.java:255) 
    at javax.faces.component.UIInput.isEmpty(UIInput.java:1257) 
    at javax.faces.component.UIInput.validateValue(UIInput.java:1144) 
    at javax.faces.component.UISelectMany.validateValue(UISelectMany.java:581) 
    at javax.faces.component.UIInput.validate(UIInput.java:967) 
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1233) 
    at javax.faces.component.UIInput.processValidators(UIInput.java:698) 
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) 
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) 
    at org.primefaces.component.fieldset.Fieldset.processValidators(Fieldset.java:197) 
    at javax.faces.component.UIForm.processValidators(UIForm.java:253) 
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) 
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) 
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1172) 
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) 
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655) 
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595) 
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98) 
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162) 
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231) 
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174) 
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828) 
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725) 
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019) 
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) 
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) 
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) 
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) 
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) 
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) 
    at java.lang.Thread.run(Thread.java:722) 

Я думаю, что в конце метода getParametrosVingentes службы, то EntityManager ясно и все объекты отсоединяются. Это может быть проблема?

Я запускаю это на Glassfish 3, используя Mojarra 2.1.2 и EJB 3.1. Спасибо за любую помощь.

+0

Я думаю, что некоторые из «других методов» в 'Parametros' здесь важны, в частности,' atualizarParametrosVingentes'. Кроме того, поскольку ошибка во время проверки выбора, код, который управляет списком параметров ('listaValorHora' и т. Д.), Может быть важен. Наконец, будьте осторожны, когда вы начинаете разговор. См. Http://stackoverflow.com/questions/8552478/conversation-not-propagated-automatically-on-form-submission. – Brian

+0

@Brian Я отправил код, который вы задали. Я отлаживал управляемый компонент, и он просто вызывает метод init (аннотируется с PostContruct, где начинается разговор) один раз. И разговор, похоже, в порядке. Но когда я попытался управлять собой EntityManager, произошли те же самые erros. Я также тестировал SessionBean, чтобы убедиться, что это не спасло состояние, но это было так. Тогда я не знаю, в чем проблема. –

ответ

19

Ну, я, наконец, решил проблему! Я видел, что LazyInitializationException было на этапе проверки selectManyCheckbox. Затем я начал поиск по этой ссылке и нашел эту ссылку: http://old.nabble.com/-jira---Created--(MYFACES-3306)-%3Ch%3AselectManyCheckBox%3E-%2B-JPA-with-Hibernate-creates-Hibernate-PersistentCollection-where-it-should-not.-Causes-td32463262.html

Проблема заключалась в том, что JSF пытался использовать PersistentBag, созданный Hibernate, но не использовал его. Решение было положено atributte, говорящему JSF использовать ArrayList вместо PersistentBag.

Это может быть сделано путем добавления этого внутри selectManyCheckbox:

<f:attribute name="collectionType" value="java.util.ArrayList" /> 
+1

спасибо :-) Помогло мне много – ke3pup

+0

Добро пожаловать. :) –