Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

lachoy (1663)

lachoy
  chris.winters@gmail.com
http://www.cwinters.com/

I am actually Chris Winters; I am actually living in Pittsburgh, Pennsylvania, USA; I am actually married and have three cats. (Guess what one of them is named?) I am the "OpenInteract" guy, which could be good or bad.

Journal of lachoy (1663)

Wednesday August 31, 2005
09:03 AM

A proxy warning with Spring

[ #26527 ]

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:

<bean id="myCommandTarget"
    class="eg.MyCommand" />

<bean id="myCommand"
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="target" ref="myCommandTarget" />
    ...
</bean>

And then try to dynamically assign the 'operator' property:

    try {
        Command cmd = (Command)ctx.getBean( "myCommand" );
        BeanWrapper bw = new BeanWrapperImpl( cmd );
        bw.setPropertyValue( "operator", "chucky" );
    }
    catch ( BeansException e ) {
        System.out.println( "Caught BeansException: " + e.getMessage() );
    }

You'll get an error 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:

<bean id="myCommand"
    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <b>&lt;property name="proxyTargetClass" value="true" /></b>
    &lt;property name="target" ref="myCommandTarget" />
    ...
&lt;/bean>

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.

Posted from cwinters.com; read original

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.