Results 1 to 6 of 6

Thread: improper use of ThreadLocalTargetSource?

  1. #1
    Join Date
    Mar 2005
    Posts
    11

    Default improper use of ThreadLocalTargetSource?

    We are in the process of converting from another framework to Spring.

    In our model tier service objects, we have a ServiceContext that we pass around to keep from having to pass it on every method as an argument. For instance, one thing we keep in it is security information about the current user.

    I was thinking that I could make it a ThreadLocal-scoped object and have Spring inject it into all the services. Then, I could get it from Spring the first time in the Web tier, load the current user info into it, then later access the same object from the services for the current thread.

    This works on the first service. However, that service (call it ServiceA) invokes a second service (ServiceB), and ServiceB's ServiceContext is a different instance, and so does not have the user information. ServiceB is injected into ServiceA.

    Am I misunderstanding what ThreadLocalTargetSource is supposed to do for you? I modelled my usage of it after this example (thanks to the author!), so I think I am using it correctly:

    http://forum.springframework.org/vie...targetso urce

    Singleton and prototype do not work here, as they would not have the proper scope. Are there any other approaches I could consider?

    Thanks

  2. #2
    Join Date
    Aug 2004
    Location
    Amsterdam, Netherlands
    Posts
    450

    Default

    How many times did you define target source? For every definition of the target source, an object is created (per thread of course). You should only define the targetsource once, so only one object per thread is created.

    If this isn't the problem, could you show some config xml?

    regards,
    Alef Arendsen
    Alef Arendsen
    SpringSource
    http://www.springsource.com

  3. #3
    Join Date
    Mar 2005
    Posts
    11

    Default

    Alef,

    Thanks for the reply!

    No, I don't think I did that, unless I'm misunderstanding the question. Here's my config.xml:
    Code:
    <bean id="serviceContextTarget" class="com.myco.ServiceContext" singleton="false">
    </bean>
    
    <bean id="serviceContext" class="org.springframework.aop.framework.ProxyFactoryBean">
      <property name="proxyInterfaces">
        <value>com.myco.IServiceContext</value>
      </property>
      <property name="singleton">
        <value>false</value>
      </property>
      <property name="targetSource">
        <bean class="org.springframework.aop.target.ThreadLocalTargetSource">
          <property name="targetBeanName"><value>serviceContextTarget</value></property>
        </bean>
      </property>
    </bean>
    
    <bean id="baseService" abstract="true" class="com.myco.BaseService">
      <property name="serviceContext"><ref bean="serviceContext"/></property>
    </bean>	
    
    <bean id="serviceATarget" class="com.myco.ServiceA" parent="baseService">
      <property name="serviceB"><ref bean="com.myco.IServiceB"/></property> 
    </bean>
    
    <bean id="com.myco.IServiceA" parent="springProxy">
      <property name="target"><ref bean="serviceATarget"/></property>
    </bean> 
    
    <bean id="serviceBTarget" class="com.myco.ServiceB" parent="baseService">
    </bean>
    
    <bean id="com.myco.IServiceB" parent="springProxy">
      <property name="target"><ref bean="serviceBTarget"/></property>
    </bean>
    BaseService is the base service class from which all others inherit. I'm trying to keep the detail down to a reasonable level here so I left out the springProxy parent, which is just a TransactionProxyFactoryBean.

    Users of serviceA request the interface com.myco.IServiceA from the Spring application context.

    Any suggestions?

  4. #4
    Join Date
    Aug 2004
    Location
    Amsterdam, Netherlands
    Posts
    450

    Default

    Well, you haven't defined the targetsource twice but it's a prototype (you've set the singleton property to false). This means for every <ref bean="proxy"/> you're getting a new instance of the proxy and a new instance of the targetsource. Per targetsource there will be one target and since this is a thread local targetsource, you're getting a threadlocal object per proxy.

    You've ref'ed the proxy twice (abstract=true just means it's inheriting the properties, so in fact you have two separate bean definitions each of them referencing the proxy once: so two proxies).

    For every proxy one targetsource, so two targetsource, two different instances.

    Did you try setting the proxy's singleton property to true (which is the default, so leaving it out should work also).

    regards,
    Alef Arendsen
    Alef Arendsen
    SpringSource
    http://www.springsource.com

  5. #5
    Join Date
    Mar 2005
    Posts
    11

    Default

    Well.... :oops:

    It turns out my mistake was in how I was wiring things up in my test cases. I won't get into the details, suffice it to say it was a stupid mistake caused by trying to change too many things at once.

    It seems to work both with the ProxyFactoryBean as a Singleton and as a Prototype. However, I like your suggestion, it makes sense to me, so I'll use a Singleton and save the resources. Thanks for the tip, it was still helpful.

    BTW - now that you're familiar with my case - let me ask you a bit of an architectural question. If you want to say no thanks and send me to the other forum for that, I'll understand.

    I saw a comment in one of the forums by Rod Johnson about ThreadLocalTargetSource that seemed interesting. He commented that he hadn't seen a good usage for it yet.

    I was a bit surprised that no one else had tried to do what we are doing here with a ServiceContext. How do other people pass this sort of information around amongst their services? Via the database? Do you think Mr. Johnson would agree that this is a good usage of ThreadLocalTargetSource, or is there another approach that you would recommend based on the Spring framework?

    BTW, I am really enjoying not having to restart my application every time I change a test case!

    Thanks!

  6. #6
    Join Date
    Aug 2004
    Location
    Toronto, Canada
    Posts
    736

    Default

    This seems like a fairly decent use for ThreadLocalTargetSource. It's obviously much more applicable in request driven environment like a web-app where there is a clean request which bubbles down and then back up.

    However, I would suggest that ideally there's really a limited amount of shared state you would need to make available to different services like this. It's really crosscutting state like a security context or something of that nature, whereas I would prefer to pass most state data directly to methods that need it.
    Colin Sampaleanu
    SpringSource - http://www.springsource.com

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •