如何从EJB捕获运行时异常?

时间:2016-07-19 08:24:12

标签: java lambda ejb jax-rs

我有一个非常奇怪的情况。

我尝试执行EJB的方法并使用JAX-RS返回结果

public Service readSingle(...) {
    try {
        service.query(...);
    } catch (final NoResultException nre) {
        throw new NotFoundException(...);
    } catch (final NonUniqueResultException nure) {
        throw new BadRequstException(...);
    }
}

查询方法需要一些值以及BiFuctionFunction

实际通话看起来像这样。

  try {
        return serviceService.<Service>query(
                id,
                ofNullable(matrixParameters.getFirst("onid"))
                .map(Integer::parseInt).orElse(null),
                ofNullable(matrixParameters.getFirst("tsid"))
                .map(Integer::parseInt).orElse(null),
                ofNullable(matrixParameters.getFirst("sid"))
                .map(Integer::parseInt).orElse(null),
                ofNullable(matrixParameters.getFirst("number"))
                .map(Integer::parseInt).orElse(null),
                ofNullable(matrixParameters.getFirst("programId"))
                .orElse(null),
                operatorId,
                (builder, root) -> emptyList(),
                TypedQuery::getSingleResult);
    } catch (final NoResultException nre) {
        throw new NotFoundException(
                "no entity idnetified by " + serviceIdSegment.getPath()
                + " with " + matrixParameters.toString());
    } catch (final NonUniqueResultException nure) {
        throw new BadRequestException("multiple entities identified");
    }

好的,我通过了TypedQuery::getSingleResult,我希望{J}在被抛出时应该被抓住。

但Payara继续以500响应并且日志显示NonUniqueResultException从未被代码捕获。

我禁用了我的ExceptionMappers,结果是一样的。

2 个答案:

答案 0 :(得分:0)

确定。我想到了。我不得不这样做。

    try {
        // execute EJB
    } catch (final EJBTransactionRolledbackException ejbtre) {
        Exception leaf = ejbtre;
        try {
            for (Exception c;
                 (c = ((EJBException) leaf).getCausedByException()) != null;
                 leaf = c);
        } catch (final ClassCastException cce) {
        }
        logger.severe("causedByException: " + leaf);
        if (leaf instanceof NoResultException) {
            throw new NotFoundException(
                    "no entity idnetified by " + serviceIdSegment.getPath()
                    + " with " + matrixParameters.toString());
        } else if (leaf instanceof NonUniqueResultException) {
            throw new BadRequestException(
                    "multiple entities identified by "
                    + serviceIdSegment.getPath()
                    + " with " + matrixParameters.toString());
        }
        throw new InternalServerErrorException(ejbtre);
    }

这远远超出了我的预期。 EJB的方法设计并不好。

有没有办法更简单地做到这一点?

答案 1 :(得分:0)

让我介绍一下我用来为自己辩护的实用课程。

public final class EJBExceptions {

    private static final Logger logger
            = getLogger(EJBExceptions.class.getName());

    public static Stream<Exception> causedByExceptions(EJBException ejbe) {
        final Stream.Builder<Exception> builder = Stream.builder();
        while (ejbe != null) {
            final Exception causedByException = ejbe.getCausedByException();
            if (causedByException != null) {
                builder.add(causedByException);
            } else {
                break;
            }
            if (causedByException instanceof EJBException) {
                ejbe = (EJBException) causedByException;
            } else {
                break;
            }
        }
        return builder.build();
    }

    public static Optional<Exception> lastCausedByException(
            final EJBException ejbe) {
        return causedByExceptions(ejbe).reduce((first, second) -> second);
    }

    private EJBExceptions() {
        super();
    }
}