On many large e-commerce projects server startup can take up to 6-10 minutes. Hybris projects I worked at are not exception. So usually when I start the tomcat server I can do lots of other things. e.g. reading the spec, browsing the net or even continue development in my IDE. So after 5-6 minutes I can forget about the fact that my server is starting up. So I thought that it would be great to have a tool that can notify me as soon as tomcat starts up and I decided to develop it. So basically what the tool has to do is to understand when tomcat server finishes startup and call OS utility to notify me about it.
OOTB hybris uses Growl to notify developer about init/update actions. To activate it you need to install Growl for windows or Grow for OS X and add it your PATH.
Unfortunately Hybris does not support “server is ready” notification. But there is very simply way to do that. First of all tomcat has The LifeCycle Listener Component that can let us know about different events in tomcat server.
public interface Lifecycle { String BEFORE_INIT_EVENT = "before_init"; String AFTER_INIT_EVENT = "after_init"; String START_EVENT = "start"; String BEFORE_START_EVENT = "before_start"; String AFTER_START_EVENT = "after_start"; String STOP_EVENT = "stop"; String BEFORE_STOP_EVENT = "before_stop"; String AFTER_STOP_EVENT = "after_stop"; String AFTER_DESTROY_EVENT = "after_destroy"; String BEFORE_DESTROY_EVENT = "before_destroy"; String PERIODIC_EVENT = "periodic"; String CONFIGURE_START_EVENT = "configure_start"; String CONFIGURE_STOP_EVENT = "configure_stop"; }
From the list above AFTER_START_EVENT is the most appropriate event we can listen to. OK, it clear about event, but how should we put notification in the system tray? Basically there are two options:
- Use Growl via command line tool as Hybris does
- Use Java’s SystemTray class
As a good developer I think we should support both versions. So when Growl exists – use it, if does not exist – use default system tray. Lets write our implementation.
Step 1 – Create a project that can be packed as jar
As maven is still the most popular build tool lets create project from maven archetype.
mvn archetype:generate -DgroupId=com.wordpress.nikitapavlenko -DartifactId=tomcat-notification -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
My maven pom.xml is following:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wordpress.nikitapavlenko</groupId> <artifactId>tomcat-notification</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>tomcat-notification</name> <url>http://maven.apache.org</url> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina</artifactId> <version>7.0.12</version> </dependency> </dependencies> </project>
Step 2 – Implement org.apache.catalina.LifecycleListener
package com.wordpress.nikitapavlenko; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleListener; import java.awt.*; import java.awt.TrayIcon.MessageType; import java.io.IOException; import java.net.URL; import java.util.Calendar; import java.util.Map; public class TomcatListener implements LifecycleListener { @Override public void lifecycleEvent(LifecycleEvent event) { if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) { if (growlExist()) { notifyViaGrowl(); } else { notifyViaDefaultSystemTray(); } } } private void notifyViaGrowl() { try { String message = "\"Server successfully started. [" + Calendar.getInstance().getTime()+"]\""; Runtime.getRuntime().exec("growlnotify /t:Tomcat " + message); System.out.println("Growl notification sent"); } catch (IOException e) { e.printStackTrace(); } } private boolean growlExist() { Map<String, String> env = System.getenv(); String path = env.get("Path"); return path != null && path.toLowerCase().contains("growl"); } private void notifyViaDefaultSystemTray() { SystemTray tray = SystemTray.getSystemTray(); TrayIcon trayIcon = createTrayIcon(); try { tray.add(trayIcon); trayIcon.displayMessage("Tomcat", "Server successfully started.", MessageType.INFO); System.out.println("System tray notification sent"); } catch (AWTException e) { e.printStackTrace(); } } private TrayIcon createTrayIcon() { URL resource = getClass().getClassLoader().getResource("icon.png"); Image image = Toolkit.getDefaultToolkit().createImage(resource); TrayIcon trayIcon = new TrayIcon(image, "Tomcat"); trayIcon.setImageAutoSize(true); trayIcon.setToolTip("Hybris server"); return trayIcon; } }
Step 3 – Package sources as jar file
mvn clean package
At this moment you will have an artifact “tomcat-notification-1.0-SNAPSHOT.jar”
Step 4 – Register listener in the server.xml
For the based hybris app open config/tomcat/conf/server.xml and add a new listener there:
... <Listener className="com.wordpress.nikitapavlenko.TomcatListener" context="GenericJavaBeanResource"/> ...
Step 5 – Add our jar to tomcat lib folder
For the hybris based project add this jar to config/customize/platform/tomcat/lib and don’t forget to run customize target before ant all.
Step 6 – Results
When growl is in system’s Path:
When growl is not in the system’s Path:
The source code is available my Github. Thanks for reading!