This post originated from an RSS feed registered with Java Buzz
by Chris Winters.
Original Post: A proxy warning with Spring
Feed Title: cwinters.com
Feed URL: http://www.cwinters.com/search/registrar.php?domain=jroller.com®istrar=sedopark
Feed Description: Chris Winters on Java, programming and technology, usually in that order.
When you're using a Spring proxy or proxy factory (like TransactionProxyFactoryBean) you're getting back by default a JDK 1.4 dynamic proxy. Unfortunately these only work on interfaces, and if you want the proxy to also reflect on class methods you need to (a) explicitly say so and (b) ensure you have CGLIB (and ASM) available.
For instance, say you have an interface:
package eg;
public interface Command {
public void execute();
}
and an implementation:
package eg;
public class MyCommand implements Command {
public void execute() { ... }
public void setOperator( String operator ) { ... }
}
If you create a Spring bean and transactional proxy around it like:
Caught BeansException: Invalid property 'operator' of bean class
[$Proxy0]: Bean property 'operator' is not writable or has an
invalid setter method: Does the parameter type of the setter match
the return type of the getter?
The problem is that the generated proxy only has the method execute() since that's the only method in the interface Command. To fix this you need to explicitly proxy the class -- just set the proxyTargetClass property to true:
This will tell Spring to proxy the class methods as well and, like I mentioned, it requires CGLIB. If you don't have CGLIB in your classpath when you try to use this you'll see an exception like:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'foo' defined in class path
resource [my_ctx.xml]: Initialization of bean failed; nested
exception is org.springframework.aop.framework.AopConfigException:
Cannot proxy target class because CGLIB2 is not available. Add
CGLIB to the class path or specify proxy interfaces....
It's easy to tell if your proxies are actually using CGLIB -- instead of the class name being something like $Proxy3, $Proxy4 and so on, you'll see eg.MyCommand$$EnhancerByCGLIB$$14e427bf.