1

I recently switched from using JSF2 to using CDI/weld. I had 2 eager @ManagedBeans(eager=true) one of which has a list populated using a database query (JPA 2). It worked just fine.

I switched to CDI and refactored those beans using the technique described here http://ovaraksin.blogspot.com/2013/02/eager-cdi-beans.html. It works great for the bean whose list is manually populated during a @PostConstruct init(), but hangs on the bean whose list is populated be injecting a service which uses a database query.

It's hanging things up so badly I have to kill the server!

Why is that, and is there a way around it otheR than making that bean non-eager? I could make the bean "non-eager" if I have to. I'm just wondering what I'm misunderstand.

Here is the bean that is hanging and it's back end

OsList.java:

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

import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;

import org.jboss.logging.Logger;

@Eager
@ApplicationScoped
@Named
public class OsList {

    Logger log = Logger.getLogger(OsList.class);

    private List<String> osList = new ArrayList<String>();

    @Inject 
    OsListService osService;

    public OsList() {}

    @PostConstruct
    public void init(){
        log.info("Creating the one and only OsList bean");
        osList = osService.fetchOs();
    }

    public List<String> getOsList() {
        return osList;
    }

    public void setOsList(List<String> osList) {
        this.osList = osList;
    }

OsListService.java:

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

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.jboss.logging.Logger;

import dne.nmst.dac.model.Devices;
import dne.nmst.dac.model.Devices_;

@Stateless
public class OsListService {

    Logger log = Logger.getLogger(OsListService.class);

    @PersistenceContext
    EntityManager em;

    public List<String> fetchOs() {
        log.info("Do we ever get here?");
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<String> cq = cb.createQuery(String.class);
        Root<Devices> d = cq.from(Devices.class);

        cq.select(d.get(Devices_.os));
        cq.distinct(true);
        cq.orderBy(cb.asc(d.get(Devices_.os)));

        TypedQuery<String> q = em.createQuery(cq);

        List<String> iosList = new ArrayList<String>();
        iosList.add("");
        for (String s : q.getResultList()) {
            iosList.add(s);
        }
        return iosList;

    }

logfile

11:14:43,569 INFO  [org.jboss.as.server.deployment.scanner] (DeploymentScanner-threads - 1) JBAS015003: Found ond-cdi.war in deployment directory. To trigger deployment create a file called ond-cdi.war.dodeploy
11:14:43,590 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-8) JBAS015876: Starting deployment of "ond-cdi.war" (runtime-name: "ond-cdi.war")
11:14:45,330 INFO  [org.jboss.as.jpa] (MSC service thread 1-5) JBAS011401: Read persistence.xml for ond
11:14:45,731 INFO  [org.jboss.weld.deployer] (MSC service thread 1-7) JBAS016002: Processing weld deployment ond-cdi.war
11:14:45,781 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-7) JNDI bindings for session bean named OsListService in deployment unit deployment "ond-cdi.war" are as follows:

    java:global/ond-cdi/OsListService!gov.ssa.dne.nmst.service.OsListService
    java:app/ond-cdi/OsListService!gov.ssa.dne.nmst.service.OsListService
    java:module/OsListService!gov.ssa.dne.nmst.service.OsListService
    java:global/ond-cdi/OsListService
    java:app/ond-cdi/OsListService
    java:module/OsListService

11:14:45,781 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-7) JNDI bindings for session bean named DeviceService in deployment unit deployment "ond-cdi.war" are as follows:

    java:global/ond-cdi/DeviceService!gov.ssa.dne.nmst.service.DeviceService
    java:app/ond-cdi/DeviceService!gov.ssa.dne.nmst.service.DeviceService
    java:module/DeviceService!gov.ssa.dne.nmst.service.DeviceService
    java:global/ond-cdi/DeviceService
    java:app/ond-cdi/DeviceService
    java:module/DeviceService

11:14:46,071 INFO  [org.jboss.weld.deployer] (MSC service thread 1-7) JBAS016005: Starting Services for CDI deployment: ond-cdi.war
11:14:46,121 INFO  [org.jboss.weld.Version] (MSC service thread 1-7) WELD-000900 1.1.13 (redhat)
11:14:46,151 INFO  [org.jboss.weld.deployer] (MSC service thread 1-5) JBAS016008: Starting weld service for deployment ond-cdi.war
11:14:46,151 INFO  [org.jboss.as.jpa] (ServerService Thread Pool -- 48) JBAS011402: Starting Persistence Unit Service 'ond-cdi.war#ond'
11:14:46,281 INFO  [org.hibernate.annotations.common.Version] (ServerService Thread Pool -- 48) HCANN000001: Hibernate Commons Annotations {4.0.1.Final-redhat-2}
11:14:46,281 INFO  [org.hibernate.Version] (ServerService Thread Pool -- 48) HHH000412: Hibernate Core {4.2.0.Final-redhat-1}
11:14:46,281 INFO  [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 48) HHH000206: hibernate.properties not found
11:14:46,281 INFO  [org.hibernate.cfg.Environment] (ServerService Thread Pool -- 48) HHH000021: Bytecode provider name : javassist
11:14:46,301 INFO  [org.hibernate.ejb.Ejb3Configuration] (ServerService Thread Pool -- 48) HHH000204: Processing PersistenceUnitInfo [
    name: ond
    ...]
