Java
Proxy Object
Reflection Error
Programming
Troubleshooting

Can not set field to com.sun.proxy.Proxy

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

The error "Can not set field to com.sun.proxy.$Proxy" occurs in Java when code tries to inject or assign a JDK dynamic proxy object to a field that expects a concrete class type. JDK proxies implement interfaces only — they cannot be cast to concrete classes. This error is most common in Spring applications where beans are proxied for AOP (aspect-oriented programming), transactions, or scoping. The fix is to program to interfaces rather than implementations, or switch to CGLIB proxies that can proxy concrete classes.

Why the Error Happens

java
1// JDK proxy only implements the interface, not the concrete class
2public interface UserService {
3    User findById(Long id);
4}
5
6@Service
7public class UserServiceImpl implements UserService {
8    public User findById(Long id) { /* ... */ }
9    public void internalMethod() { /* ... */ }
10}
11
12// This fails — Spring creates a JDK proxy that implements UserService
13// but is NOT an instance of UserServiceImpl
14@Autowired
15private UserServiceImpl userService;  // ERROR: com.sun.proxy.$Proxy cannot be cast

When Spring creates a JDK dynamic proxy for UserServiceImpl, the proxy implements the UserService interface. The proxy object's type is com.sun.proxy.$Proxy, not UserServiceImpl. Injecting into a field of type UserServiceImpl fails because the proxy is not assignable to the concrete class.

java
1@Controller
2public class UserController {
3    // Correct — inject by interface type
4    @Autowired
5    private UserService userService;
6
7    // The proxy implements UserService, so this works
8}

Always declare fields, constructor parameters, and method parameters using the interface type rather than the implementation class. This follows the Dependency Inversion Principle and works with all proxy types.

Fix 2: Enable CGLIB Proxies

java
1// In Spring Boot application class or configuration
2@SpringBootApplication
3@EnableAspectJAutoProxy(proxyTargetClass = true)
4public class MyApplication {
5    public static void main(String[] args) {
6        SpringApplication.run(MyApplication.class, args);
7    }
8}

Or in application.properties:

properties
spring.aop.proxy-target-class=true

CGLIB proxies subclass the concrete class instead of implementing interfaces, so the proxy IS an instance of UserServiceImpl. Spring Boot 2.x+ defaults to CGLIB proxies, but this can be overridden by configuration or specific annotations.

Fix 3: XML Configuration

xml
1<!-- Enable CGLIB class-based proxies -->
2<aop:aspectj-autoproxy proxy-target-class="true"/>
3
4<!-- Or for transaction management -->
5<tx:annotation-driven proxy-target-class="true"/>

For Spring XML-based configuration, add proxy-target-class="true" to the relevant AOP or transaction configuration elements.

JDK Proxy vs CGLIB Proxy

java
1// JDK Proxy — implements interfaces only
2// Generated class: com.sun.proxy.$Proxy42
3// Works with: interface types
4// Fails with: concrete class types
5
6// CGLIB Proxy — subclasses the concrete class
7// Generated class: UserServiceImpl$$EnhancerBySpringCGLIB$$abc123
8// Works with: both interface and concrete class types
9// Limitation: cannot proxy final classes or final methods
FeatureJDK ProxyCGLIB Proxy
MechanismImplements interfacesSubclasses concrete class
Requires interfaceYesNo
Proxy final classesN/ANo (cannot subclass final)
Proxy final methodsN/ANo (cannot override final)
PerformanceSlightly faster creationSlightly faster invocation
Default in Spring Boot 2+NoYes

Common Scenarios That Trigger This Error

java
1// Scenario 1: @Transactional on a class without interface injection
2@Service
3@Transactional
4public class OrderService { /* ... */ }
5
6@Autowired
7private OrderService orderService;  // Fails with JDK proxy
8
9// Scenario 2: Scoped proxy
10@Service
11@Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
12public class RequestScopedService implements MyInterface { /* ... */ }
13
14@Autowired
15private RequestScopedService service;  // Fails — proxy implements MyInterface only
16
17// Scenario 3: AOP advice applied
18@Aspect
19@Component
20public class LoggingAspect {
21    @Around("execution(* com.example.service.*.*(..))")
22    public Object log(ProceedingJoinPoint pjp) throws Throwable {
23        return pjp.proceed();
24    }
25}
26// Any service matching the pointcut gets proxied

Debugging Proxy Type

java
1@Autowired
2private UserService userService;
3
4@PostConstruct
5public void checkProxy() {
6    System.out.println("Class: " + userService.getClass().getName());
7    // JDK: com.sun.proxy.$Proxy42
8    // CGLIB: com.example.UserServiceImpl$$EnhancerBySpringCGLIB$$abc123
9
10    System.out.println("Is proxy: " + AopUtils.isAopProxy(userService));
11    System.out.println("Is JDK proxy: " + AopUtils.isJdkDynamicProxy(userService));
12    System.out.println("Is CGLIB proxy: " + AopUtils.isCglibProxy(userService));
13}

Use AopUtils to inspect whether a bean is proxied and which proxy mechanism is in use. This helps diagnose which beans are affected.

Common Pitfalls

  • Injecting by concrete class type: The most common cause. Always use the interface type for @Autowired fields. If no interface exists, either create one or ensure CGLIB proxying is enabled.
  • Mixing JDK and CGLIB proxy settings: Different Spring modules (AOP, transactions, cache) can have independent proxy settings. Ensure consistency by setting spring.aop.proxy-target-class=true globally in application.properties.
  • Final classes with CGLIB: CGLIB cannot subclass final classes. If you switch to CGLIB proxies and have final service classes, you get a different error. Remove final from classes that need proxying.
  • ScopedProxyMode.INTERFACES with concrete injection: When using request-scoped or session-scoped beans with ScopedProxyMode.INTERFACES, the proxy only implements interfaces. Use ScopedProxyMode.TARGET_CLASS for CGLIB-based scoped proxies.
  • Kotlin classes are final by default: In Kotlin, all classes are final unless marked open. This breaks CGLIB proxies. Use the kotlin-spring compiler plugin (all-open) to automatically open Spring-annotated classes.

Summary

  • The error occurs when a JDK dynamic proxy (interface-only) is injected into a field expecting a concrete class
  • Fix by declaring fields as interface types rather than implementation classes
  • Enable CGLIB proxies with spring.aop.proxy-target-class=true if interface-based injection is not possible
  • Spring Boot 2+ defaults to CGLIB proxies, but specific configurations can override this
  • Use AopUtils.isJdkDynamicProxy() and AopUtils.isCglibProxy() to diagnose proxy types
  • CGLIB cannot proxy final classes — remove final or use the Kotlin all-open plugin

Course illustration
Course illustration

All Rights Reserved.