Application Server: JBOss 4.2
I have a method which I want to intercept.Its a method annotated #Timeout and invoked by javax.ejb.TimerService instance.
The method signature:
#Stateless
class A
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
#Timeout
#Interceptors(AnInterceptor.class)
public void doSomething(Timer timer)...
Now I have the interceptor class:
public class AnInterceptor {
#AroundInvoke
public Object intercept(InvocationContext ic) throws Exception{...
System.out.prin(...)
It does work on other method methods (which are not annotated with #Timeout)
Thanks,
Rod
Per the spec, AroundInvoke is not supported for timeout methods (business interface, component interface, and webservice endpoint only). Searching Google, AroundTimeout appears to be coming in EJB 3.1 (pages 12 and 22):
http://www.ow2.org/xwiki/bin/download/Events2009AnnualConference/Program/JavaEE6-EasyBeans-F-Benoit.pdf
In the meantime, you can workaround the issue by injecting a reference to the same bean into itself. In other words inject (or lookup) another "A" from within "A", and then create and invoke a new "doTimeout" method from your "doSomething" method.
Instead of using #AroundInvoke, try using #AroundTimeout
"Interceptors for EJB timer service timeout methods may be defined using the #AroundTimeout annotation on methods in the target class or in an interceptor class. Only one #AroundTimeout method per class is allowed."
Here you can see how to use it, under the section "Intercepting Timeout Events"
http://docs.oracle.com/javaee/6/tutorial/doc/gkedm.html#gkedu
Related
If one Service class has method with #Transactional, then spring will use proxy to handle it.
But if one Transactional method call another one
#Transactional
public FeedBackModel getOne() {
///..
return getTwo();
}
#Transactional
public FeedBackModel getTwo() {
return null;
}
like this.
if it is jdk proxy, then second #Transactional will not work.
But spring PROPAGATION will handle this correctly.
How it works?
If you are trying to commit a transaction in getTwo() which is called from getOne(), that will not work, not even when both are #Transactional. Refer to the documentation:
...please do take the Spring team's advice and only annotate concrete
classes (and the methods of concrete classes) with the #Transactional
annotation.
Note: Since this mechanism is based on proxies, only 'external' method
calls coming in through the proxy will be intercepted. This means that
'self-invocation', i.e. a method within the target object calling some
other method of the target object, won't lead to an actual transaction
at runtime even if the invoked method is marked with #Transactional!
I have a spring managed bean of type B. I have #EnableREtry in a #Configuration class. When I use #Retryable on doStuff(), the method gets retried on failure as expected.
But, the method I really want to retry is a method defined in the base class, A. A is a concrete class and not a spring managed bean. the doSomethingElse method doesn't get retried on throwing an exception.
I really want doSomethingElse to be retried, the base class method. However, I'm not sure how to do this. I'm guessing it's because A is a concrete class and not a bean, although it does serve as a base class.
Do I need to use a RetryableTemplate in class A?
public class B extends A {
public void doStuff() {
super.doSomethingElse();
}
}
public class A {
// doesn't actually retry
#Retryable
public void doSomething() {
throws new Exception();
}
}
#Retryable is implemented using Spring AOP.
Only external calls to retryable methods go through the proxy (which invokes the method within a RetryTemplate); internal calls within the class bypass the proxy and therefore are not retried.
You can play some tricks to get a reference to the proxy from the application context and call that, or simply use a RetryTemplate directly within your doStuff() method.
I've the following situation:
I wish the "methodB" was executed 10 times paralleling. But it only happening when the "methodB" is called from another bean.
Why the annotation "#Asynchronous" does not work when the method is called from another method in the same class?
Thanks.
It only works for methods call via a client proxy, for example a #Local or #Remote interface. This is described in the EJB 3.1 specs (section 4.5 - 4.5.1):
A session bean can expose methods with asynchronous client invocation semantics
...
The #Asynchronous annotation is used to designate which business methods are asynchronous.
...
Asynchronous method invocation semantics only apply to the no-interface, Local business, and Remote business client views.
How do you get DI to work in a webapp? So far I've done the following:
1) Annotate setter method with #Inject
2) Extend AbstractModule so that it binds the interface class to the implementation class for the attribute whose setter was annotated in step 1
3) Extend GuiceContextServletListener and overrode getInjector so that it returns Guice.createInjector(new ExtendedAbstractModule())
4) Registered the extended GuiceContextServletListener in web.xml as a listener
I've verified that the extended GuiceContextServletListener.getInjector() method is called when the webapp is started. The attribute whose setter was annotated is not being injected and remains null.
I went ahead and created a ServletModule that serves the servlet that instantiates the object with the #Inject setter. After instantiating the object I get the Injector from the ServletContext and call the injectMembers method passing it the instantiated object.
What annotation are are you using on the setter?
I normally use #Named annotation to get attribute values which can be pointed to a property file or setup individually.
http://code.google.com/p/google-guice/wiki/BindingAnnotations
#Inject
void somethingSetter(#Named('Tag')String s) {
}
There is a tutorial of how to setup a complete Java web service using Guice and Sitebricks here:
http://www.techtraits.ca/five-minute-guide-to-setting-up-a-java-webserver/
in one dao I have 2 #Transactional methods.
if i do not provide any explicit properties,
then what will happen, if
I run one method in the body of another?
Both methods will run within THE SAME ONE TRANSACTION?
Proxies in Spring AOP
When using Transactional, you're dealing with proxies of classes, so in this scenario:
#Transactional
public void doSomeThing(){ // calling this method targets a proxy
doSomeThingElse(); // this method targets the actual class, not the PROXY,
// so the transactional annotation has no effect
}
#Transactional
public void doSomeThingElse(){
}
you are calling the proxy from outside, but the second method call is made from inside the proxied object and therefor has no transactional support. So naturally, they run in the same transaction, no matter what the values of the #Transactional annotation in the second method are
so if you need separate transactions, you have to call
yourservice.doSomething();
yourservice.doSomethingElse();
from outside.
The whole scenario is explained pretty well in the chapter Spring AOP > Understanding AOP proxies, including this "solution":
Accessing the Current AOP Proxy object from the inside
public class SimplePojo implements Pojo {
public void foo() {
// this works, but... gah!
((Pojo) AopContext.currentProxy()).bar();
}
public void bar() {
// some logic...
}
}
The default value of the propagation attribute of #Transactional is REQUIRED, which means:
Support a current transaction, create a new one if none exists.
So yes - both methods will run in the same transaction.
But one important advice: don't make your DAO transactional. The services should be transactional, not the DAO.
Spring doc
one note:
In proxy mode (which is the default),
only external method calls coming in
through the proxy are intercepted.
This means that self-invocation, in
effect, a method within the target
object calling another method of the
target object, will not lead to an
actual transaction at runtime even if
the invoked method is marked with
#Transactional.