Jax-ws #PreDestroy When does it get called exactly? - java

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

Related

Get caller class in Java CDI Interceptor

I'm trying to implement a cache that holds results from a specific business method call and then refreshes itself every 30 minutes.
I was able to accomplish that by using a singleton EJB using a scheduled method; however, every class that calls that business method now has to instead call the method from the singleton that exposes the cached results.
I want to avoid this behaviour and keep the code from these classes as is, so I thought of using an interceptor that would intercept every call to that particular business method and return instead the results from the cache singleton.
However, this solution has the application stalling since the singleton calls the intercepted business method itself to cache its results, so the interceptor intercepts the call (pardon the repetition) and tries to return the result of the singleton method that exposes the cached values, while the singleton is still waiting for the call to the business method to proceed.
The most obvious solution would be to get the method caller from the interceptor, and check if its
class corresponds to the singleton's; if so, proceed with the call, otherwise return the cached results from the singleton. However, it appears that the InvocationContext object used by the interceptor doesn't expose any methods to access information about the intercepted method's caller. Is there any other way to access the caller's class, or any workaround to this issue?
Here's my singleton class:
#Singleton
#Startup
public class TopAlbumsHolder {
private List<Album> topAlbums;
#Inject
private DataAgent dataAgent;
#PostConstruct
#Schedule(hour = "*", minute = "*/30", persistent = false)
private void populateCache() {
this.topAlbums = this.dataAgent.getTopAlbums();
}
#Lock(LockType.READ)
public List<Album> getTopAlbums() {
return this.topAlbums;
}
}
And here's my interceptor:
#Interceptor
#Cacheable(type = "topAlbums")
public class TopAlbumsInterceptor {
#Inject
private TopAlbumsHolder topAlbumsHolder;
#AroundInvoke
public Object interceptTopAlbumsCall(InvocationContext invocationContext) throws Exception {
// if the caller's class equals that of the cache singleton, then return invocationContext.proceed();
// otherwise:
return this.topAlbumsHolder.getTopAlbums();
}
}
Note that the #Cacheable annotation is a custom interceptor binding, not javax.persistence.Cacheable.
EDIT: I modified the interceptor method that way:
#AroundInvoke
public Object interceptTopAlbumsCall(InvocationContext invocationContext) throws Exception {
for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace())
if (TopAlbumsHolder.class.getName().equals(stackTraceElement.getClassName()))
return invocationContext.proceed();
return this.topAlbumsHolder.getTopAlbums();
}
But I doubt that's the cleanest solution, and I don't know if it's portable.
EDIT 2: In case it is not clear enough, I need to access information about the invoker class of the intercepted method, not the invoked class that has its method intercepted; that's why I'm iterating over the stack trace to access the invoker's class, but I reckon this is not an elegant solution, even though it works.
For what you need to do, I'd say use either interceptor or decorator.
Your interceptor is however wrong. Firtly you are missing the basic part, which is a call to InvocationContext.proceed() that forwards the call to next-in-line interceptor (if there is any) or the method call itself. Secondly, the injection point you placed there is very specific and would only help you if you intercept this very type of bean. Typically, an around invoke interceptor method looks like this:
#AroundInvoke
Object intercept(InvocationContext ctx) throws Exception {
// do something before the invocation of the intercepted method
return ctx.proceed(); // this invoked next interceptor and ultimately the intercepted method
// do something after the invocation of the intercepted method
}
Furthermore, if you want metadata information about what bean was intercepted, every interceptor can inject a special built-in bean just for that. From the metadata, you can gather information on what bean you're currently intercepting. Here is how you get that metadata:
#Inject
#Intercepted
private Bean<?> bean;
Note that interceptors are unaware of what type they intercept, it can be anything and hence you usually need to operate on plain Object.
Should you need something more specific, CDI offers a Decorator pattern which in basically a type-aware interceptor. It has a special injection point (a delegate) that gives you direct access to the decorated bean. It might possibly fit your scenario even better, take a look at this part of CDI specification explaining Decorators.
There is a misunderstanding.
You don't inject the Object which gets intercepted into the interceptor, but use the invocationContext.
You just need to call invocationContext.proceed() then there is no recursion.
The result of proceed() you can cache.
Iterate over the stack trace to check on TopAlbumsHolder exists isn't a good way.
To escape invoking the interceptor during calling the getTopAlbums() from DataAgent class you can specify the scheduler direct in the DataAgent which gathers the data and push it into TopAlbumsHolder. You can do it another way, but your main point direct invoking the getTopAlbums() within the DataAgent bean without participating proxy (in this case, the interceptor won't apply).
P.S. Pay attention that cached data should be immutable (both the collection and its objects).

Can I call a method with TransactionAttributeType.REQUIRED from another method with TransactionAttributeType.NOT_SUPPORTED in same EJB

I have a following code structure, I need guidence on how to start a local transaction cascaded from a NOT_SUPPORTED transaction type method in same EJB.
#Stateless
#TransactionManagement(value = TransactionManagementType.CONTAINER)
public class SessionBean implements SessionBeanInterface{
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void methodA() {
methodB();
}
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public void methodB() {
}
}
Currently when I try this i get below exception.
No active transaction for PuId=App#EJB.jar#Persistence
The way you have called "methodB" would not give a chance to the EJB Container to start a transactional context for you. To do that you have to invoke that method through either Remote or Local views/interface.
It is the container who supplies you these additional features and hence it is necessary to route your calls through interface than. (On a side note this is Proxy Design Pattern).
If you directly call "methodB" as you have done in above code snippet, it is just another method call without container intervention.

Spring cache using #Cacheable during #PostConstruct does not work

related to the commit in spring framework https://github.com/spring-projects/spring-framework/commit/5aefcc802ef05abc51bbfbeb4a78b3032ff9eee3
the initialisation is set to a later stage from afterPropertiesSet() to afterSingletonsInstantiated()
In short:
This prevents the caching to work when using it in a #PostConstruct use case.
Longer version:
This prevents the use case where you would
create serviceB with #Cacheable on a methodB
create serviceA with #PostConstruct calling serviceB.methodB
#Component
public class ServiceA{
#Autowired
private ServiceB serviceB;
#PostConstruct
public void init() {
List<String> list = serviceB.loadSomething();
}
This results in org.springframework.cache.interceptor.CacheAspectSupport not being initialised now and thus not caching the result.
protected Object execute(CacheOperationInvoker invoker, Object target, Method method, Object[] args) {
// check whether aspect is enabled
// to cope with cases where the AJ is pulled in automatically
if (this.initialized) {
//>>>>>>>>>>>> NOT Being called
Class<?> targetClass = getTargetClass(target);
Collection<CacheOperation> operations = getCacheOperationSource().getCacheOperations(method, targetClass);
if (!CollectionUtils.isEmpty(operations)) {
return execute(invoker, new CacheOperationContexts(operations, method, args, target, targetClass));
}
}
//>>>>>>>>>>>> Being called
return invoker.invoke();
}
My workaround is to manually call the initialisation method:
#Configuration
public class SomeConfigClass{
#Inject
private CacheInterceptor cacheInterceptor;
#PostConstruct
public void init() {
cacheInterceptor.afterSingletonsInstantiated();
}
This of course fixes my issue but does it have side effects other that just being called 2 times (1 manual and 1 by the framework as intended)
My question is:
"Is this a safe workaround to do as the initial commiter seemed to have an issue with just using the afterPropertiesSet()"
As Marten said already, you are not supposed to use any of those services in the PostConstruct phase because you have no guarantee that the proxy interceptor has fully started at this point.
Your best shot at pre-loading your cache is to listen for ContextRefreshedEvent (more support coming in 4.2) and do the work there. That being said, I understand that it may not be clear that such usage is forbidden so I've created SPR-12700 to improve the documentation. I am not sure what javadoc you were referring to.
To answer your question: no it's not a safe workaround. What you were using before worked by "side-effect" (i.e. it wasn't supposed to work, if your bean was initialized before the CacheInterceptor you would have the same problem with an older version of the framework). Don't call such low-level infrastructure in your own code.
Just had the exact same problem as OP and listening to ContextRefreshedEvent was causing my initialization method to be called twice. Listening to ApplicationReadyEvent worked best for me.
Here is the code I used
#Component
public class MyInitializer implements ApplicationListener<ApplicationReadyEvent> {
#Override
public void onApplicationEvent(ApplicationReadyEvent event) {
//doing things
}
}
Autowire ApplicationContext and invoke method call using :
applicationContext.getBean(RBService.class).getRawBundle(bundleName, DEFAULT_REQUEST_LANG);
where getRawBundle is Cacheable method.

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.

How to Wire Dependent #Async methods

I have two Spring based async thread pools and methods in the same Spring bean. The doWork() uses the default Spring thread pool and holdAndReprocess() uses its own Spring thread pool.
I currently have my class setup like below where doWork processes some work and then if a failure occurs it parks the thread in the holdAndReprocess() "queue" thread pool and then waits and reprocesses the thread by calling the doWork(). With my current setup, the call to holdAndReprocess() and then the call back to doWork() is synchronous. Any ideas on how to wire this such that all communication between the doWork() and holdAndReprocess is asynchronous?
I'm using xml backed configuration and not pure annotation driven Spring beans.
public class AsyncSampleImpl implements AsyncSample {
#Async
public void doWork(){
holdAndReprocess();
}
#Async("queue")
#Transactional(propagation = Propagation.REQUIRED)
public void holdAndReprocess(){
//sleeps thread for static amount of time and then reprocesses
doWork();
}
}
Read https://stackoverflow.com/a/4500353/516167
As you're calling your #Async method from another method in the same object, you're probably bypassing the async proxy code and just calling your plain method, ie within the same thread.
Split this bean into two beans and invoke holdAndReprocess() from separate bean.
This rules apply also to #Transactional annotations.
Read about this: https://stackoverflow.com/a/5109419/516167
From Spring Reference Documentation Section 11.5.6, “Using #Transactional”
In proxy mode (which is the default), 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!
Draft
public class AsyncSampleImpl implements AsyncSample {
public void doWork(){
reprocessor.holdAndReprocess();
}
public void holdAndReprocess(){
//sleeps thread for static amount of time and then reprocesses
worker.doWork();
}
}

Categories

Resources