在Java EE中与EJB交互的最佳方式

时间:2011-12-10 00:17:24

标签: java java-ee ejb

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

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

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

一般我该怎么做?

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

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

1 个答案:

答案 0 :(得分:8)

EJB通常用于实现任何类型的服务。它们与JPA很好地集成,因此通常用于数据库访问,但这不是它们的唯一用途。

哪些EJB通常适合建模数据。即它们应该是你申请中的动词,而不是名词。因此,错误

@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. 通过计时器自动
  5. 注入是最简单的方法,但只有托管bean是注入候选者(基本上意味着Java EE框架创建了bean,并且你不使用new()来实例化它)。

    E.g。注射:

    @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注释。