Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BeanNotOfRequiredTypeException: Bean named X is expected to be of type X but was actually of type 'com.sun.proxy.$Proxy

I have such classes and Spring context.

How to fix this wrong Java configuration, not xml?

I'd tried some solutions from other posts, but without success.

@Service
@Transactional
public class XCalculationService implements VoidService<X> {
}

public interface VoidService<Input> {
}

@AllArgsConstructor
public class XService {
private XCalculationService calculationService;
}

@Configuration
public class ServiceConfiguration {
@Bean
public OrderService orderService(XCalculationService calculationService) {
    return new XService(calculationService);
}

@Bean
public XCalculationService calculationService() {
    return new XCalculationService ();
}
}

Error

BeanNotOfRequiredTypeException: Bean named 'calculationService' is expected to be of type 'com.x.XCalculationService' but was actually of type 'com.sun.proxy.$Proxy
like image 617
Arthur Avatar asked Oct 02 '18 07:10

Arthur


3 Answers

Here is 100% fix:

@EnableTransactionManagement(proxyTargetClass = true)
like image 157
Arthur Avatar answered Nov 11 '22 10:11

Arthur


Java proxies are working on interfaces, not concrete classes.
Reasoning with spring documentation: https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch08s06.html

If the target object to be proxied implements at least one interface then a JDK dynamic proxy will be used.

Therefore, when using aspect/proxy based annotations as @Transactional, Spring will attempt to proxify the concrete class and resulting object will be instance of VoidService interface not XCalculationService.

Therefore you can solve it two ways:

  1. use @Arthur solution and turn off Java's interface proxy in favor of CGLib for transaction support @EnableTransactionManagement(proxyTargetClass = true)
  2. Instead of using XCalculationService type in injectable fields, use only its proxied interface aka VoidService.
like image 39
oneat Avatar answered Nov 11 '22 11:11

oneat


I suppose you have got @ComponentScan somewhere activated and it scans your @Service annotated XCalculationService class.

So you should either remove @Service from XCalculationService

or remove

@Bean
public XCalculationService calculationService() {
    return new XCalculationService ();
}

from ServiceConfiguration

like image 1
mrkernelpanic Avatar answered Nov 11 '22 09:11

mrkernelpanic