I am setting up a Spring Boot Application and would like to have the host have access to a System Tray Icon with access to some bean Information.
I currently Tried to Create a Bean for my SystemTrayIcon with the @Autowired details. However When I try to add the SystemTrayIcon I get the following Exception:
Caused by: java.awt.HeadlessException
at java.awt.TrayIcon.<init>(Unknown Source)
at java.awt.TrayIcon.<init>(Unknown Source)
at java.awt.TrayIcon.<init>(Unknown Source)
at hermes.subsrciber.systemTray.HermesTrayIcon.<init>(HermesTrayIcon.java:36)
at hermes.subscriber.boot.AppStarter.trayIcon(AppStarter.java:83)
at hermes.subscriber.boot.AppStarter$$EnhancerBySpringCGLIB$$c4f80849.CGLIB$trayIcon$3(<generated>)
at hermes.subscriber.boot.AppStarter$$EnhancerBySpringCGLIB$$c4f80849$$FastClassBySpringCGLIB$$d62ab0bd.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
at hermes.subscriber.boot.AppStarter$$EnhancerBySpringCGLIB$$c4f80849.trayIcon(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
... 17 more
Is there any way that a SpringBoot Application can have access to System Tray Icons?
I believe I CAN simply define it in the Main method (alongisde the SpringApplication.run) however I would not be able to autowire my properties.
Is this setup possible?
If anyone wants the full code...
import java.awt.AWTException;
import java.awt.CheckboxMenuItem;
import java.awt.Image;
import java.awt.Menu;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.URL;
import javax.annotation.PostConstruct;
import javax.swing.ImageIcon;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
public class MyTrayIcon extends TrayIcon {
private static final String IMAGE_PATH = "/PATH.png";
private static final String TOOLTIP = "Running";
private PopupMenu popup;
final SystemTray tray;
public MyTrayIcon(){
super(createImage(IMAGE_PATH,TOOLTIP),TOOLTIP);
popup = new PopupMenu();
tray = SystemTray.getSystemTray();
try {
setup();
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@PostConstruct
private void setup() throws AWTException{
// Create a pop-up menu components
MenuItem exitItem = new MenuItem("Exit");
popup.add(exitItem);
exitItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
final int exitCode = 0;
ExitCodeGenerator exitCodeGenerator = new ExitCodeGenerator() {
@Override
public int getExitCode() {
return exitCode;
}
};
tray.remove(MyTrayIcon.this);
SpringApplication.exit(Application.context, exitCodeGenerator);
}
});
// popup.addSeparator();
setPopupMenu(popup);
tray.add(this);
}
protected static Image createImage(String path, String description){
URL imageURL = MyTrayIcon.class.getResource(path);
if(imageURL == null){
System.err.println("Failed Creating Image. Resource not found: "+path);
return null;
}else {
return new ImageIcon(imageURL,description).getImage();
}
}
}
And in your Application.java:
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableConfigurationProperties(StorageProperties.class)
public class Application {
public static ConfigurableApplicationContext context;
public static void main(String[] args) {
//SpringApplication.run(Application.class, args);
SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
builder.headless(false);
context = builder.run(args);
MyTrayIcon m = new MyTrayIcon();
}
}
The Solution is, rather than using SpringApplication.run(MyConfig.class,args)
, use the following setup:
SpringApplicationBuilder builder = new SpringApplicationBuilder(MyConfig.class);
builder.headless(false);
ConfigurableApplicationContext context = builder.run(args);
To actually add the System Icon I then added a bean of the followign type:
public class MyTrayIcon extends TrayIcon {
private static final String IMAGE_PATH = "/path/icon_16x16.png";
private static final String TOOLTIP = "Text";
private PopupMenu popup;
private SystemTray tray;
public MyTrayIcon(){
super(createImage(IMAGE_PATH,TOOLTIP),TOOLTIP);
popup = new PopupMenu();
tray = SystemTray.getSystemTray();
}
@PostConstruct
private void setup() throws AWTException{
// popup.add(itemAbout);
// here add the items to your popup menu. These extend MenuItem
// popup.addSeparator();
setPopupMenu(popup);
tray.add(this);
}
protected static Image createImage(String path, String description){
URL imageURL = MyTrayIcon.class.getResource(path);
if(imageURL == null){
System.err.println("Failed Creating Image. Resource not found: "+path);
return null;
}else {
return new ImageIcon(imageURL,description).getImage();
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With