Java EE - 通过 Glassfish 资源将 EJB 连接到 Oracle 数据库
Java EE - Connect EJB to Oracle Database through Glassfish resource
我是 Java 的新手,尤其是 EE。我启动了一个 EE 项目,该项目应提供 REST API,它将处理远程 Oracle 数据库中的 2 个实体。我正在使用 NetBeans,因为它是在 Enterprise Java 中完成任何事情的唯一方法(如我现在所见)。
我做了什么:
- 我在 Glassfish (v4.1-13) 中创建了 JDBC 池。我可以成功 ping 池。然后我为池创建了 JDBC 资源。
- 我为我需要处理的两个实体生成了实体 classes。
<persistence version="2.1" xmlns...>
<persistence-unit name="semestralka-ejbPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/dbs</jta-data-source>
<class>cz.ctu.bitjv.kopecj24.semestralka.entities.Food</class>
<class>cz.ctu.bitjv.kopecj24.semestralka.entities.User</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database" value="Oracle"/>
</properties>
</persistence-unit>
</persistence>
- 我有一个无状态 EJB,它像这样调用实体管理器:
public FoodServiceBean()
{
this.facade = new FoodFacade(Food.class);
this.facade.setEntityManager(Persistence.createEntityManagerFactory("semestralka-ejbPU").createEntityManager());
}
然后,有一个 REST 服务 class 应该列出数据库中的实体。
@Path("food")
public class 食物资源 {
@Context
private UriInfo context;
private FoodServiceInterface service;
/**
* Creates a new instance of FoodResource
*/
public FoodResource() {
try {
InitialContext ic = new InitialContext();
service = (FoodServiceInterface) ic.lookup("java:global/semestralka/semestralka-ejb/FoodServiceBean");
} catch (NamingException ex) {...}
}
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("list")
public String getAll() {
List<Food> foods = service.listAllFood();
...
}
}
不幸的是,一旦我请求 getAll 操作(访问 localhost:8080/semestralka-war/wr/food/list),我得到这个异常:
Warning: StandardWrapperValve[cz.ctu.bitjv.kopecj24.semestralka.rest.ApplicationConfig]: Servlet.service() for servlet cz.ctu.bitjv.kopecj24.semestralka.rest.ApplicationConfig threw exception
javax.naming.NameNotFoundException: dbs not found
这是异常屏幕的屏幕截图:
仔细检查持久性单元和 glassfish 服务器中的连接池名称。你也可以用实体更新你的问题。
我可以看到你从 rest 服务调用的 ejb 是错误的。您需要添加带有包路径的远程接口名称。
假设您的包路径是 com.rs.www 那么您的查找字符串应该是以下一个:
service = (FoodServiceInterface) ic.lookup("java:global/semestralka/semestralka-ejb/FoodServiceBean!com.rs.www.FoodServiceInterface");
谢谢。
终于,我找到了解决办法。问题出在我的 FoodServiceBean 中。我试图在 EJB 构造函数中实例化外观,但 EntityManager 是在构造函数之后注入的。所以这是帮助我解决问题的 Bean 代码。
@Stateless
@EJB(beanInterface=FoodServiceInterface.class, name="FoodServiceBean")
public class FoodServiceBean implements FoodServiceInterface {
@PersistenceContext(unitName="testPU")
private EntityManager em;
private FoodFacade facade;
public FoodServiceBean()
{
}
@PostConstruct
public void init() {
this.facade = new FoodFacade(Food.class);
this.facade.setEntityManager(em);
}
请注意,我更改了持久性单元的名称只是为了确保没有拼写错误。
感谢您的帮助。
我是 Java 的新手,尤其是 EE。我启动了一个 EE 项目,该项目应提供 REST API,它将处理远程 Oracle 数据库中的 2 个实体。我正在使用 NetBeans,因为它是在 Enterprise Java 中完成任何事情的唯一方法(如我现在所见)。
我做了什么:
- 我在 Glassfish (v4.1-13) 中创建了 JDBC 池。我可以成功 ping 池。然后我为池创建了 JDBC 资源。
- 我为我需要处理的两个实体生成了实体 classes。
<persistence version="2.1" xmlns...>
<persistence-unit name="semestralka-ejbPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/dbs</jta-data-source>
<class>cz.ctu.bitjv.kopecj24.semestralka.entities.Food</class>
<class>cz.ctu.bitjv.kopecj24.semestralka.entities.User</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database" value="Oracle"/>
</properties>
</persistence-unit>
</persistence>
- 我有一个无状态 EJB,它像这样调用实体管理器:
public FoodServiceBean()
{
this.facade = new FoodFacade(Food.class);
this.facade.setEntityManager(Persistence.createEntityManagerFactory("semestralka-ejbPU").createEntityManager());
}
然后,有一个 REST 服务 class 应该列出数据库中的实体。
@Path("food") public class 食物资源 {
@Context private UriInfo context; private FoodServiceInterface service; /** * Creates a new instance of FoodResource */ public FoodResource() { try { InitialContext ic = new InitialContext(); service = (FoodServiceInterface) ic.lookup("java:global/semestralka/semestralka-ejb/FoodServiceBean"); } catch (NamingException ex) {...} } @GET @Produces(MediaType.TEXT_PLAIN) @Path("list") public String getAll() { List<Food> foods = service.listAllFood(); ... }
}
不幸的是,一旦我请求 getAll 操作(访问 localhost:8080/semestralka-war/wr/food/list),我得到这个异常:
Warning: StandardWrapperValve[cz.ctu.bitjv.kopecj24.semestralka.rest.ApplicationConfig]: Servlet.service() for servlet cz.ctu.bitjv.kopecj24.semestralka.rest.ApplicationConfig threw exception
javax.naming.NameNotFoundException: dbs not found
这是异常屏幕的屏幕截图:
仔细检查持久性单元和 glassfish 服务器中的连接池名称。你也可以用实体更新你的问题。
我可以看到你从 rest 服务调用的 ejb 是错误的。您需要添加带有包路径的远程接口名称。
假设您的包路径是 com.rs.www 那么您的查找字符串应该是以下一个:
service = (FoodServiceInterface) ic.lookup("java:global/semestralka/semestralka-ejb/FoodServiceBean!com.rs.www.FoodServiceInterface");
谢谢。
终于,我找到了解决办法。问题出在我的 FoodServiceBean 中。我试图在 EJB 构造函数中实例化外观,但 EntityManager 是在构造函数之后注入的。所以这是帮助我解决问题的 Bean 代码。
@Stateless
@EJB(beanInterface=FoodServiceInterface.class, name="FoodServiceBean")
public class FoodServiceBean implements FoodServiceInterface {
@PersistenceContext(unitName="testPU")
private EntityManager em;
private FoodFacade facade;
public FoodServiceBean()
{
}
@PostConstruct
public void init() {
this.facade = new FoodFacade(Food.class);
this.facade.setEntityManager(em);
}
请注意,我更改了持久性单元的名称只是为了确保没有拼写错误。
感谢您的帮助。