/** * Determines whether it is necessary to rollback the current transaction * when the specified exception occurred during the method invocation. * * @param exception the exception that occurred during the method * invocation. * @return {@code true} if the interceptor should rollback the current * transaction, {@code false} if the interceptor should commit the * current transaction. */ private boolean needsRollback( Exception exception) { boolean rollback = exception instanceof RuntimeException; for (Class<?> clazz = exception.getClass(); clazz != null; clazz = clazz .getSuperclass()) { ApplicationException ae = clazz .getAnnotation(ApplicationException.class); if (ae != null) { if (ae.inherited()) { return ae.rollback(); } else { break; } } } return rollback; }
private void processApplicationExceptions(final Class<?> clazz, final AssemblyDescriptor assemblyDescriptor) { /* * @ApplicationException */ for (final Method method : clazz.getMethods()) { for (final Class<?> exception : method.getExceptionTypes()) { final ApplicationException annotation = exception.getAnnotation(ApplicationException.class); if (annotation == null) { continue; } if (assemblyDescriptor.getApplicationException(exception) != null) { mergeApplicationExceptionAnnotation(assemblyDescriptor, exception, annotation); } else { logger.debug("Found previously undetected application exception {0} listed on a method {1} with annotation {2}", method, exception, annotation); assemblyDescriptor.addApplicationException(exception, annotation.rollback(), annotation.inherited()); } } } }
@Test /** * For http://issues.apache.org/jira/browse/OPENEJB-980 */ public void applicationExceptionInheritanceTest() throws Exception { EjbModule ejbModule = testModule(); final AnnotationDeployer.DiscoverAnnotatedBeans discvrAnnBeans = new AnnotationDeployer.DiscoverAnnotatedBeans(); ejbModule = discvrAnnBeans.deploy(ejbModule); final AssemblyDescriptor assemblyDescriptor = ejbModule.getEjbJar().getAssemblyDescriptor(); org.apache.openejb.jee.ApplicationException appEx = assemblyDescriptor.getApplicationException(BusinessException.class); assertThat(appEx, notNullValue()); assertThat(appEx.getExceptionClass(), is(BusinessException.class.getName())); assertThat(appEx.isRollback(), is(true)); //inheritance is now handled at runtime, only explicitly mentioned exceptions are in the assembly descriptor appEx = assemblyDescriptor.getApplicationException(ValueRequiredException.class); assertThat(appEx, nullValue()); }
@AroundInvoke public Object trackRequest(InvocationContext invocationContext) throws Throwable { RequestEvent event = new RequestEvent(String.format("%s#%s", invocationContext.getTarget().getClass().getSimpleName(), invocationContext.getMethod().getName())); try { Object result = invocationContext.proceed(); requestEvents.select(new AnnotationLiteral<Succeed>() { }).fire(event.finished()); return result; } catch (Throwable t) { if (!t.getClass().isAnnotationPresent(ApplicationException.class)) { // only count failure if it is not an ApplicationException! requestEvents.select(new AnnotationLiteral<Failed>() { }).fire(event.finished(t)); } else { requestEvents.select(new AnnotationLiteral<Succeed>() { }).fire(event.finished()); } throw t; } }
@Override public boolean isApplicationException(Exception e) { for (Class<?> declaredEx : interfaceMethod.getExceptionTypes()) { if (declaredEx.isInstance(e)) { return true; } } if (e.getClass().getAnnotation(ApplicationException.class) != null) { return true; } return false; }
@Test public void testException() { ForbiddenOperationException wrappedException = new ForbiddenOperationException("someMessage"); JaxRsResponseException response = new JaxRsResponseException(wrappedException); assertEquals(response.getMessage(), wrappedException.getMessage()); assertEquals(response.getStatusCode(), wrappedException.getStatusCode()); assertNotNull(response.getClass().getAnnotation(ApplicationException.class)); }
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { boolean newTransaction = beginTransaction(); try { return method.invoke(delegate, args); } catch (Throwable throwable) { if (throwable instanceof InvocationTargetException) { InvocationTargetException invocationTargetException = (InvocationTargetException) throwable; ApplicationException applicationException = invocationTargetException.getTargetException().getClass().getAnnotation(ApplicationException.class); if (applicationException == null || applicationException.rollback()) { rollbackTransaction(); } } else { rollbackTransaction(); } throw throwable.getCause(); } finally { endTransaction(newTransaction); } }
public ExceptionType getExceptionType(final Throwable e) { // Errors are always system exceptions if (!(e instanceof Exception)) { return ExceptionType.SYSTEM; } // check the registered app exceptions Class<?> exceptionClass = e.getClass(); boolean inherited = false; while (exceptionClass != Object.class) { final ExceptionType type = exceptions.get(exceptionClass); if (type == ExceptionType.APPLICATION || type == ExceptionType.APPLICATION_ROLLBACK) { return type; } if (type != null) { if (inherited) { return ExceptionType.SYSTEM; } if (type == ExceptionType.APPLICATION_NOT_INHERITED) { return ExceptionType.APPLICATION; } return ExceptionType.APPLICATION_ROLLBACK; } exceptionClass = exceptionClass.getSuperclass(); inherited = true; } // Unregistered - runtime exceptions are system exception and the rest are application exceptions final Class<? extends Throwable> eClass = e.getClass(); final ApplicationException applicationException = eClass.getAnnotation(ApplicationException.class); if (applicationException != null) { addApplicationException(eClass, applicationException.rollback(), applicationException.inherited()); return getExceptionType(e); } if (e instanceof RuntimeException) { return ExceptionType.SYSTEM; } return ExceptionType.APPLICATION; }
private static void mergeApplicationExceptionAnnotation(final AssemblyDescriptor assemblyDescriptor, final Class<?> exceptionClass, final ApplicationException annotation) { final org.apache.openejb.jee.ApplicationException applicationException = assemblyDescriptor.getApplicationException(exceptionClass); if (applicationException.getRollback() == null) { applicationException.setRollback(annotation.rollback()); } if (applicationException.getInherited() == null) { applicationException.setInherited(annotation.inherited()); } }
/** * Logs any exceptions thrown by the EJB method invoked. * * @param invContext the method context * @return the method result * @throws Exception if invoking the method throws an exception. */ @AroundInvoke @SuppressWarnings({"PMD.SignatureDeclareThrowsException", "ucd" }) public Object logException(InvocationContext invContext) throws Exception { try { return invContext.proceed(); } catch (Exception e) { // do not log exceptions annotated w/AnnotationException - they are expected if (e.getClass().getAnnotation(ApplicationException.class) == null) { Logger log = Logger.getLogger(invContext.getTarget().getClass()); log.error("Exception thrown while invoking " + invContext.getMethod().getName(), e); } throw e; } }
private static boolean hasRollbackAnnotation(Exception ex) { ApplicationException annotation = ex.getClass().getAnnotation( ApplicationException.class); return annotation != null && annotation.rollback(); }
@Override public boolean rollbackOn(Throwable ex) { ApplicationException ann = ex.getClass().getAnnotation(ApplicationException.class); return (ann != null ? ann.rollback() : super.rollbackOn(ex)); }