I wondering if I should exspect any problems when I autowire threads with prototype scope.
The thread:
...
#Service
#Scope("prototype")
public class MyThread extends Thread {
...
}
The thread starting class:
...
public class ThreadStarter {
#Autowired
private MyThread myThread;
public void startThread(){
myThread.start();
}
}
The starting class will be called from a webservice implementation.
Are there any pitfalls I should take into consideration?
Well it reallty depends on what the thread class instance does.
Think of Servlet doGet and/or doPost methods. If you're being stateless and don't keep values in wider scopes (such as session or context) you're fine with not troubling yourself about which instance of your servlet will be called when. However if you are being statefull (get/put objects to the session scope for example) then you need to synchronize that servlet instance's access to said scope (synchronized(session)) or serialize the way requests are being treated by the servlet threads.
I think here you're pretty much in the same situation. You want to make your thread instance to be prototype scoped (and thus have a new instance created each time an injection is needed) if you are infact stateful and share data between your threads, and you can leave it to the default scope of singleton if that thread's run() method is stateless as far as data outside it is concerned.
Nope, autowiring only affects which bean is choosed to fulfill a dependency- as long as you are not meddling with the ApplicationContext (i.e. adding/modifying beans concurrently), no weird stuff should happen.
In your example ThreadStarter will be injected a new instance of MyThread everytime it is instantiated- which I hope is what you want.
Related
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(){}
}
}
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.
I have created a bean of a class with default (Singleton) scope. Within the class I have a method which is scheduled to be run every hour.
public class TaskService implements InitializingBean {
#Scheduled(cron="0 0 */1 * * ?")
public void hourlyReportTask()
{
... code here ...
}
public void performAllTasks()
{
hourlyReportTask();
...
...
}
}
My application config looks something like this,
<bean id="reportService"
class="com.tasks.TaskService" />
I am assuming the Thread running the scheduled task will be using the same TaskService bean since its created in singleton scope. What shall happen if the application is currently running hourlyReportTask() and the Spring container kicks off a background scheduled thread to run hourlyReportTask() at the same time. Will it wait for the to get access of the TaskService instance?
The exact same instance is used by both your application and the scheduling service. There is no synchronization so the scheduling service may run that method while your application invokes it.
Pretty much the same way as you would have injected TaskService in something that can be accessed by multiple threads at the same time and those threads call that method concurrently.
There's no black magic behind #Scheduled: it invokes your method the same way as you would manually. If that method is not thread-safe you need to fallback on regular synchronization mechanism in Java (for instance by adding the synchronized keyword to your method declaration).
Spring Singleton, does not mean what you expect from Design Patterns Singleton. In Spring, Singleton means that a bean only has created only one instance (without meaning that another cannot be created) and that instance is used whenever Spring needs that type.
In your case your hourlyReportTask() method would execute twice.
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.
I have a jsp application (using Spring) that uses a couple of global variables. I need multiple people to be able to use this program concurrently, however. What is the best way to go about making it thread-safe such that each instance of the program is independent of the others?
::EDIT:: Am I okay if I just don't use any singleton objects?
Each request is handled in its own thread. These threads are managed by the servlet container. It is not a good idea to use static global variables in a servlet. All instance variables are common to all threads, therefore it can lead to ambiguous state.
I recommend saving this type information in a scope variable (application,session, request, page, etc).
If you have to use a global variable then you will need to synchronize the access to it to avoid unknown states.
A typical container uses a thread-per-request model, so you have an easily-recognizable boundary built right in. The general rule is to never store any state in any object that is visible to multiple requests (threads) unless that state is effectively immutable. For example, a singleton controller like this
#Controller
#RequestMapping("/schedule")
class MyController {
private Scheduler scheduler;
#RequestMapping(method = RequestMethod.POST)
public void scheduleSomething(Foo foo) {
scheduler.schedule(foo);
}
}
is stateful--the schedular field holds state--but the state is initialized at startup and remains constant across all requests/threads. If you had a singleton controller like this, on the other hand:
#Controller
#RequestMapping("/schedule")
class MyController {
private Scheduler scheduler;
private Foo foo;
#RequestMapping(method = RequestMethod.POST)
public void scheduleSomething(Foo foo) {
this.foo = foo;
scheduler.schedule(this.foo);
}
}
That is absolutely not safe for concurrent access because all requests go to this same controller, and foo will be constantly changing in a non-thread-safe way. Follow this line of reasoning through your entire application, and you'll be safe.