Correct way to find if spring context was started - spring

In my spring bean I want to use send spring event functionality. The problem is event can't be sent if spring context was not initialized and my bean by some reasons can send events before that happen.
I used the following:
implement ApplicationContextAware and use ConfigurableApplicationContext.isActive() - this becomes true in the beginning of the context initialization phase
use ConfigurableApplicationContext.isRunning() - this throws exception IllegalStateException("LifecycleProcessor not initialized...
listen for ContextRefreshedEvent - this doesn't work because this is inner bean and is used as a property for the bean that implements BeanFactoryPostProcessor
implementing SmartLifecycle also doesn't work because for inner beans
So what is the EASY and correct way to determine if context is running and event can be sent?

Hopefully this is already fixed SPR-13667 in spring 4.1.7.

Related

Fire CDI event AFTER bean creation via producer

I have a CDI producer method which creates an UserBean. The producer fires an UserBeanEvent. Other beans rely on that user bean and those beans may be used in the observer methods.
CDI again tries to create the user bean, the producer is invoked, the event is fired and so on - endless loop.
Is there any neat way to fire the event AFTER the producer completed and the bean was fully added to the bean store? I looked through the sources but I was not able to find anything.
I'm using WELD 2.3.5.final on WildFly 10.1
You need to detail several things, and one of the most important one is scope, and at what point is the bean needed?
Obviously if there is an observer method that listens to this bean event, and also needs a reference to this bean in the observer parameter, then you are definitely creating a cyclic dependency, which you cannot resolve, as the events in CDI are synchronous by default (And even if you use the fireAsync, there is no guarantee that by the time the event arrive, CDI has put the bean into proper context)
I would solve this problem by doing a method injection on an eargerly loaded bean such as ejbs Singleton or #ApplicationScoped with some kind of earger loading, and then fire the event from there.
Assuming that the bean is eargerly loaded:
public class EargerBean {
#Inject
private Event<BeanEvent> event;
#Inject
public void onInjected(Bean bean){
BeanEvent beanEvent ...;
event.fire(beanEvent);
}
}

Spring AMQP ListenerContainer lifecycle management

We are using Spring AMQP to connect to RabbitMQ in our Spring based web application.
When we declare our listener-containers as beans (using rabbit:listener-container) in application context, their lifecycle is managed by Spring.
If we declare a listener-container in a component inside a #PostConstruct method, or we create a bean with class org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer as a prototype scoped bean, we then have to manage the lifecycle i.e. start and stop the listener-container ourselves.
My question is, if we declare new queues, bindings and listener-containers inside a #PostConstruct method, just calling listener.stop/shutdown/destroy method inside the corresponding #PreDestroy method would be enough for a graceful shutdown? Or else what do I need to do?
Note: I am guessing I don't have to do anything for the new queues and bindings created in the #PostContruct, but I would be very glad if you also confirm this for me.
I would not recommend starting a listener container or declaring queues/bindings in an #PostConstruct method; the context is only half-baked at that time. It might work but it's not recommended to do stuff like that while the context is being initialized.
It's better to implement SmartLifecycle and start/stop them in the start()/stop() methods.
Then, the container lifecycles would be indirectly managed by the spring context.
You can also control exactly when your bean is started/stopped by putting it in a phase.

injecting spring beans into non-singleton classes

is it possible to inject spring beans into a polling filter class (FClass) controlled by a scheduler job?
i don't quite understand how singleton applies here.
i understand spring beans are singleton so in order to inject the spring beans into class FClass. i need to define FClass as a bean and add the DI as property etc..
so how do i know if FClass should be a singleton? i assume only classes that are singletons can be created and beans and have DI done to them.
my problem is :
i need to be able to inject my facade bean xfacade into FClass. x_facacde handles the dao object. it has Y_dao and a Z_hibernate session beans injected as DI.
when i tried to create a spring bean of StatusPollingFilter (FClass) and injected the facade bean - i got a null and the setter is never called for the injection in debug mode.
the problem:
i'm thought it might be something to do with the thread / scheduler nature of StatusPollingFilter, and since spring beans are singletons it might not work due to that.
i'm thinking of creating a factory for the StatusPollingFilter (FClass). but need to know if this is correct thing and i'm on right track before i do too much work and realize even that doesn't work as the problem might be somewhere else. ideally i just want to update a table in the easiest possible way. but i have to use hibernate as the DAO exists but hibernate is configured using
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
with /hibernate/TopoObject.hbm.xml
files.
so no matter how i try this i always get null pointer exception on session or injected facade bean.
reading some of the QA's here seems like because StatusPollingFilter is instantiated using the scheduler and not spring it cant be aware of the DI beans. so would the above factory pattern help here.
I may have an additional problem but i'll cross that bridge when i come to it. but just to mention briefly, in case anyone is aware of issues that i might hit ... not sure what / how the scheduler would invoke the factory for an instance as its all controlled by 3rd party api - which invokes a StatusPollingFilter but i'm assuming if i pass in the factory as the class and parameter it would find its way through... but initial part is the main question. please ignore the latter waffle. thanks in advance.
Actually :
i assume only classes that are singletons can be created
is where you are wrong.
A bean is just a class that you let spring instantiate. By default, they are created as singleton but you can specify the scope on your bean using the attribute scope (quite surprisingly). The value you can specify are those specified in the documentation here
So one thing you have to be careful with is the injection of beans scoped as prototype or request into singletons.
having read more - i have come across the ans.
because the StatusPollingFilter object is under control of scheduler (i knew that scheduler had something to do with it) then it is unaware of the spring beans which is why i keep getting null when i try injecting the bean.
i created a class:
ApplicationContextProvider implements ApplicationContextAware
added static access
private static ApplicationContext appContext;
did a setter for it :
public void setApplicationContext(ApplicationContext context)
{
appContext = context;
}
and added
public static Object getBean(String beanName) throws BeansException
{
return appContext.getBean(beanName);
}
used in code as :
EvoTAMDAOFacade evoDao = (EvoTAMDAOFacade) ApplicationContextProvider.getBean("evoDaoFacade");
i now have access to the facade bean and all injected beans into facade.
i still have an issue with hibernate session but thats prob due to some other issue.
pt here is i don't have access to the bean as its not in control of the spring container so i needed to somehow get it , probably could have done it via the factory method but why mess around when there a simpler way.
thanks for help by anyone who may have posted or tried to understand my problem.

Spring session handling: HttpSessionDestroyedEvent not received

I have a web app where in the web.xml I have added the HttpSessionEventPublisher as listener. The web app runs on Jetty 7.x and we are using Spring 3.1.1.
This is supposed to fire HttpSessionCreatedEvent and HttpSessionDestroyedEvent to Spring context event listeners.
I have a Bean (#Controller) that implements ApplicationListener<ApplicationEvent>. ApplicationEvent is the common parent class of HttpSessionCreatedEvent and HttpSessionDestroyedEvent. When I now login to my web application or log out from it I'd expect these events to be fired to the onApplicationEvent(ApplicationEvent event) method. I have received other events like some request handling event, but the expected event's didn't show up. I have traced the app a bit, the HttpSessionEventPublisher definitely fires the event to the context, but the listener isn't approached. what do I miss here?
The issue is that HttpSessionEventPublisher publishes events on the "Spring Root WebApplicationContext" per the javadoc, this is the application context registered through ContextLoaderListener entry in your web.xml file. Your #Controller on the other hand is probably registered through a different application context altogether - the one registered through the DispatcherServlet. So I would suggest that you create a different ApplicationListener, register it to the Root WebapplicationContext, the events should come through then.
Facing a similar problem, if it not possible to move your ApplicationListener to the root context, you can use the org.springframework.security.context.DelegatingApplicationListener.
Just autowire a DelegatingApplicationListener in your Bean and use constructor / #PostConstruct to register your listener against the DelegatingApplicationListener (one should be already in place by spring-security)

Spring calling 'destroy' method on session/request scoped beans

How does Spring know when to call 'destory' method on a session/request scoped bean (in other words, how does it detect that the concerned bean is going out of scope)?
I read somewhere that it uses request/session listeners to be notified of these events. But these listners need to be defined in web.xml, and there's no mention of defining such listeners in Spring literature. So how does this work?
The org.springframework.web.servlet.DispatcherServlet does it. It uses own code, e.g. the org.springframework.web.context.request.RequestAttributes#registerDestructionCallback callback list functionality to register all these scoped beans.
and there's no mention of defining such listeners in Spring literature
Oh, there is:
To support the scoping of beans at the request, session, and global session levels (web-scoped beans), some minor initial configuration is required before you define your beans.[...]
If you use a Servlet 2.4+ web container, [...] you need to add the following javax.servlet.ServletRequestListener to the declarations in your web applications web.xml file[...]
From: 4.5.4.1 Initial web configuration.
Also note that Spring does not call destroy on prototype-scoped beans.
You can implement the interface DisposableBean and InitializingBean for session scoped bean.
The org.springframework.beans.factory.InitializingBean interface allows a bean to perform initialization work after all necessary properties on the bean have been set by the container. The InitializingBean interface specifies a single method afterPropertiesSet().
Implementing the org.springframework.beans.factory.DisposableBean interface allows a bean to get a callback when the container containing it is destroyed. The DisposableBean interface specifies a single method destroy().
Read more about it here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-factory-nature

Resources