Java
Proxy Object
Reflection Error
Programming
Troubleshooting

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

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

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

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.