Reputation: 311
I'd like using spring-boot-starter-data-jpa features to create a non-web aplication. In the 52.4 documentation says:
Application code that you want to run as your business logic can be implemented as a CommandLineRunner and dropped into the context as a @Bean definition.
My AppPrincipalFrame looks like:
@Component
public class AppPrincipalFrame extends JFrame implements CommandLineRunner{
private JPanel contentPane;
@Override
public void run(String... arg0) throws Exception {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
AppPrincipalFrame frame = new AppPrincipalFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
And boot application class looks like:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(Application.class, args);
AppPrincipalFrame appFrame = context.getBean(AppPrincipalFrame.class);
}
}
But does not work. Anybody have a sample about this?
Edited and exception added.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appPrincipalFrame'.
Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [es.adama.swing.ui.AppPrincipalFrame]: Constructor threw exception; nested exception is java.awt.HeadlessException
Regards.
Upvotes: 27
Views: 38243
Reputation: 1
//@Component
public class SwingApp extends JFrame {
vv...
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class)
.headless(false).run(args);
SwingApp sw = new SwingApp();
sw.setVisible(true);
}
}
//@Component
public class SwingApp extends JFrame {
vv...
private void jButtonRunSpringServer(java.awt.event.ActionEvent evt){
String [] args = {"abc","xyz"};
Application.runSpringServer(args);
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SwingApp sw = new SwingApp();
sw.setVisible(true);
}
public static void runSpringServer(String[] args) {
/*
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class)
.headless(false).run(args);
*/
SpringApplication.run(Application.class, args);
}
}
Upvotes: 0
Reputation: 6808
Another simple and elegant solution is to disable headless property as shown here. You will have to do it though, right before you create/show the JFrame.
System.setProperty("java.awt.headless", "false"); //Disables headless
So, the thing that worked for me:
SpringApplication.run(MyClass.class, args);
System.setProperty("java.awt.headless", "false");
SwingUtilities.invokeLater(() -> {
JFrame f = new JFrame("myframe");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
});
Annotations in MyClass.class (I am not aware if they play any role):
@SpringBootApplication
@EnableWebMvc
Upvotes: 6
Reputation: 11637
The Swing application must be placed on the Swing Event Queue. Not doing so is a serious mistake.
So the correct way to do it:
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(SwingApp.class)
.headless(false).run(args);
EventQueue.invokeLater(() -> {
SwingApp ex = ctx.getBean(SwingApp.class);
ex.setVisible(true);
});
}
In addition, we can just use the @SpringBootApplication
annotation.
@SpringBootApplication
public class SwingApp extends JFrame {
See my Spring Boot Swing integration tutorial for a full working example.
Upvotes: 18
Reputation: 1532
It's been a while since you posted the question, but I run out with the same problem in a old project that I'm migrating and figured a different way, I think that more clear, to make the things work.
Instead of using SpringApplication.run(Application.class, args);
you can use: new SpringApplicationBuilder(Main.class).headless(false).run(args);
and it isn't necessary to make toy Application class extends from JFrame. Therefore the code could look like:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(Application.class).headless(false).run(args);
AppPrincipalFrame appFrame = context.getBean(AppPrincipalFrame.class);
}
Upvotes: 44