【问题标题】:Best way to interact with EJBs in Java EE在 Java EE 中与 EJB 交互的最佳方式
【发布时间】:2011-12-10 00:17:23
【问题描述】:

我有一个中等规模的 Java EE 6 项目,它使用多个 EJB,其中一个唯一目的是通过 JPA 管理数据库调用。我的问题是添加一个执行一些随机功能的新类然后调用数据库访问 EJB 以持久保存此类数据的最佳方法是什么。

如果这个新类需要访问注解和注入,它是否必须是 EJB?如果它必须与项目的其余部分一起部署,它是否必须是 EJB?

有人告诉我,如果您想在项目中添加一个新的逻辑类,它要么必须是 EJB,要么您可以使用 JNDI 远程集成它以访问 EJB 元素并创建某种客户端接口。现在我的新类只是一个 POJO,但它无法访问 EJB 功能。

一般我应该怎么做?

编辑:请注意我的问题不是关于数据库访问。这只是我正在使用的一个例子。我的猜测更广泛。我想知道如何从我创建的其他类访问 EJB 方法。从一个 EJB 到另一个,您可以简单地注入另一个 EJB,因为它们都是容器管理的。但是假设我在与 EJB 相同的包中创建了另一个类,我该如何访问这些方法?有可能吗?这里的最佳做法是什么。

现在我有一个类,它从 URL 获取 twitter 提要数据,然后解析 JSON 并返回前 10 个条目的字符串。我想调用管理数据库访问的 EJB 并将该字符串传递给其相应的方法,但我不能这样做,因为我的类也不是 EJB。

【问题讨论】:

  • “在 JEE 项目中是不允许 POJO 的吗?” - 你从哪里听到的?
  • 我创建了一个并尝试将它与我的 EJB 集成,但它不起作用。这就是我问这个问题的原因。

标签: java jakarta-ee ejb


【解决方案1】:

EJB 通常用于实现任何类型的服务。它们与 JPA 集成得非常好,因此经常用于 DB 访问,但这不是它们的唯一用途。

EJB 通常适合建模数据。 IE。它们应该是应用程序中的动词,而不是名词。因此以下是错误的

@Stateless
@Entity
public class CreditCard { // silly, don't do this!

     @Id
     Long id; + getters/setters
     Data expiration date; + getters/setters
}

以下更好,它是一项服务,当您的应用程序启动时,它会从某处获取一些报价数据:

@Singleton
@Startup
public class QuoteFetcher {

     private List<Quote> quotes; // + getter

     @PostConstruct
     public fetchQuote()
          quotes = SomeUrlBuilder.someUrl().getQuotes();
     }
 }

以下是强制性 DAO 示例:

@Stateless
public class JPAInvoiceDAO implements InvoiceDAO {

     @PersistenceContext
     private EntityManager entityManager;

     public Invoice getById(Long invoiceId) {
           return entityManager.find(invoiceId, Invoice.class);
     }

     // More DAO methods
}

下面展示了如何使用声明性安全性,以及 bean 如何查找已在外部映射到其私有上下文 (ENC) 的内容:

@Stateless
public class TokenFetcher

    @Resource
    private SessionContext sessionContext;

    @RolesAllowed("SYSTEM")
    public Token getToken() {
        return (Token) sessionContext.lookup("token");
    }
}

问题的第二部分似乎是如何在您的代码中使用这些 bean。基本上有四种方法:

  1. 托管 bean 中的注入
  2. 通过 JNDI 引导
  3. 启动时自动调用
  4. 通过计时器自动

注入是最简单的方法,但只有托管 bean 才是注入候选者(基本上意味着 Java EE 框架会创建 bean,并且您不使用 new() 来实例化它)。

例如注入:

@ManagedBean
public class InvoiceBacking {

     private Long invoiceId; // + getter/setter
     private Invoice invoice; // + getter

     @EJB
     private InvoiceDAO invoiceDAO;

     @PostConstruct
     public void init() {
          invoice = invoiceDAO.getById(invoiceId);
     }
 }

(另见Communication in JSF 2.0#Processing GET request parameters

通过 JNDI 引导:

 public class SomeQuartzJob implements Job {

     public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
          InvoiceDAO invoiceDAO = (InvoiceDAO) new InitialContext().lookup("java:global/myApp/myEJB/InvoiceDAO");
          List<Invoice> openInvoices = invoiceDAO.getAllByOpenStatus();
          // verbose exception handling and closing JNDI context omitted for brevity
     }
  }

前面展示的 @Singleton bean 是 Java EE 框架如何在启动时调用您的代码本身的一个示例。对于自动计时器,您可以在 bean 的方法上使用 @Schedule 注释。

【讨论】:

  • 谢谢。 JPA 不会强制将 EJB 实体类创建为名词吗?这是有道理的,通常当您编写 EJB 时,它是为了执行某些操作,但 @Entity 是为了建模数据,对吧?为什么这么傻?这不就是容器管理数据库对象的方式吗?
  • > EJB 用于执行某些操作,但 @Entity 用于建模数据,对吗?为什么这很傻? - 这并不傻,这就是 Java EE 中惯用的做事方式。如果您声明一个实体也是一个 EJB(尤其是无状态的),那么这是相当愚蠢的。 StatelessEntity 几乎是直接矛盾的。
  • Stateless 表示客户端不能假定在两次调用之间 bean 中存在任何数据。而Entity 表示 bean 的唯一目的是保存数据。
猜你喜欢
  • 2016-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多