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.
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'm trying to use Container-Managed Transactions inside webservice, but transaction isn't created. I have something like that:
#WebService(...)
#Stateless
#TransactionManagment(TransactionManagmentType.CONTAINER)
public class ExampleService {
// EntityManager and other fields
#TransactionAttribure(TransactionAttributeType.REQUIRED)
public void test(String s){
// persist something with EntityManager
}
}
When I call this method, I get javax.persistence.TransactionRequiredException: The method public abstract void javax.persistence.EntityManager.persist(java.lang.Object) must be called in the context of a transaction.
What am I doing wrong?
Thanks!
From what I recall 'TransactionAttributeType.REQUIRED' means that method should be only called when transaction is already in progress for current thread (in other words 'called in context of transaction'). It's not clear who if anybody starts transaction in your case. If nobody then the exception you're getting makes perfect sense.
Now I'm not sure how or is it even currently possible to propagate transaction across Web services call. I don't think this is particularly good idea to do so even if possible.
Perhaps you what you need TransactionAttributeType.REQURES_NEW in your case so Container would start the transaction before passing control to your annotated method?
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.
I have the following bean declaration:
#Stateful
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class InteruptBean implements Interrupt {
private boolean interrupt = false;
#Override
public boolean check() {
return interrupt;
}
#Override
public void interrupt() {
interrupt = true;
}
}
I'm trying to understand the Stateful EJB Lifecycle. Once the state of this EJB is permanently modified using the interrupt() method, and all references to this instance are set to null, is the bean instance put back in the eligible pool or is it discarded?
What makes me question my judgement is the TransactionAttributeType.NOT_SUPPORTED. I would hope the container spec says somewhere that a Stateful EJB is reset somehow how to it's initial state before being used again, not matter what the TransactionAttributeType is.
Thanks!
Read http://download.oracle.com/javaee/6/tutorial/doc/giplj.html#gipln.
At the end of the lifecycle, the client invokes a method annotated #Remove, and the EJB container calls the method annotated #PreDestroy, if any. The bean’s instance is then ready for garbage collection.
If nobody ever calls an #Remove method, the container will wait antil a timeout is reached and remove it.
The #TransactionAttribute annotation has nothing to do with the bean's lifecycle. It only tells the container if and when a transaction should be started when one of its business methods is invoked.
#cj91
I am not sure whether the SPEC specifically says what you are asking, i,e
I would hope the container spec says
somewhere that a Stateful EJB is reset
somehow how to it's initial state
before being used again, not matter
what the TransactionAttributeType is.
But I am pretty sure that the transaction attribute type has no impact on how a stateful EJB is (re)initialized.
NOT_SUPPORTED just means that the method cannot be invoked from within a transaction context. If it is invoked, it is silently ignored.
See
http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html
I have a simply web service using #PostConstruct and #PreDestory annotations.
#PostConstruct
private void init() {...} //initialize some database connection
#PreDestroy
private void release() {...} //release data base resources
then a client will call some web methods to do some database operations. I did a simply testing by setting break points in the code. The #PostConstruct works fine. but #PreDestroy method never get called.
I thought #PreDestroy will always get called when a client finish calling a web method since web service is stateless by nature. So in the end, the instance is always destroyed and before that, my release method should be called? Is this a correct understanding?
But after reading some online resources, i got confused. some says #PreDestroy will be called when it's un-deployed?
#PreDestroy is only called when the application server decides to reduce the size of the Method-Ready pool - i.e. it determines it doesn't need to keep as many instances of your #WebService #Stateless session bean around. It doesn't get called after each invocation of your #WebMethod (and #PostConstruct is only called when a new instance is added to the Method-ready pool, not necessarily before each web method invocation).
If you have logic you need called before and after each method invocation you could do it as follows:
#AroundInvoke
public Object intercept( InvocationContext ctx )
{
try
{
init();
return ctx.proceed();
}
finally
{
release();
}
}
This method can be added to your #WebService bean or as a separate class using #Interceptors