1

Have a service that exposes crypto functions. We don't need a clean up nor do I want objects to be created every time/ every session. But i need a separate object per thread.

In a web app - will the scope be the web container's thread pool ?

Is it same in spring 3 and 4 implementation?

Another place we plan to use this is to cache SimpleDateFormat objects. Again don't need a clean up method.

tgkprog
  • 4,493
  • 4
  • 41
  • 70

4 Answers4

5

Since version 3.0, Spring has a basic notion of thread scope : the SimpleThreadScope. It looks like it can feet what you ask, but it has some limitations :

  • it is not registered by default with containers but must explicitely be
  • it performs no cleanup on its beans.

If you can accomodate with those limitations, you can register the scope programatically :

Scope threadScope = new SimpleThreadScope();
appContext.getBeanFactory().registerScope("thread", threadScope);

or in xml config :

<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
    <property name="scopes">
        <map>
            <entry key="thread">
                <bean class="org.springframework.context.support.SimpleThreadScope"/>
            </entry>
        </map>
    </property>
</bean>

This works the same in Spring 3 and Spring 4. If you want to inject a thread scoped bean in a singleton bean, you have to declare an aop scoped-proxy on it :

<bean id="bar" class="x.y.Bar" scope="thread">
    <property name="name" value="Rick"/>
    <aop:scoped-proxy/>
</bean>
<bean id="foo" class="x.y.Foo">
    <property name="bar" ref="bar"/>
</bean>

(All examples from Spring Framework Reference Documentation).

If you have to do some cleanup, you can look at this document Spring by Example Custom Thread Scope Module that shows an enhanced version of SimpleThreadScope.

But I am not sure you really want that, unless all threads continuously use the thread scoped beans, or memory is not really a concern. Because in that design pattern, if only one session at a time needs the bean, but it is served by several threads (assuming other requests do not need the bean), all the threads will get a different instance of the bean, whereas with a pool only one instance would have been used.

You will find an example of using a CommonsPoolTargetSource with Apache Common Pools in this other post from SO How to pool objects in Spring?. Extract from the post :

<bean id="simpleBeanTarget" class="com.bean.SimpleBean" scope="prototype"/>

<bean id="poolTargetSource" class="org.springframework.aop.target.CommonsPoolTargetSource">
    <property name="targetBeanName" value="simpleBeanTarget" />
    <property name="maxSize" value="2" />
</bean>

<bean id="simpleBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="targetSource" ref="poolTargetSource" />
</bean>

The example use a ProxyFactoryBean to give an aop proxy to allow injection of simpleBean in a singleton bean, provided it is injected as an interface.

Community
  • 1
  • 1
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Yeap this is what I wanted to hear about. We are using this, just surprised that few others are using it. Do you use this actively? Do you evaluate services to see if they can be thread level beans and this have less beans instantiated and more reused at run time? – tgkprog Aug 22 '14 at 13:57
  • 1
    No, but I once used UnboundID LDAP SDK for Java, and they have different memory pools for saving LDAP connections, including one that *maintains a dedicated connection for each thread*. Documentations stated *This implementation eliminates the need to determine how best to size the connection pool, and it can eliminate contention among threads when trying to access a shared set of connections*, but remaining parts was clear about the non thread backed implementation being the prefered one. My understanding was the thread implementation existed only for its easy config in non prod environments. – Serge Ballesta Aug 22 '14 at 14:29
  • Thanks have marked your answer as right for now, will give bounty in a day or two if no other awesome answer :-) – tgkprog Aug 22 '14 at 14:46
  • In practice all threads will be in a pool and resused - the app container thread pool (tomcat/jboss atleast) use a thread pool for servlet processing. So in practice less objects are created. Can confirm this by printing something in constructor or keeping a static instance count – tgkprog Aug 25 '14 at 19:49
  • https://javaeeinsights.wordpress.com/2015/07/21/register-spring-custom-scope-using-java-config/ shows how to configure with annotations. – downeyt Aug 02 '18 at 16:12
2

ThreadLocal has thread scoped objects. Secondly, SimpleDateFormat and DateFormats in general are not synchronized. So be aware of thread issues there. By the way, when you say 'per thread', did you mean per request? As the java doc for SimpleThreadScope says, it is typically preferable to use RequestScope in web environments.

Spring can create beans with specific scopes like prototype, request, you might want to consider. And as @Sairam mentioned, life cycle management is also worth a thought.

Atul
  • 2,673
  • 2
  • 28
  • 34
  • See about SimpleThreadScope this is what i was looking for. I dont think we should blindly use request scope. Its easy to choose the wrong one but if you know the difference and each class has updated note on how to use, then thread scope means less objects created and less garbage collection at run time. Means better app performance. – tgkprog Aug 22 '14 at 13:59
0

In spring framework, to get a separate object per thread, we could achieve this by having the bean scope as prototype.

From the reference.,

<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>

There is no change in Spring 3 & 4 with respective to this specific case. Regarding the clean up of objects, prototype scope behaves differently.,from the same reference document.,

In contrast to the other scopes, Spring does not manage the complete lifecycle of a prototype bean: the container instantiates, configures, and otherwise assembles a prototype object, and hands it to the client, with no further record of that prototype instance. Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding.

Sairam Krish
  • 10,158
  • 3
  • 55
  • 67
  • This is the worst, every time a new one is created. session is better, thread level is best (if applicable to a particular bean - that does a service, not thread safe/ needs state during call but not after; thus cannot be application scope. ) – tgkprog Aug 22 '14 at 14:02
0

An solution for you:

  1. provide your own FactoryBean to create your service bean.
  2. in your FactoryBean, you shuld use ThreadLocal to hold your bean, if not exist, create one and save it to ThreadLocal, next time, retrieve it from ThreadLocal!
Laurence Geng
  • 424
  • 3
  • 9
  • @PavelHoral Ridiculous! – Laurence Geng Aug 23 '14 at 03:44
  • I have realized that it is not that bad, but I can not remove the downvote unless you edit the answer. Still I think that if you want to use ThreadLocal, you should make sure to clean up. You can not do that using FactoryBean. Better approach for expensive objects is to use pooling as Sergei wrote in his answer. – Pavel Horal Aug 23 '14 at 06:25