This is the source class:

@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@JsonSerialize(as = RequestContext.class)
public class RequestContext implements Serializable {

    private static final long serialVersionUID = 1L;

    private String statusCode;

    private String statusType;
    
    private String txnId;
    
    private int channelId;

    private String channel;

}

These are the target class and its parent classes:

@Data
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@JsonSerialize(as = Transaction.class)
public class Transaction extends TransactionBase implements Serializable {

    private static final long serialVersionUID = 1L;

    private Actors actors = Actors.SENDER;
    private PartnerMaster senderPartner;
    private PartnerMaster receiverPartner;
    private PartnerMaster userPartner;
    private UserMaster senderUser;
    private UserMaster receiverUser;

    private WalletAction adjustmentType;
    private BigDecimal netAmount = BigDecimal.ZERO;
    private BigDecimal amount = BigDecimal.ZERO;
    private BigDecimal rollbackAmount = BigDecimal.ZERO;

    private Charges charges = new Charges();

    private List<SystemWalletMaster> systemWallets = new ArrayList<>();
    private List<SystemCdrBean> systemCdr = new ArrayList<>();

    private List<Items> products;

    /** generic params for dynamic values. **/
    private HashMap<String, Object> genericParams = new HashMap<>();

}
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@AllArgsConstructor
public class TransactionBase extends TransactionFlags implements Serializable {

    private static final long serialVersionUID = 1L;

    private int channelId;
    private String channel;
    private String mvnoId;

    private ServiceMaster service = new ServiceMaster();

    private String featureId;

    private String statusCode;
    private String statusCodeReceiver;
    private String statusType;
    private String txnType;
    private String message;

    private String txnId;
    private String requestId;
    private long duration;

    private TransactionCommon transactionCommon;

}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TransactionFlags implements Serializable {

    private static final long serialVersionUID = 1L;

    /** flags . **/
    private boolean rollback;
    
    
    private boolean adjustment;
    private boolean adjustmentSystem;
    private boolean isWhitelisted;
    private boolean adjustCommission;
    private boolean adjustFee;
    private boolean adjustSystemCommission;
    private boolean adjustSystemFee;
    private boolean isLimitExists;
    private boolean isLimitAllServices;
    private boolean isApprovalEnabled;

}

Beans copy:

@Component
@Slf4j
public class RequestInterceptor implements HandlerInterceptor {

    @Autowired
    private Transaction transaction;

    @Autowired
    private RequestContext requestContext;

    @Autowired
    private UserContext userContext;

    @Autowired
    private CopyPropertyUtils copyPropertyUtils;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        if (log.isDebugEnabled())
            log.debug("{}Inside MFS Builder, building Transaction request", CONVERTER);

        copyPropertyUtils.copy(requestContext, transaction);
        
        ..............
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        // No implementation is done in post handle of the intercepter
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {

        ..................
    }

}

When we try to copy RequestContext to Transaction we get this error

java.lang.IllegalArgumentException: object is not an instance of declaring class
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:352) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:765) ~[spring-aop-6.1.1.jar:6.1.1]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:717) ~[spring-aop-6.1.1.jar:6.1.1]
    at com.sixdee.mfs.base.beans.Transaction$$SpringCGLIB$$0.setChannel(<generated>) ~[classes/:?]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:?]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[?:?]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:?]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[?:?]

Followed by this:

[2m2024-03-08T12:37:20.803+05:30[0;39m [31mERROR[0;39m [35m20264[0;39m [2m---[0;39m [2m${sys:LOGGED_APPLICATION_NAME}[nio-9110-exec-1][0;39m [36mc.s.d.b.e.ResponseErrorHandler          [0;39m [2m:[0;39m Resource Not Found : object is not an instance of declaring class CLASS jdk.internal.reflect.NativeMethodAccessorImpl LINE -2 
[2m2024-03-08T12:37:20.836+05:30[0;39m [33m WARN[0;39m [35m20264[0;39m [2m---[0;39m [2m${sys:LOGGED_APPLICATION_NAME}[nio-9110-exec-1][0;39m [36m.m.m.a.ExceptionHandlerExceptionResolver[0;39m [2m:[0;39m Resolved [org.springframework.beans.FatalBeanException: Could not copy property 'channel' from source to target]
[2m2024-03-08T12:37:20.836+05:30[0;39m [32mDEBUG[0;39m [35m20264[0;39m [2m---[0;39m [2m${sys:LOGGED_APPLICATION_NAME}[nio-9110-exec-1][0;39m [36mc.s.m.b.s.e.EventManager                [0;39m [2m:[0;39m Event management is in progress...
[2m2024-03-08T12:37:20.836+05:30[0;39m [31mERROR[0;39m [35m20264[0;39m [2m---[0;39m [2m${sys:LOGGED_APPLICATION_NAME}[nio-9110-exec-1][0;39m [36mo.s.w.s.HandlerExecutionChain           [0;39m [2m:[0;39m HandlerInterceptor.afterCompletion threw exception

org.springframework.aop.AopInvocationException: AOP configuration seems to be invalid: tried calling method [public java.lang.String com.sixdee.mfs.base.beans.Transaction.toString()] on target [RequestContext(statusCode=DFS100, statusType=F, txnId=168421046664246, channelId=1, channel=PORTAL)]

All the properties required in the target (Transaction) are extended from its parent TransactionBase.

  1. If we try to move those properties to Transaction there will be no error.
  2. When we tried to copy new RequestContext() to new Transaction() rather than the autowired beans there was no error.
  3. The copy worked when we removed the @Scope annotation.
  4. We decompiled the .class file of Transaction and found that there were no inherited methods.
  5. We gave all the annotations of Transaction to TransactionBase the error was still occurring.

We are not able to find what is causing this issue, whether it is the issue with the source (Point-3) or the issue with the target (Point-1), all we can understand is one of the object isn't available, also the property names and types are the same. According to the comment by @M. Deinum in this post I believe the issue is with the org.springframework.beans.BeanUtils but the answer says something else.

We are using @Autowired in some scenarios and @AllArgsConstructor in some other scenarios for dependency injection, would that be causing any issues? Also, the RequestContext is a bean in parent maven project and the others are in the child maven project which depends on the parent.

Versions

Java 17

Spring Boot 3.2.0

1

There are 1 best solutions below

0
Saulo Bastos Da Silva On

when you use ScopedProxyMode.TARGET_CLASS it'll use CGLIB to create a class-based proxy. So the objects of type Transaction and RequestContext aren't the real instances, they're proxies to the concrete classes, like Andrew and M.Deinum said in the comment section. You'll need to use the concrete implementation instead of the proxy.