来自持久化上下文Java EE的EntityManager空指针异常

时间:2016-11-05 21:37:20

标签: jpa dependency-injection nullpointerexception ejb entitymanager

我使用EJB容器管理的entityManager时遇到问题。

在我耳边,我有3个模块:

-domain - 有接口作为EJB的实体类和DAO实现。

-services - 在那里我会有与处理请求相关的逻辑,根据库异常调用业务异常(例如数据库异常)。

-Rest Services - 我会有其他端点来接收和发送一些业务对象。

所以主要的问题是在服务层使用EJB,我可以将Rest端点类,服务类和DAO类声明为EJB。但是这样我就无法捕获与数据库相关的异常,因为我正在使用WildFly提供的EJB容器中得到transactionRollback异常,并且这个异常存在于提交事务中。

我考虑过从服务类中删除@Stateless注释,但是当我这样做时,EJB容器不会在我的DAO类中注入entityManager。我也尝试在服务类中使用@Inject注释,但仍然在Dao类中的entityManager上获得相同的NullPointer异常。

下面我在我的项目中添加示例代码实现:

DAO班级:

@Stateless
public class CardDaoImpl implements CardDao {

@PersistenceContext(unitName = "test")
protected EntityManager em;

public CardBase addCardToDatabase(CardBase card) {
    em.persist(card);
    return card;
}

服务类(这里我想处理businessExceptions):

@Stateless
public class TestService implements TestServiceIf {

@EJB(beanInterface = CardDao.class)
private CardDao dao;

@Override
public CardBase addCard(CardBase card) {
    dao.addCardToDatabase(card);
    return card;
}

}

休息端点类:

@Stateless
@Path("/test")
public class Test {

@EJB(beanInterface = TestServiceIf.class)
private TestServiceIf service;

@GET
@Path("/test")
@Produces(MediaType.APPLICATION_JSON)
public String addCard() {
    CardBase card = new SampleCard();
    //Setting card object fields//
    service.addCard(card);
    return "Hello";
}

}

这只是我发现的一种解决方案。但抛出我的businnesExceptions是什么?将它们扔进这个服务层可能不是一个好习惯吗?

1 个答案:

答案 0 :(得分:1)

使用EJB 3.X,您可以了解ejb方法中发生的异常的一些特性。

  

-services - 在那里,我将有与处理请求相关的逻辑,根据库异常调用业务异常(for   示例数据库异常)。

默认情况下,容器包含技术异常(EJBTransactionRolledbackException)在EJB中发生的所有异常,它认为是意外的。以同样的方式,您可以捕获应用程序中的所有意外异常。除了异常包装之外,容器还会触发当前事务的回滚 为了避免容器的技术异常包装,容器不应将业务异常视为意外。

从广义上讲,你有两种情况:

  • 要么检查这些。在这种情况下无事可做。

  • 要么是运行时间。您必须在其上添加ApplicationException注释,或者指定自EJB的xml配置以来的应用程序异常行为。

来自ApplicationException javadoc:

  

:应用于异常以表示它是一个   应用程序异常并应直接向客户端报告   (即打开包装)。

最后,回滚操作可能是合乎需要的。您可以这样配置:

@ApplicationException(rollback=true)
public class MyBusinessRuntimeException extends RuntimeException {

@ApplicationException(rollback=false)
public class MyBusinessRuntimeException extends RuntimeException {

使用Weblogic,我记得我还必须在方法的签名中声明这些异常。

评论更新:

  

但首先我需要从第三方lib中捕获异常   ConstraintValueException。

你有两种做法。在可能发生问题的地方明确处理异常或以横向方式处理异常。 我想你是指ConstraintViolationException

  • 处理异常特定且需要处理上下文时发生的异常:

如果您希望在特定方案中遇到特定的第三方例外,您希望捕获它以返回您的业务例外,您应该在它上升后立即捕获第三方例外。
首先,一旦我们知道如何处理异常,就抓住异常是一种好习惯。
其次,避免让异常进入下一层,因此会变成EJBTransactionRolledbackException例外 但是,有时,出于某些原因,可以横向处理异常类型 在这种情况下,您可以对该异常使用横向处理。

  • 当异常包含要处理的所需信息时的横向处理:

如果要以横向方式处理预期的运行时异常,可以使用JEE拦截器捕获它以引发自己的业务异常。
在这种情况下,您必须在拦截器中定义捕获的异常的原因与您的自定义异常之间的映射。

执行您需要的拦截器示例(它不处理所有场景,只是一个名义场景):

public class WrappingInBusinessExceptionInterceptor {

    @AroundInvoke
    public Object handleExceptions(final InvocationContext ctx) throws Exception {

        try {
            Object result = ctx.proceed();
            return result;
        }

        catch (Exception exception) {
            // log the root exception
               ...
               Exception causeException = e.getCause();
               if (causeException !=null &&
                   causeException.getClass()==ConstraintValueException.class){
                  // throw your custom exception
                  String businessMsg =  
                         retrieveBusinessMessageFrom(causeException);
                  throw new MyBusinessException(businessMsg);
                }
        }                               

    }