在 Java EE 7 上使用 CDI 的 AOP 拦截异常记录
Intercept Exceptions for logging with CDI's AOP on Java EE 7
我有以下 class 片段,我想从中删除重复的日志记录代码并将其移动到使用 CDI 的 AOP 的拦截器。
/**
* Javadoc omitted
*/
public abstract class JpaDao<T extends LongIdentifiable> implements
GenericDao<T> {
@Override
@Transactional
public Long persist(T type) throws GeneralPersistenceException {
if (type == null) {
throw new GeneralPersistenceException("Can't persist null");
}
try {
entityManager.persist(type);
return type.getId();
} catch (PersistenceException e) {
String message = "Failed to persist an entity";
logger.error(message, e);
throw new GeneralPersistenceException(message, e);
}
}
@Override
@Transactional
public T merge(T type) throws GeneralPersistenceException {
if (type == null) {
throw new GeneralPersistenceException("Can't merge null");
}
try {
T mergedType = entityManager.merge(type);
return mergedType;
} catch (PersistenceException e) {
String message = "Failed to merge an entity";
logger.error(message, e);
throw new GeneralPersistenceException(message, e);
}
}
}
注意下面的代码片段,它在 persist
和 merge
方法中重复
} catch (PersistenceException e) {
String message = "Failed to persist an entity";
logger.error(message, e);
throw new GeneralPersistenceException(message, e);
}
替换上述代码段的候选代码如下:
} catch (PersistenceException e) {
throw new GeneralPersistenceException("Failed to persist an entity", e);
}
换句话说,我希望每次抛出 GeneralPersistenceException
时,都会写入一条日志消息。我的例外情况如下:
public class GeneralPersistenceException extends Exception {
private static final long serialVersionUID = -6057737927996676949L;
public GeneralPersistenceException() {
}
public GeneralPersistenceException(String message) {
super(message);
}
public GeneralPersistenceException(String message, Throwable cause) {
super(message, cause);
}
public GeneralPersistenceException(Throwable cause) {
super(cause);
}
}
如您所见,Exception 只有构造函数。
鉴于这种情况,我有以下问题:
- 在 Java EE 7 兼容应用程序中解决此问题的最佳策略是将 AOP 与 CDI 结合使用吗?
- 如果是AOP,我应该拦截
GeneralPersistenceException
吗?
- 是否可以拦截
GeneralPersistenceException
的构造函数,或仅拦截方法(尚不存在)?
- 是否已经为此目的实施了一些东西,而我正在重新发明轮子?
提前致谢。
您无法拦截异常,因为它是使用 **new* 创建的,并且不会由 CDI 管理。实际上,您不应该以这种方式进行拦截。
您正在寻找的解决方案是拦截您服务中的调用,在那里捕获您的异常并将其记录下来。
我有以下 class 片段,我想从中删除重复的日志记录代码并将其移动到使用 CDI 的 AOP 的拦截器。
/**
* Javadoc omitted
*/
public abstract class JpaDao<T extends LongIdentifiable> implements
GenericDao<T> {
@Override
@Transactional
public Long persist(T type) throws GeneralPersistenceException {
if (type == null) {
throw new GeneralPersistenceException("Can't persist null");
}
try {
entityManager.persist(type);
return type.getId();
} catch (PersistenceException e) {
String message = "Failed to persist an entity";
logger.error(message, e);
throw new GeneralPersistenceException(message, e);
}
}
@Override
@Transactional
public T merge(T type) throws GeneralPersistenceException {
if (type == null) {
throw new GeneralPersistenceException("Can't merge null");
}
try {
T mergedType = entityManager.merge(type);
return mergedType;
} catch (PersistenceException e) {
String message = "Failed to merge an entity";
logger.error(message, e);
throw new GeneralPersistenceException(message, e);
}
}
}
注意下面的代码片段,它在 persist
和 merge
方法中重复
} catch (PersistenceException e) {
String message = "Failed to persist an entity";
logger.error(message, e);
throw new GeneralPersistenceException(message, e);
}
替换上述代码段的候选代码如下:
} catch (PersistenceException e) {
throw new GeneralPersistenceException("Failed to persist an entity", e);
}
换句话说,我希望每次抛出 GeneralPersistenceException
时,都会写入一条日志消息。我的例外情况如下:
public class GeneralPersistenceException extends Exception {
private static final long serialVersionUID = -6057737927996676949L;
public GeneralPersistenceException() {
}
public GeneralPersistenceException(String message) {
super(message);
}
public GeneralPersistenceException(String message, Throwable cause) {
super(message, cause);
}
public GeneralPersistenceException(Throwable cause) {
super(cause);
}
}
如您所见,Exception 只有构造函数。 鉴于这种情况,我有以下问题:
- 在 Java EE 7 兼容应用程序中解决此问题的最佳策略是将 AOP 与 CDI 结合使用吗?
- 如果是AOP,我应该拦截
GeneralPersistenceException
吗? - 是否可以拦截
GeneralPersistenceException
的构造函数,或仅拦截方法(尚不存在)? - 是否已经为此目的实施了一些东西,而我正在重新发明轮子?
提前致谢。
您无法拦截异常,因为它是使用 **new* 创建的,并且不会由 CDI 管理。实际上,您不应该以这种方式进行拦截。 您正在寻找的解决方案是拦截您服务中的调用,在那里捕获您的异常并将其记录下来。