11:14:46,621 INFO  [org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator] (ServerService Thread Pool -- 48) HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider
11:14:46,842 INFO  [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 48) HHH000400: Using dialect: org.hibernate.dialect.MySQLInnoDBDialect
11:14:46,862 INFO  [org.hibernate.engine.transaction.internal.TransactionFactoryInitiator] (ServerService Thread Pool -- 48) HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory
11:14:46,862 INFO  [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (ServerService Thread Pool -- 48) HHH000397: Using ASTQueryTranslatorFactory
11:14:46,892 INFO  [org.hibernate.validator.internal.util.Version] (ServerService Thread Pool -- 48) HV000001: Hibernate Validator 4.3.1.Final-redhat-1
11:14:47,592 INFO  [org.jboss.solder.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Solder Config XML provider starting...
11:14:47,592 INFO  [org.jboss.solder.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Loading XmlDocumentProvider: org.jboss.solder.config.xml.bootstrap.ResourceLoaderXmlDocumentProvider
11:14:47,602 INFO  [org.jboss.solder.config.xml.bootstrap.XmlConfigExtension] (MSC service thread 1-6) Reading XML file: vfs:/D:/work/software/jboss-eap-6.1/standalone/deployments/ond-cdi.war/WEB-INF/beans.xml
11:14:47,612 INFO  [org.jboss.solder.Version] (MSC service thread 1-6) Solder 3.1.1.Final (build id: 3.1.1.Final)
11:14:48,422 INFO  [gov.ssa.dne.nmst.util.OsList] (MSC service thread 1-6) Creating the one and only OsList bean
april26
  • 833
  • 3
  • 14
  • 27

2 Answers2

0

One Possible way to circumvent the problem might be to use an Singleton-EJB with @Startup annotation instead. Not really solving the problem tho.

import javax.ejb.Singleton;
...

@Singleton
@Startup
public class OsListService {

    Logger log = Logger.getLogger(OsListService.class);

    @PersistenceContext
    EntityManager em;

    private List<String> iosList;

    @PostConstruct
    public void init() {


        this.iosList = ... //result from your query
    }

    public List<String> fetchOs() {
        return this.iosList;
    }
}
Aksel Willgert
  • 11,367
  • 5
  • 53
  • 74
  • This doesn't work either. It start OsListService, then starts OsList, and then creates OsListService again and then hangs somewhere in EnterpriseBeanProxyMethodHandler. Mainly out of curiosity I'm trying to figure out what exactly in the code is going on when it hangs. The server at this point requires a hard kill. Ugly. – april26 Jun 26 '13 at 12:17
0

Honestly, I don't know why you would do this. Part of CDI is that your beans don't live any longer than they need to. To easily migrate I'd simply find the correct scope (ApplicationScoped is typically the wrong scope) for your bean and do what you need to in a @PostConstruct method.

My guess as to what is happening is that you're hitting contention for when the EJB is created vs when the CDI bean needs to inject it and they're blocking each other. I don't have any hard evidence to support this though.

LightGuard
  • 5,298
  • 19
  • 19
  • That's what I ended up doing (ApplicationScoped/PostConstruct). I was mostly curious as to why it was hanging this hard. I was hoping to get some insight into how beans get created and in what order, etc. This is for a select list that shows up on the search page and gets reused every time anyone accesses the search page. Is that considered a good use of ApplicationScoped? – april26 Jun 27 '13 at 12:24
  • If you don't ever expect it to change throughout the whole life of the application (I'm considering an undeploy to be the end of life), yes you're fine. If that is not true, move it down to session. – LightGuard Jun 27 '13 at 22:05
  • The question about when beans are created is an implementation detail, it'll probably vary on every server. – LightGuard Jun 27 '13 at 22:06
  • Thanks. I realized it a bit belatedly that this was probably a server question more than anything. Some day I may take it up with the jboss community or redhat. – april26 Jun 28 '13 at 12:20