EntityManager 未注入无状态会话 Bean

EntityManager not injected in Stateless Session Bean

我一直在浏览很多类似的问题,但没有反映出我的确切问题。如果我忽略了有人已经解决了这个问题,请告诉我。

我目前正在将 JBoss 3.x 上的旧 EJB 2.1 应用程序迁移到 JBoss 7.x 上的 EJB 3.x。由于应用程序客户端和服务器之间通信的变化,我创建了一个小的测试客户端来检查陷阱。

其中之一是我的无状态会话 bean 中的 entitymanager 没有注入,使 EntityManager 为空。我尝试使用 EntityManagerFactory 解决这个问题,但都没有注入。 引用的数据源可用并且已针对数据库测试连接。

我希望你们中的一些人遇到过这个问题,可以想到下一步我可以看哪里或者我可以做些什么来追踪这个问题。 附上服务器端的persistence.xml、RemoteInterface和Bean代码以及我的测试客户端代码。

如果我能提供更多信息,请告诉我。 (如果您想知道,类 大部分都保留了 EJB 2 应用程序中的名称)。

无状态会话 Bean (GUITabUsersDao):

@Stateless
@Remote(GUITabUsersDaoRemote.class)
public class GUITabUsersDao implements GUITabUsersDaoRemote {
    Logger logger = Logger.getLogger(GUITabUsersDao.class.getName());

    @PersistenceContext(name = "OracleGUIDS", type =   PersistenceContextType.TRANSACTION)
    EntityManager entityManager;

    @Override
    public List<GUITabUsers> findAll() throws FinderException {
         List<GUITabUsers> resultList = null;
         TypedQuery<GUITabUsers> namedQuery;
         if (entityManager == null) {
             logger.severe("**** CKU: This is not going to end well. entitymanager is null. :( ****");
         } else {
            namedQuery = entityManager.createNamedQuery(GUITabUsers.FIND_ALL, GUITabUsers.class);
            resultList = namedQuery.getResultList();
        }
        return resultList;
    }
}

远程接口

public interface GUITabUsersDaoRemote {
    List<GUITabUsers> findAll() throws FinderException;
}

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="OracleGUIDS" transaction-type="JTA">
        <jta-data-source>java:jboss/datasources/OracleGUIDS</jta-data-source>
        <class>de.printcom.loginmodule.GUITabUsers</class>
        <properties>
            <!-- Properties for Hibernate  -->
            <property name="hibernate.hbm2ddl.auto" value="verify"/>
            <property name="hibernate.show_sql" value="false"/>
        </properties>
    </persistence-unit>
</persistence>

客户端代码

package de.my.test;

public class TestClient {
    public static final String URL = "localhost";
    public static final String PORT = "4447";

    private static final Logger LOGGER = Logger.getLogger(TestClient.class.getName());

    public static void main(String[] args) {
        IDPLookupRemote bean;
        LAEC_MachineControlSES bean2;
        GUITabUsersDaoRemote guiTabUsersDao;
        try {
            EJBHomeFactory factory = EJBHomeFactory.getInstance(URL, PORT);
            guiTabUsersDao = (GUITabUsersDaoRemote) lookup("GUITabUsersDao", GUITabUsersDaoRemote.class);
            LOGGER.info("Bean '" + guiTabUsersDao.toString() + "' received.");
            List<GUITabUsers> col = null;
            try {
                col = guiTabUsersDao.findAll();
            } catch (FinderException | NullPointerException e) {
                e.printStackTrace();
            }
            if (null != col) {
                LOGGER.info(col.get(0).toString());
            } else {
                LOGGER.info("Col is empty!");
            }
        } catch (NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static Object lookup(String jndiName, Class<?> remoteInterfaceClass) throws NamingException {
        Object object = new Object();
        try {
            Properties properties = new Properties();
            properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
            properties.put("jboss.naming.client.ejb.context", true);
            properties.put(Context.PROVIDER_URL, "remote://" + URL + ":" + PORT);
            Context context = new InitialContext(properties);
            final String appName = "appName";
            final String moduleName = "moduleName";
            final String distinctName = "";
            final String beanName = jndiName;
            final String viewClassName = remoteInterfaceClass.getName();
            LOGGER.info("Looking EJB via JNDI ");
            String jndiLookupName = appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName;
            LOGGER.info(jndiLookupName);
            object = context.lookup(jndiLookupName);
            LOGGER.info("Calling 'context.lookup(" + jndiLookupName + ")'");
            // object = context.lookup(jndiName);
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return object;
    }
}

根据 BalusC 和 jgitter 的建议,这是我之前编辑的答案:

如果您遇到类似的问题,请随时为下面提到的问题沐浴在我的愚蠢之中。

在我需要从 JBoss 3.x 迁移到 7.x 的应用程序中,许多项目被放在一起。其中一个项目在 persistence.xml 中声明了两个持久性单元,而无状态会话 Bean 的声明都与此类似:

@Stateless
@Remote(SomeStatelessRemote.class)
public class SomeStatelessBean implements SomeStatelessRemote {

    @PersistenceContext(name = "OracleGUIDS")
    EntityManager entitymanager;
    ...
}

现在如果你部署它,你会收到错误消息

JBAS011470: Persistence unitName was not specified

在某些论坛中,有人建议禁用独立版中的特定子系统

<subsystem xmlns="urn:jboss:domain:jpa:1.1">
   <jpa default-datasource="" default-extended-persistence-inheritance="DEEP"/>
</subsystem>

如您所见,这将完全禁用任何使用 JPA 的可能性。

现在我启用了子系统并使用正确的语法注入实体管理器:

@Stateless
@Remote(SomeStatelessRemote.class)
public class SomeStatelessBean implements SomeStatelessRemote {

    @PersistenceContext(unitName= "OracleGUIDS")
    EntityManager entitymanager;
    ...
}

而且,哦,奇迹,我能够访问 entitymanager 并使用它。 感谢大家绞尽脑汁帮助我。 希望这篇文章能帮助您避免这个错误。