简体   繁体   English

由于 Spring CGLIB 而未获得确切的行号

[英]Not getting exact line number because of Spring CGLIB

I am working on a Spring Boot application.我正在处理 Spring 启动应用程序。 I have defined an exception aspect, in order to customize and send meaningful error codes in the API response for service classes something like the below:我定义了一个异常方面,以便在服务类的 API 响应中自定义和发送有意义的错误代码,如下所示:

@Aspect
@Order(0)
public class TcInternalExceptionAspect {

  private static final String INTERNAL_SERVER_ERROR = "Internal Server Error";
  private final Logger log = LoggerFactory.getLogger(TcInternalExceptionAspect.class); 

  @Pointcut("@within(org.springframework.stereotype.Service)")
  public void applicationServicePointcut() { }    

  @AfterThrowing(pointcut = "applicationServicePointcut()", throwing = "e")
  public void translate(JoinPoint joinPoint, Throwable e) {
    String resourceId = getResourceId();
    if (e instanceof JDBCException) {
     String message = (StringUtils.isBlank(e.getMessage()) ?
      e.getClass() : e.getMessage());
     log.error(message);
     throw new BadServerStateException("Internal Server Error", resourceId,
      DATABASE_ERROR_CODE);
   } else {
     String message = (StringUtils.isBlank(e.getMessage()) ?
      e.getClass() : e.getMessage());
     log.error(message);
     throw new BadServerStateException("Internal Server Error", resourceId,
      INTERNAL_ERROR_CODE);
  }
 }

BadServerStateException looks like the below: BadServerStateException如下所示:

import org.zalando.problem.AbstractThrowableProblem;

public class BadServerStateException extends AbstractThrowableProblem {
  private static final long serialVersionUID = 1L;

  private final String entityName;
  private final String errorKey;
  private final String errorType;

  public BadServerStateException(String defaultMessage, String entityName, String errorKey) {
    this(defaultMessage, entityName, Status.INTERNAL_SERVER_ERROR, errorKey,
        ErrorTypes.SYSTEM_ERROR.name());
  }

  public BadServerStateException(String defaultMessage, String entityName, String errorKey,
                                 String errorType) {
    this(defaultMessage, entityName, Status.INTERNAL_SERVER_ERROR, errorKey, errorType);
  }

  public BadServerStateException(String defaultMessage,  String message, String entityName,
                             StatusType statusType, String errorKey, String errorType) {


 super(null, defaultMessage, statusType, null, null, null,
        getAlertParameters(message));
    this.entityName = entityName;
    this.errorKey = errorKey;
    this.errorType = errorType;
  }

  public BadServerStateException(String defaultMessage, String entityName, StatusType statusType,
                                 String errorKey, String errorType) {
    super(null, defaultMessage, statusType, null, null, null,
        getAlertParameters(defaultMessage));
    this.entityName = entityName;
    this.errorKey = errorKey;
    this.errorType = errorType;
  }

  private static Map<String, Object> getAlertParameters(String defaultMessage) {
    Map<String, Object> parameters = new HashMap<>();
    if (!StringUtils.isEmpty(defaultMessage)) {
      parameters.put(EXCEPTION_MESSAGE_PARAMETER_NAME, defaultMessage);
    }
    return parameters;
  }

  public String getEntityName() {
    return entityName;
  }

  public String getErrorKey() {
    return errorKey;
  }

  public String getErrorType() {
    return errorType;
  }

} }

In case of any API error, I am getting an error log something like the below:如果出现任何 API 错误,我将收到如下错误日志:

com.mycom.tc.exception.external.BadServerStateException: Internal Server Error
    at com.mycom.tc.exception.TcInternalExceptionAspect.translate(TcInternalExceptionAspect.java:73)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:617)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:68)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
    at com.mycom.tm.service.impl.MyServiceImpl$$EnhancerBySpringCGLIB$$b4c3687b.myFunction(<generated>)
    at com.mycom.tm.web.rest.MyResource.createDocument(MyResource.java:46)
    at com.mycom.tm.web.rest.MyResource$$FastClassBySpringCGLIB$$43df49a4.invoke(<generated>)

As you can see in the above log snipper, I am not getting the exact line of error in myFunction , not able to understand how to get this.正如您在上面的日志截图中看到的,我没有在myFunction中得到确切的错误行,无法理解如何得到它。

Could someone please help here?有人可以帮忙吗? Thanks.谢谢。

The effect you are seeing is not due to CGLIB, it is due to the way you handle exceptions.您看到的效果不是由于 CGLIB,而是由于您处理异常的方式。 It is not even related to Spring AOP or Spring as such, really.它甚至与 Spring AOP 或 Spring 本身无关,真的。

Does your BadServerStateException not have a constructor with a Throwable cause like this?您的BadServerStateException是否没有像这样的Throwable cause的构造函数?

package de.scrum_master.spring.q73557968;

public class BadServerStateException extends RuntimeException {
  public BadServerStateException(String internalServerError, String resourceId, Object p2) {
    this(internalServerError, resourceId, p2, null);
  }
  public BadServerStateException(String internalServerError, String resourceId, Object p2, Throwable cause) {
    super(internalServerError + ": " + resourceId + " -> " + p2, cause);
  }
}

Then, given you have an application and a service like this, ...然后,假设您有这样的应用程序和服务,...

package de.scrum_master.spring.q73557968;

import org.hibernate.JDBCException;
import org.springframework.stereotype.Service;

