I have an on Object with an annotation
#ApplicationScoped
public class DbGraphConnectionLocator implements ServerStopTask {
...
}
This object create an embedded database.
I have tried to create an hook to shutdown database when i redeploy the application.
So i construct the class
#WebListener
public class UndeployHook implements ServletContextListener{
#Inject
DbGraphConnectionLocator dbGraphConnectionLocator;
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
try {
dbGraphConnectionLocator.executeStopTask();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Actually the method contextDestoyed is called but the object used in is not the original one DbGraphConnectionLocator created at start up, and this is causing me some trouble.
In my opinion with the annotation
#ApplicationScoped
public class DbGraphConnectionLocator implements ServerStopTask { ....}
The instance of DbGraphConnectionLocator have to be unique at application level so when i use it with a
#Inject
DbGraphConnectionLocator dbGraphConnectionLocator;
I have to found the same instance created on start up by my application, but this is not true another instance was created.
Anyway i resolved adding the
#PreDestroy
public void shutdownDB(){
graphDb.shutdown();
}
to DbGraphConnectionLocator.
For info i see that this method is called after the contextDestroyed method , and this means that when the contextDestroyed is called the original instance still exist, so i miss something....
any hint?
If the embedded db shall be created at application start and be shut down when the application is stopped, just do the following:
#ApplicationScoped
#Startup
public class AnyNameForYourApplicationClass {
#PostConstruct
public void connectDB() {
// creates the db connection at startup
}
#PreDestoy
public void disconnectDB() {
// disconnects from the db
}
}
This should do it.
Alternatively you could also use a CDI producer to create an application scoped db connection. Then you can disconnect from the db using a disposer method.
In your case the behavior is correct since when the web listener is called the application must still be alive. So the shutdownDB method with #PreDestroy is called afterwards when the application scoped bean is destroyed. And since you are referencing it in your listener, it must stay alive until the listener is destroyed.
Related
It is a class which instance is connected to the external service and it is listening constantly of it.
#Component
public class Service extends PollingBot {
#Value("${token}")
private String token;
#Override
public void onUpdateReceived(Update update) {
if (update.hasMessage()) {
}
}
public void sendMessageToUser(String message) {
try {
execute(sendMessage);
} catch (ApiException e) {
}
}
}
You could see that there is a method called sendMessageToUser which send message. It could not be static because execute method not allow static context. This method could not be separeted to other class. /
So, I have to call this method from other class. However I don't want to create additional instance of Service class otherwise I have two instances which are listen for updates, but I want it is sole class instance doing so.
I have tried to run a Application Context and run method from it, but it was not worked.
So, my question is very simple. How could I run this class non-static(!) method from other class?
By default all spring managed beans are singleton. You need to use #Autowired to inject the bean into other and then you can call the methods of that bean.
#Autowired
private Service service;
public void sendMessage(String message){
service.sendMessageToUser(message);
}
You can use #Autowired annotation to call a method of a bean class(component) in Spring. Also, as mentioned by default beans are singleton in spring so you don't need to worry about creating a single instance explicitly every time.
Try to use the below code in the calling class:
#Autowired
private Service service;
public void sendText() {
service.sendMessage(message);
}
I am developing a project which involves JAX-RS (for REST API) and Websocket (for notifications). The project will be deployed as a WAR into a application server.
For JAX-RS, I do the following:
#ApplicationPath("/")
public class MyApplicationREST extends ResourceConfig {
public MyApplicationREST() {
... initialization here ...
}
}
For Websockets, I do the following:
public class MyApplicationWebsockets implements ServerApplicationConfig {
... callbacks for discovery of endpoints here ...
}
Both classes are perfectly picked up by the application server (Tomcat in my case) when the WAR is deployed and work fine in vacuum.
However, in both classes, I need a reference to a command instance (being the database connection in this case, but it can be anything). I cannot instantiate it in one of the two classes above (and use it in the other), as there is no guarantee of the initialization order of the two classes.
What is the best way to do this?
Initialization
(1) Create a class that implements ServletContextListener.
(2) Write your initialization code in contextInitialized(ServletContextEvent) method.
public class MyContextListener implements ServletContextListener
{
#Override
public void contextInitialized(ServletContextEvent context)
{
// Your initialization code here.
}
#Override
public void contextDestroyed(ServletContextEvent context)
{
// Your finalization code here.
}
}
(3) Register the class as a listener in web.xml.
<listener>
<listener-class>com.example.MyContextListener</listener-class>
</listener>
Shared Instance
Regarding a shared instance, singleton pattern is one of possible means to achieve it.
public class DB
{
private static final DB sInstance = new DB();
// Private constructor to prevent DB instances from being created by others.
private DB()
{
}
// Get the singleton instance.
public static DB getInstance()
{
return sInstance;
}
}
Hi I need to send an email when my application starts and and email when my application stops.
Using spring...
public class Main {
public static void main(String[] args) {
FileSystemXmlApplicationContext fac = new FileSystemXmlApplicationContext("config/applicationContext.xml");
}
}
The rest is wired up through the application context...
I suppose I can just inject a simple bean that implements smart life cycle and send an email from within the start() and stop() methods?
You can simply use a bean in default singleton scope, and declare its init and destroy method. The bean need no adherence to Spring and could be something like :
public class StartAndStop {
public void onStart() {
// send the mail signaling start of application
...
}
public void onStop() {
// send the mail signaling stop of application
...
}
}
In xml config :
<bean class="org.example.StartAndStop" init-method="onStart" destroy-method="onStop"/>
And with Java configuration
#Configuration
public class Configurer {
#Bean(initMethod="onStart", destroyMethod="onStop")
StartAndStop startAndStop() {
return new StartAndStop();
}
... other beans configuration ...
}
Of course, you can also use spring to set properties on the bean ...
Spring automatically raises events in these sitatuations.
You can listen for events by creating an ApplicationListener bean:
#Component
public class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
// is called whenever the application context is initialized or refreshed
}
}
Spring raises the following application context events:
ContextClosedEvent (ApplicationContext gets closed)
ContextRefreshedEvent (ApplicationContext gets initialized or refreshed)
ContextStartedEvent (ApplicationContext gets stopped)
ContextStoppedEvent (ApplicationContext gets stopped)
See Standard and Custom Events documentation
I am having troubles invoking a method asynchronously in Spring, when the invoker is an embedded library receiving notifications from an external system. The code looks as below:
#Service
public class DefaultNotificationProcessor implements NotificationProcessor {
private NotificationClient client;
#Override
public void process(Notification notification) {
processAsync(notification);
}
#PostConstruct
public void startClient() {
client = new NotificationClient(this, clientPort);
client.start();
}
#PreDestroy
public void stopClient() {
client.stop();
}
#Async
private void processAsync(Notification notification) {
// Heavy processing
}
}
The NotificationClient internally has a thread in which it receives notifications from another system. It accepts a NotificationProcessor in its constructor which is basically the object that will do the actual processing of notifications.
In the above code, I have given the Spring bean as the processor and attempted to process the notification asynchronously by using #Async annotation. However, it appears the notification is processed in the same thread as the one used by NotificationClient. Effectively, #Async is ignored.
What am I missing here?
#Async (as well as #Transactional and other similar annotations) will not work when the method is invoked via this (on when #Async is used for private methods*), as long as you do not use real AspectJ compiletime or runtime weaving.
*the private method thing is: when the method is private, then it must been invoked via this - so this is more the consequence then the cause
So change your code:
#Service
public class DefaultNotificationProcessor implements NotificationProcessor {
#Resource
private DefaultNotificationProcessor selfReference;
#Override
public void process(Notification notification) {
selfReference.processAsync(notification);
}
//the method must not been private
//the method must been invoked via a bean reference
#Async
void processAsync(Notification notification) {
// Heavy processing
}
}
See also the answers for: Does Spring #Transactional attribute work on a private method? -- this is the same problem
I have to update a table entry when application is started and stopped.
I have a service which has the calls to the DAO method but when this DAO method is called the SessionFactory which is autowired is null.
I have used 2 methods:
#PostConstruct, #PreDestroy
ApplicationListener onApplicationEvent()
In both the cases I am getting the SessionFactory as null in the DAO class. I am using Setter-Injection in the DAO class for injecting the SessionFactory.
Environment: JDBC-Datasource, Hibernate 3.4, Spring 3.1.2, Weblogic 10.3
It would be great if you could point me in the right direction.
Update:
Thanks for all your comments I got it resolved.Our app is a EAR and my DAO bean config was in a different WAR's applicationContext.xml. I moved the DAO bean config to my shared configuration (appConfig.xml) and it worked like charm. I used #PostConstruct and #PreDestroy
You can do it using SmartLifecycle interface and then configuring it as a bean:
<bean class="com.my.package.MySmartlifecycle">
And your implementation:
public class MySmartLifecycle implements SmartLifecycle{
//autowire anything you need from context
#Override
public void start() {
//do stuff on startup here
}
#Override
public void stop() {
//do stuff on shutdown here
}
#Override
public boolean isRunning() {
return false;
}
#Override
public int getPhase() {
return 0;
}
#Override
public boolean isAutoStartup() {
return true;
}
#Override
public void stop(Runnable callback) {
}
}
If you want to execute method after the context is initialized, you have to use ContextRefreshedEvent. In case of context destroying you should use ContextStoppedEvent, but you also have to remebmer that there is no guarantee that this event will be posted.
#Component
public class SpringStartedListener implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// do something
}
}
#Component
public class SpringClosedListener implements ApplicationListener<ContextStoppedEvent> {
#Override
public void onApplicationEvent(ContextStoppedEvent event) {
// do something
}
}
If you need some more details please refer to http://www.tutorialspoint.com/spring/event_handling_in_spring.htm