Announcement Announcement Module
Collapse
No announcement yet.
Proxying a BeanFactory Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Proxying a BeanFactory

    How can I proxy an object returned by a FactoryBean? Specificly, I want to put a DebugInterceptor around a RemoteStatelessSessionProxyFactoryBean. The problem is, it puts it around the FactoryBean, not what the FactoryBean returns (the proxy to the EJB)

    Here's an example:
    Code:
    <bean id="serviceProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator" lazy-init="false">
      <property name="beanNames">
        <value>userService,caseService,customerService,contactService</value>
      </property>
      <property name="interceptorNames">
        <list>
          <value>debugInterceptor</value>
        </list>
      </property>
    </bean>
    
    <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor" />
    
    <bean id="userService" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean" lazy-init="true" singleton="true">
      <property name="businessInterface">
        <value>mypackage.UserService</value>
      </property>
      <property name="jndiName">
        <value>UserServiceBean-v1.6.0.0</value>
      </property>
      <property name="jndiTemplate">
        <ref bean="jndiTemplate"/>
      </property>
    </bean>
    What that produces is entries in my log of:
    Code:
    Debug interceptor&#58; count=1 invocation=&#91;Invocation&#58; method=&#91;public abstract java.lang.Object org.springframework.beans.factory.FactoryBean.getObject&#40;&#41; throws java.lang.Exception&#93; args=null&#93; target is of class &#91;org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean&#93;&#93;
    Debug interceptor&#58; next returned
    ... which isn't very helpful.

  • #2
    To proxy BeanFactory returned Object instead of BeanFactory itself you can apply your interceptors using ProxyFactoryBean:
    Code:
    <bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
      <property name="target">
        <bean class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"> 
          <property name="businessInterface"> 
            <value>mypackage.UserService</value> 
          </property> 
          <property name="jndiName"> 
            <value>UserServiceBean-v1.6.0.0</value> 
          </property> 
          <property name="jndiTemplate"> 
            <ref bean="jndiTemplate"/> 
          </property> 
        </bean>
      </property>
      <property name="interceptorNames">
       <list>
        <value>debugInterceptor</value>
       </list>
      </property>
    </bean>

    Comment


    • #3
      Thanks for the suggested solution.

      That works, but is there no way an autoproxy can be used? I've got a lot of services that I'd rather not have to manually apply the aspects to. :? Not being able to proxy FactoryBeans seems like a pretty significant limitation for the AOP framework considering how important FactoryBeans are to the Spring framework...

      Comment


      • #4
        I do not know if this will make things easier for you. You can reduce the typing by using an abstract template and inheriting from it:
        Code:
        <!-- Requires Spring 1.1 -->
        <bean id="interceptorStack" class="org.springframework.aop.framework.ProxyFactoryBean" abstract="true">
          <property name="interceptorNames"> 
           <list> 
            <value>debugInterceptor</value> 
            <value>interceptor2</value> 
            <value>interceptor3</value> 
           </list> 
          </property> 
        </bean> 
        
        <bean id="userService" parent="interceptorStack">
          <property name="target"> 
            <bean class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"> 
              <property name="businessInterface"> 
                <value>mypackage.UserService</value> 
              </property> 
              <property name="jndiName"> 
                <value>UserServiceBean-v1.6.0.0</value> 
              </property> 
              <property name="jndiTemplate"> 
                <ref bean="jndiTemplate"/> 
              </property> 
            </bean> 
          </property> 
        </bean>

        Comment


        • #5
          I still think not being able to proxy FactoryBeans is a problem, but the abstract template solution addresses my immediate problem quite well. Thanks!

          Comment


          • #6
            btw: As written, that doesn't work -- CGLib complains about not being able to proxy a final class because it's trying to proxy a java.lang.Proxy using Proxy's interface. The solution is to specify the proxyInterfaces to the ProxyFactoryBean.

            ie,
            Code:
            <bean id="userService" parent="serviceInterceptorStack">
              <property name="proxyInterfaces">
                <value>mypackage.UserService</value>
              </property>
              <property name="target">
                <bean class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
                  <property name="businessInterface">
                    <value>mypackage.UserService</value>
                  </property>
                  <property name="jndiName">
                    <value>UserServiceBean-v1.6.0.0</value>
                  </property>
                  <property name="jndiTemplate">
                    <ref bean="jndiTemplate"/>
                  </property>
                </bean>
              </property>
            </bean>
            That kind of redundancy is annoying, so I overrode ProxyFactoryBean's setBeanFactory method with the following code:
            Code:
            if &#40;getProxiedInterfaces&#40;&#41;.length == 0&#41; &#123;
              final Class targetClass = getTargetSource&#40;&#41;.getTargetClass&#40;&#41;;
              if &#40;java.lang.reflect.Proxy.class.isAssignableFrom&#40;targetClass&#41; ||
                  net.sf.cglib.proxy.Proxy.class.isAssignableFrom&#40;targetClass&#41;&#41; &#123;
                final Class&#91;&#93; classes = targetClass.getInterfaces&#40;&#41;;
                for &#40;int i = 0; i < classes.length; i++&#41; &#123;
                  addInterface&#40;classes&#91;i&#93;&#41;;
                &#125;
              &#125;
            &#125;
            that removes the need to specify the proxyInterfaces in the ProxyFactoryBean definition.

            Comment


            • #7
              I've added an issue in JIRA for this: http://opensource.atlassian.com/proj...browse/SPR-337.

              I'll try to look at it in the 1.1.2 timeframe. Not sure it's easy to address, but we'll see.

              Comment


              • #8
                Originally posted by Rod Johnson
                I've added an issue in JIRA for this: http://opensource.atlassian.com/proj...browse/SPR-337.

                I'll try to look at it in the 1.1.2 timeframe. Not sure it's easy to address, but we'll see.

                Was this ever resolved? The link goes to a non-existent error (not sure if that's a good thing or not!)

                Comment


                • #9
                  Originally posted by aidano
                  Originally posted by Rod Johnson
                  I've added an issue in JIRA for this: http://opensource.atlassian.com/proj...browse/SPR-337.

                  I'll try to look at it in the 1.1.2 timeframe. Not sure it's easy to address, but we'll see.

                  Was this ever resolved? The link goes to a non-existent error (not sure if that's a good thing or not!)
                  Remove the dot (.) at the end of the jira link. The issue has not been addressed.

                  Comment

                  Working...
                  X