Page 1 of 3 123 LastLast
Results 1 to 10 of 21

Thread: Need for thread-level scope (ThreadScope) in Spring

  1. #1
    Join Date
    Feb 2006
    Posts
    164

    Default Need for thread-level scope (ThreadScope) in Spring

    Hi, Costin, David and everyone.

    It was interesting to note, after the many forum threads on which I've raised this problem here:

    http://forum.springframework.org/showthread.php?t=24569
    http://forum.springframework.org/showthread.php?t=25938
    http://forum.springframework.org/showthread.php?t=28317

    ... and at javaranch, that whoever wrote this Custom Scopes section picked "ThreadScope" as the stated example. Hmmm...


    But seriously, the latest Spring reference documentation mentions thread-level scoping (aka ThreadScope aka "per-thread singleton"). Maybe it was in a previous release as well, but it sounds like Spring is at least thinking about going in that direction, and that is a good thing, I believe.

    On that subject, sorry David, but I don't consider the classloader singleton a feature of java. See thread:

    http://forum.springframework.org/sho...t=28317&page=2

    I think what MOST developers really want is a JVM-level singleton pattern, but such does not exist, so we muddle through as best we can with the classloader "feature". To date, no one has given me a real-world application requirement for the classloader-level singleton. Several developers have given me such requirements for both the JVM-level and the thread-level singleton pattern. Please enlighten me if you think I'm missing something big here.

    Costin, the latest spring-reference.pdf in Spring version 2.0-rc3 clarifies this as we were discussing in one of the above threads, i.e Spring singleton is NOT Gang-Of-4 Singleton pattern. Thanks for making that clear, but I think you may also need to clarify what you meant in there by a Spring "container". Like the word "singleton", J2EE developers think of the word "container" in certain "contexts", if you will ...and there are assumptions, sometimes unconscious, that developers will make, unless they are SPECIFICALLY told otherwise...as you have done with the word "singleton" in your documentation.

    My understanding of that use of the word "container" is that the container is the instantiated ApplicationContext, yes? If so, it may be unclear in other developers' minds, just exactly what is a Spring "container", and what are the high-level implications.

    We are about to heavily invest in Spring across all our layers, in a new development project. Most of Spring is flowing nicely in it, but there is one glaring problem, a problem that I believe many developers are about to discover the hard way, a problem about which I'm still hoping I'm just missing something fundamental in Spring. The problem is this:

    Without some kind of thread-level singleton (ThreadScope as you call it), app developers are forced to either:

    (a) pass, via constructor arg or method arg, your "container" (i.e. the instantiated ApplicationContext) down to ALL objects in ALL layers...except possibly the Web layer, thanks to the new scopings...down to all objects in all layers that need its instantiated singleton beans or...

    (b) write their own custom thread-level scope, as shown in the 2.0-rc3 documentation in Section 3.4.4 Custom Scopes, and as we discussed and coded in previous forum threads.

    Ben

  2. #2
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    I'll leave the scoping subject to the initial author (i.e. Rick who's now on holidays).

    Costin, the latest spring-reference.pdf in Spring version 2.0-rc3 clarifies this as we were discussing in one of the above threads, i.e Spring singleton is NOT Gang-Of-4 Singleton pattern. Thanks for making that clear, but I think you may also need to clarify what you meant in there by a Spring "container". Like the word "singleton", J2EE developers think of the word "container" in certain "contexts", if you will ...and there are assumptions, sometimes unconscious, that developers will make, unless they are SPECIFICALLY told otherwise...as you have done with the word "singleton" in your documentation.

    My understanding of that use of the word "container" is that the container is the instantiated ApplicationContext, yes? If so, it may be unclear in other developers' minds, just exactly what is a Spring "container", and what are the high-level implications.
    The container would be the BeanFactory (that is a parent of ApplicationContext) that produces beans based on your configuration. As the scoped/singleton is part of the definition, is going to be applied in the context of the BeanFactory/ApplicationContext = container that instantiated it.
    Note that this is per definition - that is if you have class A which is defined as bean X and bean Y then there will be two singletons of the same class - one for bean X and one for bean Y.
    So to answer to your question yes, a container is a instantiated set of bean definitions (for example an XML file).

    Most of Spring is flowing nicely in it, but there is one glaring problem, a problem that I believe many developers are about to discover the hard way, a problem about which I'm still hoping I'm just missing something fundamental in Spring. The problem is this:

    Without some kind of thread-level singleton (ThreadScope as you call it), app developers are forced to either:
    I recall discussing about this issue some time ago - basically through IoC one doesn't need a ThreadLocal (i.e. a global registry) since components are wired automatically by the container that instantiate them. If you need an dependency/parameter then inject it into your bean.
    If you need to look it up (for example you have dynamic behavior) then you can get a hold of the application context (through ApplicationContextAware interface) and query for the beans you need.
    Spring does use some ThreadLocals internally but only for some components where information that is bound only to the local thread has to be shared (i.e. transaction started for example).
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  3. #3
    Join Date
    Feb 2006
    Posts
    164

    Default

    Quote Originally Posted by Costin Leau
    I recall discussing about this issue some time ago
    That was probably this:

    Quote Originally Posted by trisberg
    Well, you need to pass some things around. You service layer is going to need a DAO and a TransactioManager and booth of these needs to have a reference to the DataSource - so somehow you must "pass" this stuff around either during construction of the objects or when you call the methods. That's why dependency injection became so popular and for me is the preferred way to write these type of systems.
    ...from this forum thread, where we were discussing possible need for ThreadLocal:

    http://forum.springframework.org/sho...t=24569&page=4


    Quote Originally Posted by Costin Leau
    basically through IoC one doesn't need a ThreadLocal (i.e. a global registry) since components are wired automatically by the container that instantiate them. If you need an dependency/parameter then inject it into your bean.
    If you need to look it up (for example you have dynamic behavior) then you can get a hold of the application context (through ApplicationContextAware interface) and query for the beans you need.
    As Thomas and I were discussing back then, if Object A instantiates the Spring "container" and then instantiates object B, and object B instantiates object C, and object C needs object A's instantiated container (i.e. the "live" beans in it, which may now have had instance-level fields set by object A, or by the beans interacting among themselves in the container)...

    ...how is object C going to be able to access that instantiated container unless object A passes it (by reference) down to object B, which would then pass it down to object C?

    Ben

  4. #4
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    It depends on what your use case is - if the same object has to be used in several places you can inject it all over. As for using a container aware bean, if you do need such functionality (you will be doing dependency lookup instead of having the dependencies injected) you can mark the appropriate beans with ApplicationContextAware interface for example.
    Inside Spring source code, the threadLocals for passing objects local to the thread - when doing transaction management the current transaction is stored on a thread so that components that handle this can check if one has been already started.
    If you have such a case then sure, use thread locals since it offers a thread bound scoped repository.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  5. #5
    Join Date
    Feb 2006
    Posts
    164

    Default

    Hi, Costin.

    Reading up on ApplicationContextAware in the Spring In Action book (p 87), it seems to me that ApplicationContextAware only allows the bean to know which ApplicationContext (i.e. container) it lives. It doesn't change the "scope of things" (if you will ) The author gives the analogy of The Matrix (movie). The main character learns that he lives in a Matrix, but that doesn't mean that he can live as a "reference singleton" in a second Matrix at the same time. ThreadScope would allow such.

    I'm thinking that the answer is either going to turn out to be either (a) simple java which is the kludge I'm trying to avoid, or (b) some thread-local magic that Spring is doing behind the scenes, of which I'm as of yet unaware..due to limitations of MY Matrix .

    Let's talk about the simple java, and the answer may emerge from that. Here is a simple example I created, one that exhibits the problem:

    First, objectA, as discussed above:

    Code:
    package test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    public class ClassA {
    
      /**
       * @param args
       */
      public static void main(String[] args) {
        ClassA objA = new ClassA();
        objA.sayInitialBeanGreeting();
        objA.callLowerObjects();
      }
      private void callLowerObjects() { 
        ClassB objB = new ClassB();
        objB.sayTheModifiedGreeting();
      }
    
      public void sayInitialBeanGreeting() {
        ApplicationContext appContext = new FileSystemXmlApplicationContext("C:/AccuRevWS/SpringTest/ApplicationContext.xml");
        GreetingService greetingService = (GreetingService) appContext.getBean("greetingService");
        greetingService.sayGreeting();
        greetingService.setGreeting("Ola!");
        greetingService.sayGreeting();
      }
    }
    Then objectB, as discussed:

    Code:
    package test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    
    public class ClassB {
    
      public void sayTheModifiedGreeting (){
        ApplicationContext appContext = new FileSystemXmlApplicationContext("C:/AccuRevWS/SpringTest/ApplicationContext.xml");
        GreetingService greetingService = (GreetingService) appContext.getBean("greetingService");
        String theHopefullyModifedGreeting = greetingService.sayGreeting();  
        if (!theHopefullyModifedGreeting.equals("Ola!")) {
          System.out.println("Oops! Spring container is not acting like a true container, to my way of thinking. What am I missing?");     
        }
      }
    }
    (I dropped objectC in the interest of brevity, since the same concept obviously holds for objectB.)

    Now, the simple bean interface:

    Code:
    package test;
    public interface GreetingService {
      public String sayGreeting();
      public String getGreeting();
      public void setGreeting(String greeting);
    }
    ...and its implementation:

    Code:
    package test;
    
    public class GreetingServiceImpl implements GreetingService {
      private String greeting;
      public GreetingServiceImpl(){}
      public GreetingServiceImpl(String greeting) {
        this.greeting = greeting;
      }
      public String sayGreeting() {
        System.out.println(this.greeting);
        return this.greeting;
      }
      public String getGreeting() {
        return greeting;
      }
      public void setGreeting(String greeting) {
        this.greeting = greeting;
      }
    }
    ...and finally the ApplicationContext.xml:

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
    <beans>
        <bean id="greetingService" class="test.GreetingServiceImpl">
            <property name="greeting">
            	<value>Buenos Dias</value>
            </property>
        </bean>
    </beans>
    When I run this, it prints out the "Oops..." message, as I suspected. How do I get this to print "Ola!", i.e. keep the singleton bean alive in the container throughout the run of the app, without either (a) passing around the appContext by reference (ugly) or (b) implementing some kind of ThreadScope mechanism?

    Ben

  6. #6
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    The problem with your approach is that you are not really using the IoC - your objects are actually totally aware of the container and they are doing dependency lookup.
    A first step would be to first remove the bootstrap sequence from your object A into a Main class for example:

    Code:
    package test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.FileSystemXmlApplicationContext;
    
    public class Main {
    
      /**
       * @param args
       */
      public static void main(String[] args) {
        ApplicationContext appContext = new FileSystemXmlApplicationContext("C:/AccuRevWS/SpringTest/ApplicationContext.xml");
        GreetingService greetingService = (GreetingService) appContext.getBean("greetingService"); 
        <!-- start the greetings -->
        greetingService.startGreetings();
        appContext.close();
      }
    }
    and let bean A and B to simply execute the greetings w/o any awareness of the Spring or the IoC container (btw, by loading manually the container you create several instances of the Spring so you actually have several containers running - this is not what you want).

    In your case you have a dependency from B to A- based on the behavior of B you'd like to make some actions. You have several choices:

    1. use AOP to wrap A into a proxy so that you can intercept the output and modify it or inform other parties (basically an event mechanism).
    2. inject B into A - this makes sense you have the dependency anyway so instead of relying on a thread local you simply have the reference yourself; this means that B will become:

    Code:
    public class ClassB {
    
      private GreetingService greetingService;
      // setter somewhere
      
      public void sayTheModifiedGreeting (){
        String theHopefullyModifedGreeting = greetingService.sayGreeting();  
        if (!theHopefullyModifedGreeting.equals("Ola!")) {
          System.out.println("Oops! Spring container is not acting like a true container, to my way of thinking. What am I missing?");     
        }
      }
    }
    and the context :

    Code:
        <bean id="greetingService" class="test.GreetingServiceImpl">
            <property name="greeting">
            	<value>Buenos Dias</value>
            </property>
        </bean>
    
        <bean id="beanB" class="test.beanB">
          <property name="greetingService" ref="greetingService"/>
        </bean>

    I think the problem in your case is how the container and the components are actually started.
    Think of the servlet container - there your webapp is automatically started by the web container and the spec define the lifecycle of your servlets/listeners and so on.
    There Spring is started through a listener but at no point the developer codes how the webapp is started - this is rather taken care off through the servlet/actions/(put your web framework term in here) mappings - page X triggers Action Y.

    The same happens inside a standalone app - your components have to be totally separated from the Spring container. Have a main class that starts the container and then, inside the main class start the 'server' -i.e. the bean that triggers your application startup (in case of a GUI it can be something like 'startScreen').
    The container is started so the beans are already instantiated and the deps injected so you don't have to do this yourself.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  7. #7
    Join Date
    Feb 2006
    Posts
    164

    Default

    Hi, Costin. Sorry, but what you are proposing seems overly complicated (on the surface at least), and could be solved much simpler and more elegantly with a simple ThreadScope implementation in Spring (simple from the Spring user's point of view, anyway). Allow me to explain why I say that:

    Quote Originally Posted by Costin Leau
    The problem with your approach is that you are not really using the IoC - your objects are actually totally aware of the container and they are doing dependency lookup.
    (1) Depends on what you mean by "dependency lookup". This isn't "my" approach. This is the approach used in Spring In Action book, for both the initial GreetingService example and the Knight/Quest example. In the Knight/Quest example, the author gives a pretty good example of what is a "dependency lookup" and then a Spring IoC re-write that eliminates the "lookup". It's supposed to give us a basic understanding of IoC and how to use it, and nowhere in there does it show any kind of "startService" method (i.e. a listener pattern). I imagine lots of other developers are using that "Understanding Inversion Of Control" chapter as a basic Spring design pattern. Other than the ThreadScope issue I'm raising, it's working ok for us as-is, but if it's now considered, by the Spring team, to be an anti-pattern for IoC, I'd like know about it sooner rather than later.

    Quote Originally Posted by Costin Leau
    (btw, by loading manually the container you create several instances of the Spring so you actually have several containers running - this is not what you want).
    I agree. This is not what I want to do. In fact, as you can see, it does not even work.

    (2) What, exactly, is in your startGreeting method? I mean, you're not really showing a full working example yet, so it's hard for me to guess what its consequences (good and bad) are. Reason I ask is that depending on what's in it, I'm guessing that you are either (a) limiting yourself to a stand-alone app (which some kind of ThreadScope or just a simple but ugly object reference pass-down does not) or (b) having to deal with the relatively messy threading, synchronization and lifecycle issues (just like the servlet container has to) or (c) putting in some Spring magic that will elegantly solve the problem for both stand-alone apps and servlet-contained web apps.

    I'm hoping for (c).

    Ben

  8. #8
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    but if it's now considered, by the Spring team, to be an anti-pattern for IoC, I'd like know about it sooner rather than later.
    I haven't read Spring In Action and I don't have the whole context - however as I understand the Knight/Quest example shows how to eliminate the dependency lookup.
    This being said, if your webapp is running inside a Spring context you don't have to use dependency lookup - even if you want to get a hold of the application context you can use ApplicationContextAware.
    What, exactly, is in your startGreetings method?
    It was just a dummy method to complete my explanation - you can simply consider it to be something like:
    public void startGreetings()
    {
    greetingService.sayGreeting();
    greetingService.setGreeting("Ola!");
    greetingService.sayGreeting();
    }

    Not sure if it was discussed before, but ThreadLocals are scoped to a thread - on each thread you'll have to reinitialize the thread local value otherwise the components will get NPE.

    When I run this, it prints out the "Oops..." message, as I suspected. How do I get this to print "Ola!", i.e. keep the singleton bean alive in the container throughout the run of the app, without either (a) passing around the appContext by reference (ugly) or (b) implementing some kind of ThreadScope mechanism?
    I missed this question - since you have to reuse the container you have several posibilities (order does not count):

    1. - a thread local (however consider what happens when the thread ends)
    2. - use a common location such as BeanFactoryLocator so that different applications within the same VM can get a hold of the Spring application context (this includes well known locations such as JNDI or Singletons).
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  9. #9
    Join Date
    Feb 2006
    Posts
    164

    Default

    Thanks for taking the time to help me figure this out, Costin.

    Quote Originally Posted by Costin Leau
    Not sure if it was discussed before, but ThreadLocals are scoped to a thread - on each thread you'll have to reinitialize the thread local value otherwise the components will get NPE.
    That (above) is fair, and your 1. makes sense.

    Your 2. does not, or at least, not for my particular pattern need. I need the bean to live and die with the top-level objectA, and the values set by objectA to only be seen by objects that objectA calls. Your 2. behavior looks more like JVM-level singleton behavior, which is not the same. All objects in all threads would see the same value of your live bean. I need the bean value to be different for each thread, i.e. each run, i.e. each request. Hmmmm..... I just thought of something:

    The pattern I need is almost exactly analogous to the new Request Bean Scope in the 2.0 documentation, except that I have a web service running (using Spring Web Services) as opposed to a "normal" http web app.

    Gosh, maybe, since the Web Service is just another flavor of web app (isn't it?), I can simply use the new Request Bean scope!

    That way, my appContext comes alive and stays alive all through the Request cycle, and dies when the request cycle ends.

    Am I making sense? Should I discuss this with Arjen?

    Ben

  10. #10
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    Scoping sound like a great candidate for your problem.
    Since your dealing with Web Services you should definitely take a look at SpringWS - feel free to open the issue with Arjen; the more he knows about the problem, the more appropriate the solution will be.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

Posting Permissions

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