2016-07-19 1 views
1

У меня очень любопытная ситуация.Как я могу уловить исключение во время выполнения из EJB?

Я пытаюсь выполнить метод EJB и возвращает результат с JAX-RS

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

Метод запроса требует некоторых значений и BiFuction и Function.

Фактический вызов выглядит следующим образом.

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"); 
    } 

Ok Я прошел TypedQuery::getSingleResult и я ожидаю, NonUniqueResultException должен быть пойман, когда он должен быть выброшен.

Но Payara продолжает отвечать 500, и журнал показывает, что NonUniqueResultException никогда не попадал под код.

Я отключил свои ExceptionMappers, результаты такие же.

ответ

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 не очень хорош.

Есть ли способ сделать это проще?

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(); 
    } 
}