In the context of a classic web application with REST controllers, I've had the need to develop a small Java program that will be called as a regular task using an appropriate scheduler.
The source code of the project has two main classes: one that is the usual Spring boot Application, with some common Spring boot annotations (@EnableAutoConfiguration, @componentScan, etc.)
The second main class is a plain Java class with a static void main method. Since the task program will use data created by the standard web application, I have (without giving it much thought, I must admit), used @Autowired annotations on several class variables to access the data through JPA repositories.
Only now, when running the task program, I hit a NullPointerException on using the first repository. For one second, I was puzzled then I realized that the error is to be expected since Spring does not do its magic.
My question now is how can I have Spring do dependency injection on this plain Java main class? My guess is that there's one or several annotations to put somewhere, but in the wealth of Spring annotations, it's like finding a specific needle in a stack of bags of needles.
[EDIT] The answer by @J-Mengelle is the way to go: I've seen the exact usual console messages when launching the task as when launching the web application.
This is the code to which I got (explanation below):
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Application.class); // This is the Spring boot application class
InputStream is = Application.class.getClassLoader()
.getResourceAsStream("application.properties"); //$NON-NLS-1$
Properties props = new Properties();
props.load(is);
is.close();
ConfigurableEnvironment environment = new StandardEnvironment();
MutablePropertySources propertySources = environment.getPropertySources();
Map<String, Object> myMap = new HashMap<>();
for (Object key : props.keySet()) {
myMap.put((String) key, props.get(key));
}
propertySources.addFirst(new MapPropertySource("MY_MAP", myMap)); //$NON-NLS-1$
ctx.setEnvironment(environment);
ctx.refresh();
However, I hit a first exception with this message:
Cannot determine embedded database driver class for database type NONE
This was because application.properties was not being read and the datasource was not being configured, hence the manual reading above, which I assume is usually taken care of by Spring boot.
After that, one might get into bean creation exceptions. I've faced one such exception with springfox. I then simply removed the @EnableSwagger2 annotation on the Swagger config bean and it went on smoothly from then on, meaning that I could write instructions like actionRepository = ctx.getBean(ActionRepository.class); and have valid references correctly injected into the variables.
Something like this :
public static void main(String[] args) {
ApplicationContext ctx =
new AnnotationConfigApplicationContext(HelloWorldConfig.class);
HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
helloWorld.setMessage("Hello World!");
helloWorld.getMessage();
}
See http://www.tutorialspoint.com/spring/spring_java_based_configuration.htm
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