import java.sql.SQLException;

@Service
public class MyService {
  public void doSomething() {
    System.out.println("My service");
  }

  public void doSomethingElse() {
    throw new JDBCException("uh-oh, database error", new SQLException("syntax error in SQL"));
  }

  public void doAnotherThing() {
    throw new ClassCastException("oops, cannot cast Foo to Bar");
  }
}
package de.scrum_master.spring.q73557968;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
@Configuration
public class DemoApplication {
  public static void main(String[] args) throws Throwable {
    try (ConfigurableApplicationContext appContext = SpringApplication.run(DemoApplication.class, args)) {
      doStuff(appContext);
    }
  }

  private static void doStuff(ConfigurableApplicationContext appContext) {
    MyService myService = appContext.getBean(MyService.class);
    myService.doSomething();
    try {
      myService.doSomethingElse();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
    try {
      myService.doAnotherThing();
    }
    catch (Exception e) {
      e.printStackTrace();
    }
  }
}

..., just change the aspect to use the constructor with the Throwable parameter and pass on the original exception: ...,只需更改方面以使用带有Throwable参数的构造函数并传递原始异常:

package de.scrum_master.spring.q73557968;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.hibernate.JDBCException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Order(0)
public class TcInternalExceptionAspect {
  private static final String INTERNAL_SERVER_ERROR = "Internal Server Error";
  private static final Object DATABASE_ERROR_CODE = 11;
  private static final Object INTERNAL_ERROR_CODE = 22;
  private final Logger log = LoggerFactory.getLogger(TcInternalExceptionAspect.class);

  @Pointcut("@within(org.springframework.stereotype.Service)")
  public void applicationServicePointcut() {}

  @AfterThrowing(pointcut = "applicationServicePointcut()", throwing = "e")
  public void translate(JoinPoint joinPoint, Throwable e) {
    String resourceId = getResourceId();
    if (e instanceof JDBCException) {
      String message = e.getMessage() == null || e.getMessage().trim().equals("")
        ? e.getClass().toString()
        : e.getMessage();
      log.error(message);
      throw new BadServerStateException(INTERNAL_SERVER_ERROR, resourceId, DATABASE_ERROR_CODE, e);
    }
    else {
      String message = e.getMessage() == null || e.getMessage().trim().equals("")
        ? e.getClass().toString()
        : e.getMessage();
      log.error(message);
      throw new BadServerStateException(INTERNAL_SERVER_ERROR, resourceId, INTERNAL_ERROR_CODE, e);
    }
  }

  private String getResourceId() {
    return "ABC-123";
  }
}

Then, on the console you should see:然后,您应该在控制台上看到:

2022-12-10 08:51:26.017  INFO 23880 --- [           main] d.s.spring.q73557968.DemoApplication     : Started DemoApplication in 2.585 seconds (JVM running for 3.175)
My service
2022-12-10 08:51:26.031 ERROR 23880 --- [           main] d.s.s.q.TcInternalExceptionAspect        : uh-oh, database error
2022-12-10 08:51:26.033 ERROR 23880 --- [           main] d.s.s.q.TcInternalExceptionAspect        : oops, cannot cast Foo to Bar
de.scrum_master.spring.q73557968.BadServerStateException: Internal Server Error: ABC-123 -> 11
    at de.scrum_master.spring.q73557968.TcInternalExceptionAspect.translate(TcInternalExceptionAspect.java:33)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:617)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:68)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
    at de.scrum_master.spring.q73557968.MyService$$EnhancerBySpringCGLIB$$22cb0578.doSomethingElse(<generated>)
    at de.scrum_master.spring.q73557968.DemoApplication.doStuff(DemoApplication.java:24)
    at de.scrum_master.spring.q73557968.DemoApplication.main(DemoApplication.java:16)
Caused by: org.hibernate.JDBCException: uh-oh, database error
    at de.scrum_master.spring.q73557968.MyService.doSomethingElse(MyService.java:14)
    at de.scrum_master.spring.q73557968.MyService$$FastClassBySpringCGLIB$$7d395b25.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
    ... 9 more
Caused by: java.sql.SQLException: syntax error in SQL
    ... 16 more
de.scrum_master.spring.q73557968.BadServerStateException: Internal Server Error: ABC-123 -> 22
    at de.scrum_master.spring.q73557968.TcInternalExceptionAspect.translate(TcInternalExceptionAspect.java:40)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:617)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:68)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698)
    at de.scrum_master.spring.q73557968.MyService$$EnhancerBySpringCGLIB$$22cb0578.doAnotherThing(<generated>)
    at de.scrum_master.spring.q73557968.DemoApplication.doStuff(DemoApplication.java:30)
    at de.scrum_master.spring.q73557968.DemoApplication.main(DemoApplication.java:16)
Caused by: java.lang.ClassCastException: oops, cannot cast Foo to Bar
    at de.scrum_master.spring.q73557968.MyService.doAnotherThing(MyService.java:17)
    at de.scrum_master.spring.q73557968.MyService$$FastClassBySpringCGLIB$$7d395b25.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
    ... 9 more

See?看? Of course, you see the newly created exception and its current stack trace, but the causing exception's stack trace is also displayed.当然,您会看到新创建的异常及其当前堆栈跟踪,但也会显示引发异常的堆栈跟踪。 This is a standard means of exception handling in Java.这是Java中异常处理的标准手段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM