Correctly (not) disposing of singleton Spring beans - java

Consider the case where I have a Spring Service bean, which depends on other beans that may expose the AutoCloseable interface. I'll ask this question generically and will later explain my specific need.
public class ServiceBean {
#Autowired private ResourceBean resource; //Resource is Closeable
}
According to configuration, under certain configurations Resource is a global singleton, and in other cases it is a prototype. Since I am writing a library, I was asked to provide degrees of flexibility.
If resource is a singleton, it should never be close()d until the ApplicationContext is shut down. Otherwise, if resource was created prototypely for my instance of ServiceBean (which is a prototype, I know this by design), then it shall be disposed (close()d) when the lifecycle of ServiceBean ends.
Step 1: make ServiceBean closeable
Not a bad thing to do. Best practices in programming say that when your class depends on disposable resources, it should be declared disposable and included in try-with-resources blocks
public class ServiceBean implements AutoCloseable {
#Autowired private ResourceBean resource; //Resource is Closeable
public void close() throws Exception {
resource.close(); //what the!!!
}
}
The problem with this setup is that if resource is a prototype, it will be closed on first instance.
Spring provides methods isPrototype and isSingleton that take String as argument, so I deduce they are meant for bean names, which I don't (want) to know in this context
Question: what should be the correct way to dispose prototype resources in prototype beans? Spring AFAIK disposes only of singletons when ApplicationContext shuts down
My specific case
I have a ThreadPoolTaskExecutor to inject. It may be a singleton or prototype object, and the shutdown is useful to clear the pool from outstanding threads

I have come with an idea (a mad idea, not yet tested).
The injected resource bean could leverage the BeanFactory<> class.
Declare Resource by means of a factory
public class ResourceBeanFactoryBean extends AbstractFactoryBean
Parameterize the singletonness
AbstractFactoryBean exposes isSingleton
Wrap the returned bean into a non-closeable when the bean is singleton
protected ResourceBean createInstance() {
return isSingleton() ? myBean : wrapNonCloseable(myBean);
}
Where myBean is the instance you would have created normally, and wrapNonCloseable is a utility method that extends the close method to do nothing
protected MyResourceBean wrapNonCloseable(MyResourceBean bean) {
return new MyResourceBean()
{
//Delegate all methods to the original bean
public void close(){}
}
}

Related

Autowire of prototype bean into prototype bean?

I'm working with some existing code and it is doing things I haven't seen before. I've dealt with autowiring prototype beans into singletons using method injection or getting the bean from the context using getBean(). What I am seeing in this code I am working on is a bean that is a prototype and retrieved using getBean(), and it has autowired dependencies. Most of these are singleton beans, which makes sense. But there is an autowire of another prototype bean, and from what I see, it does seem like it is getting a new bean. My question is when you autowire a prototype into a prototype, will that give you a new instance? Since the autowire request is not at startup but rather when this bean is created, does it go and create a new instance? This goes against what I thought about autowire and prototype beans and I wanted to hear an answer from out in the wild. Thanks for any insight. I'm trying to minimize my refactoring of this code as it is a bit spaghetti-ish.
example:
#Scope("prototype")
public class MyPrototypeClass {
#Autowired
private ReallyGoodSingletonService svc;
#Autowired
private APrototypeBean bean;
public void doSomething() {
bean.doAThing();
}
}
#Scope("prototype)
public class APrototypeBean {
private int stuffgoeshere;
public void doAThing() {
}
}
So when doSomething() in MyPrototypeClass is called, is that "bean" a singleton or a new one for each instance of MyPrototypeClass?
In your example, the APrototypeBean bean will be set to a brand new bean which will live through until the instance of MyPrototypeClass that you created is destroyed.
If you create a second instance of MyPrototypeClass then that second instance will receive its own APrototypeBean. With your current configuration, every time you call doSomething(), the method will be invoked on an instance of APrototypeBean that is unique for that MyPrototypeClass object.
Your understanding of #Autowired or autowiring in general is flawed. Autowiring occurs when an instance of the bean is created and not at startup.
If you would have a singleton bean that is lazy and that bean isn't directly used nothing would happen as soon as you would retrieve the bean using for instance getBean on the application context an instance would be created, dependencies get wired, BeanPostProcessors get applied etc.
This is the same for each and every type of bean it will be processed as soon as it is created not before that.
Now to answer your question a prototype bean is a prototype bean so yes you will receive fresh instances with each call to getBean.
Adding more explanation to #Mark Laren's answer.
As explained in Spring 4.1.6 docs
In most application scenarios, most beans in the container are
singletons. When a singleton bean needs to collaborate with another
singleton bean, or a non-singleton bean needs to collaborate with
another non-singleton bean, you typically handle the dependency by
defining one bean as a property of the other. A problem arises when
the bean lifecycles are different. Suppose singleton bean A needs to
use non-singleton (prototype) bean B, perhaps on each method
invocation on A. The container only creates the singleton bean A once,
and thus only gets one opportunity to set the properties. The
container cannot provide bean A with a new instance of bean B every
time one is needed.
Below approach will solve this problem, but this is not desirable because this code couples business code with Spring framework and violating IOC pattern. The following is an example of this approach:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
So, there are 2 desirable ways to solve this problem.
1. Using Spring's method injection
As name suggests, Spring will implement & inject our abstract method by using #Lookup annotation from Spring 4 or tag if you use xml version. Refer this DZone article.
By using #Lookup.
from Java Doc...
An annotation that indicates 'lookup' methods, to be overridden by the
container to redirect them back to the BeanFactory for a getBean call.
This is essentially an annotation-based version of the XML
lookup-method attribute, resulting in the same runtime arrangement.
Since:
4.1
#Component
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
#Lookup
public MyClass2 myClass2(){
return null; // No need to declare this method as "abstract" method as
//we were doing with earlier versions of Spring & <lookup-method> xml version.
//Spring will treat this method as abstract method and spring itself will provide implementation for this method dynamically.
}
}
The above example will create new myClass2 instance each time.
2. Using Provider from Java EE (Dependency Injection for Java (JSR 330)).
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public static class SomeRequest {}
#Service
public static class SomeService {
#Autowired
javax.inject.Provider<SomeRequest> someRequestProvider;
SomeRequest doSomething() {
return someRequestProvider.get();
}
}
The above example will create new SomeRequest instance each time.

start transaction AFTER not BEFORE start of synchronized method in singleton bean

I have a war file deployed in glassfish. We have a Singleton bean and we have 1 synchronized method in it.
#TransactionAttribute (TransactionAttributeType.REQUIRED)
public synchronized void do()
{
...
}
However, I am noticing that transaction is started before the method is called. How do I start a transaction after the caller obtains the lock on the bean class' monitor?
Thank you.
Update: We are just trying to have a bean method that can only be called by one thread at a time. We do not want any other thread to call this method until the previous thread is completely done with it. I had created another thread where I got the idea of using a singleton bean: synchronized method in stateless session bean not working as expected in glassfish
Update: After doing some reading, it seems I can create my own transactions UserTransaction. Will that be supported? Never mind. I got this error message:
Only session beans with bean-managed transactions can obtain UserTransaction
I think one way would be to move the synchronization out of the bean by wrapping the call to the method inside another bean (YourBean would be the interface of your bean class):
public class WrapperBeanImpl implements WrapperBean {
private YourBean yb;
private final Object lock;
#Resource
private SessionContext ctx;
#PostConstruct
public void init() {
yb = ctx.getBusinessObject(YourBean.class);
}
#TransactionAttribute(TransactionAttributeType.NEVER)
public void synchronizedDo() {
synchronized(lock) {
yb.do();
}
}
}
(Example slightly modified from http://www.javahelp.info/2009/11/01/using-transactionattribute-in-submethods-on-same-ejb3-beans/ )
Of course, this does not really stop anyone from calling the do() method directly bypassing this extra synchronization, although that may not be a problem. You also have the option of leaving the synchronization in your bean as an extra safeguard.
Just use #ConcurrencyManagementType(CONTAINER) on a class level and container will maintain synchronization. And use methond without synchronized directive.

CDI and pooling

Does CDI allows pooling in some way?Because I thought this is a feature of EJB beans but Adam Bien says in this screencast that container chooses whether to create new instance of class through reflection or use the existing one. So if I have for example these two beans
#RequestScoped
public class RequestBean {
public void doIt() {
}
}
#SessionScoped
public class SessionBean {
#Inject
private RequestBean bean;
public void doSomething() {
bean.doIt();
}
}
the question is - is there always new instance of RequestBean created upon calling doSomething or does CDI container somehow manage instances in pool?
The first one is scoped to the request, so a new instance is created for each request. The second one is scoped to the session, so a new one is created for each session.
CDI doesn't pool and recycle the objects, because it has no idea if the objects are stateful or not, and you don't want, in a request, to get back the state that a bean had in a previous request. That would ruin the whole point of the request/session scope.
Unless beans are really costly to create (because they start a new connection or something like that), pooling them doesn't bring any advantage. Short-lived objects are very fast to create and garbage collect nowadays. And if the bean is really expensive to create, then it should probably be a singleton.

How to enforce a prototype scope of Spring beans

I have a stateful Spring bean. How can I enforce its usage scope to prototype in my application?
How can I prevent another developper on my project of injecting this bean with the singleton scope?
I know you can configure scope either via annotation or via the xml configuration. Of what I have seen, when using Spring 3, the scope configured by annotation gets overriden by the scope defined manually in the xml. How can I enforce my scope, thru configuration or programatically, so my bean will never be used as a singleton?
I thought about inspecting the bean scope on the startup of the application, but it doesn't sound like an elegant solution.
This is not elegant, but AFAIK this is the only way to achieve what you are looking for
public class MyStatefulBean implements InitializingBean, ApplicationContextAware, BeanNameAware {
private String myName;
private ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext;
}
#Override
public void setBeanName(String s) {
this.myName = s;
}
#Override
public void afterPropertiesSet() throws Exception {
if(this.context.isSingleton(this.myName))
throw new RuntimeException("Bean CANNOT be singleton");
}
}
Document it? There's no way for it to know if someone is keeping a reference to the bean and reusing it or sharing it across threads when they should have been using getBean() to get the prototype.
Spring cannot stop your peers from writing code that is simply incorrect, which is all that such a usage would be.
If you don't want to rely on the API user doing what's expected of them, expose the bean via a factory.

Correct way of making a singleton a Spring bean

I am converting a singleton to a Spring bean, so that if the singleton fails to initialize, then entire web application's spring context doesn't load properly.
The advantage of making the Spring context not load properly, is that people will take notice and fix the configuration during deployment itself. As opposed to using 'non-spring bean' singleton: when that throws exception during initialization, nobody notices.. until a actual user complains of missing functionality.
My changes are working as expected.. but I am not sure if I am doing the right thing.
Any thoughts?
The code looks like this:
public class MySingleton {
private static MySingleton INSTANCE = null;
private MySingleton(){}
public static MySingleton getInstance(){
if(INSTANCE == null){
synchronized(MySingleton.class){
if(INSTANCE == null){
try{
doWork()
}catch(Exception e){
throw new IllegalStateException("xyz", e);
}
INSTANCE = new MySingleton();
}
}
}
return INSTANCE;
}
private static void doWork() {
// do some work
}
}
And in the spring config xml, the bean will be defined as:
<bean id="MySingletonBean"
class="com.MySingleton"
factory-method="getInstance" lazy-init="false" singleton="true">
</bean>
Note:
Most of this is similar to the strategy discussed in this article:
http://springtips.blogspot.com/2007/06/configuration-hell-remedy-with.html
Edit 1:
The classes that use this singleton, are not spring beans themselves.. they are just non-spring pojos, that I can't convert to spring. They must rely on getInstance() method get hold of the Singleton.
Edit 2: (copying a comment I made below into this description section)
I am trying to target two things:
I want Spring to initialize the singleton. So that if the
initialization fails, then the application loading fails.
I want the other classes be able to use classes without having to rely on contextAwareObj.getBean("MySingleton")
EDIT 3 (FINAL):
I decided to make this class a singleton.. and am not making it a spring bean. If it fails to initialize, it will log something in the Log file.. hopefully the person doing deployment takes notice.... I abandoned the approach I mentioned earlier because I feel it will create a maintenance nightmare in future, so I had to pick between - singleton - or - spring bean. I chose singleton.
You must declare the INSTANCE field as volatile for double-checked locking to work correctly.
See Effective Java, Item 71.
Why are you using singleton pattern on the first place? Just let Spring create bean for you (with default singleton scope) and... use it. Of course always somebody might create the bean by hand, but this was never a problem in my case.
Dependency injection and Spring-managed bean lifecycle will ease your life significantly (just see how many pitfalls you can avoid). Also note that exceptions thrown from c-tor or #PostContruct method will propagate and cause application context startup to fail as well.
UPDATE: I get your point. This is what came in to my mind:
#Service
public class Singleton {
private static AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();
public Singleton() {
final Singleton previous = INSTANCE.getAndSet(this);
if(previous != null)
throw new IllegalStateException("Second singleton " + this + " created after " + previous);
}
public static Singleton getInstance() {
return INSTANCE.get();
}
}
And let Spring do its job. You can use DI when possible and Singleton.getInstance() where you have to.
Also there are more hard-core solutions like compile-time AspectJ weaving and injecting Spring beans basically to everything.
I'm not sure why you'd want to do this. When you tell Spring that a bean should be a singleton, the corresponding class does not need to be a singleton, and does not need a factory. Spring just simply only ever creates one instance.
The linked article makes no sense to me, since there is NO injection happening, that I can see: "AnyService" is calling the singleton factory method; that the singleton is referenced in the app context is irrelevant until it's referenced, and it seems no other bean references it.
True singleton are hard to get working.
Volatile double-checked locking also does not work property. Read about it on wiki http://en.wikipedia.org/wiki/Double-checked_locking
Your best bet is to simply do this
public class MySingleton {
private static MySingleton INSTANCE = new MySingleton();
That is if you do not have any constructor parameters in your real code.
According to me this is a belts-and-suspenders solution.
If you create a bean and declare it as a singleton in the configuration then there should be no need to protect the bean against being multiply created.
You are now basically protecting yourself from someone wrongly configuring the bean.
I personally would "solve" that by documentation in the spring configuration and Javadoc.
To run code at startup (and fail on error) use one of the many ways to register startup events, e.g. see http://www.baeldung.com/running-setup-logic-on-startup-in-spring
Example:
#Component
public class InitializingBeanExampleBean implements InitializingBean {
private static final Logger LOG = Logger.getLogger(InitializingBeanExampleBean.class);
#Autowired
private Environment environment;
#Override
public void afterPropertiesSet() throws Exception {
LOG.info(Arrays.asList(environment.getDefaultProfiles()));
}
}
#Component
public class SingletonDAOImpl {
}
#Component
public class SingletonDAO {
#Autowired private SingletonDAOImpl instance;
public SingletonDAOImpl getInstance(){
return this.instance
}
}
public class WhateverPlaceYouNeedIt{
#Awtowired private SingletonDAO singletonDao;
public void useSIngleton() {
SingletonDAOImpl INSTANCE = singletonDao.getInstance();
}
}
I tried in so many ways to do something like SingletonDao.instance.doSomething()
but just is not in the spring way and you will find so many hacks in order to do this but is incorrect in my opinion
here
You have your Singleton, which can be changed after in a Multiton
For sure is a single implementation
is respecting the INSTANCE pattern as "getInstance"
Is in-memory so each time is the same object as in singleton
is the same principle applied slightly different, very simple, all the time try to KIS implementation(Keep it simple)

Categories

Resources