[Solved] Solve the problem of com.alibaba.fastjson.JSONException: write javaBean error and solve the problem that Spring Boot joins Shiro and causes spring aop to fail

Article table of contents

  • 1. Reproduce the problem
  • 2. Analyze the problem
  • 3. Problem solving

1. Reproduce the problem

When calling the /user/getAll interface today, the following error is reported:

com.alibaba.fastjson.JSONException: write javaBean error, fastjson version 1.2.54, class org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl, fieldName : sourceLocation
at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:523)
at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:160)
at com.alibaba.fastjson.serializer.JSONSerializer.writeWithFieldName(JSONSerializer.java:310)
at com.alibaba.fastjson.serializer.ASMSerializer_1_MethodInvocationProceedingJoinPoint.write(Unknown Source)
at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:281)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:676)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:614)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:579)
at com.superjson.superjsonmanager.aop.log.RequestLogAspect.doBefore(RequestLogAspect.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
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.AspectJMethodBeforeAdvice.before(AspectJMethodBeforeAdvice.java:44)
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
at com.superjson.superjsonmanager.aop.log.RequestLogAspect.doAround(RequestLogAspect.java:95)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
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:750)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
at com.superjson.superjsonmanager.controller.UserController$$EnhancerBySpringCGLIB$$25c82d38.getAllUsers(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
......

That is, com.alibaba.fastjson.JSONException: write javaBean error, , that is, fastjson creates Javabean object error, why does this happen What about the situation? The following analysis can only be done through breakpoints.

2. Analyze the problem

By analyzing the above other error messages class org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl, fieldName : sourceLocation, the error occurs on the aspect property.

My aspect class is RequestLogAspect, which is a global unified log class that uses the spring boot aop aspect technology. The breakpoints are as follows:

Through breakpoints, the problem can be clearly located in joinPoint.proceed();, and attributes.getRequest(); returns the ShiroHttpServletRequest object .

Why does this object return instead of the spring boot aop object? Because I configured shiro aop as shown in the following code:

/**
 * To enable Shiro's annotations (such as @RequiresRoles, @RequiresPermissions), you need to use SpringAOP to scan classes annotated with Shiro, and perform security logic verification when necessary
 * Configure the following two beans (DefaultAdvisorAutoProxyCreator (optional) and AuthorizationAttributeSourceAdvisor) to achieve this function
 *
 * <p>creator.setUsePrefix(false); choose either creator.setProxyTargetClass(false);
 *
 * @return
 */
@Bean
@DependsOn({<!-- -->"lifecycleBeanPostProcessor"})
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {<!-- -->
  DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
  creator.setUsePrefix(false);
  return creator;
}

Why does configuring shiro aop cause spring aop to fail? The reason lies in the secondary proxy, as follows:

  1. proxy-target-class is enforced due to the use of aop:aspectj-autoproxy

  2. That is to say, the CGLib agent is used for the Class (mainly Controller) of the Web layer.

  3. Then use DefaultAdvisorAutoProxyCreator when Shiro is proxying

  4. Originally should judge Controller and found that there is no interface, so use CGLib to proxy

  5. But because Controller has been delegated by CGLib once

  6. DefaultAdvisorAutoProxyCreator is not Contoller itself, but the proxy result of CGLib

  7. The proxy result of CGLib itself has an interface, which interferes with

  8. Internal judgment of DefaultAdvisorAutoProxyCreator

  9. Use JDK to proxy the results of CGLib

  10. As a result, when the function of Controller went to the interface of CGLib to find the method name, it was found that the method did not exist, causing the proxy to fail.

3. Solve the problem

According to the information on the Internet, we need to configure the following in application.yml:

# spring configuration
spring:
  aop: # Solve the conflict between spring aop and shiro
    proxy-target-class: true

But in fact, this configuration cannot solve the problem, and the above error is still reported.

Therefore, I need to modify the @Pointcut annotation of the aspect class and use the annotation method to solve this problem, as follows:

// The original code, the scan controller
// @Pointcut("execution(public * com.superjson.superjsonmanager.controller.*.*(..))")
// public void requestLog() {}

 /**
  * New code: use annotations to resolve conflicts between shiro aop and spring aop
  *
  * @author is beautiful
  * @datetime 2022/8/22:11:32
  * @return
  */
@Pointcut("@annotation(com.superjson.superjsonmanager.annotation.LogAnnotation)")
public void requestLog() {<!-- -->}

My LogAnnotation annotation class looks like this:

/**
 * @author is beautiful
 * @datetime 2022/8/22 10:05
 * @desc log annotation
 */
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAnnotation {<!-- -->
}

Restart spring boot and call the /user/getAll interface to successfully access and record logs, as shown in the following figure: