1

I'd like to do a simple main using Spring boot and have some fields autowired.

I'd like the app to fail (error-code != 0) if some exception is thrown in the process.

Example:

@SpringBootApplication
public class SqlInserterMain
{
    @Autowired
    private static JdbcTemplate jdbcTemplate;

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(SqlInserterMain.class, args);

        insertData();

        context.close();
    }

    private static void insertData()
    {
        // Do something with jdbcTemplate.
        // If jdbcTemplate fails on exception, the app should fail and return some error code.
        System.out.println("YOYO" + jdbcTemplate);
    }
}

But, jdbcTemplate is null.

If I add a @component or an ApplicationRunner, the @autowire will work but I won't get the main to fail.

Any idea how to do a fast and simple main with some autowired fields that will fail on an exception? Thanks.

AlikElzin-kilaka
  • 34,335
  • 35
  • 194
  • 277

3 Answers3

2

I think you want to execute code on startup

You can use ApplicationListener and auto wire JdbcTemplate or beans you need to execute task

@Component
@Order(0)
class MyApplicationListener 
    implements ApplicationListener<ApplicationReadyEvent> {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        System.out.println("YOYO" + jdbcTemplate);
    }
}
AlikElzin-kilaka
  • 34,335
  • 35
  • 194
  • 277
Ori Marko
  • 56,308
  • 23
  • 131
  • 233
  • Will the the whole app stop and return and error code if an exception is thrown in the `ApplicationListener`? – AlikElzin-kilaka Jun 15 '20 at 08:59
  • @AlikElzin-kilaka if you throw an exception https://stackoverflow.com/questions/56837551/shutdown-spring-application-from-applicationlistener – Ori Marko Jun 15 '20 at 09:10
  • I tested this and it partly works. When an exception was thrown, the app indeed stopped but the error code was `0` :( – AlikElzin-kilaka Jun 15 '20 at 09:33
  • what error code do you mean? process exit code? this solution is the cleanest for sure! – bbortt Jun 15 '20 at 09:36
  • Yes, the app (process) returned exit code 0 even though an exception occurred and haven't been caught be my code. I'd like spring boot to fail with an exit code `1` - just like a regular java main. – AlikElzin-kilaka Jun 15 '20 at 09:42
  • @AlikElzin-kilaka You can use `ExitCodeExceptionMapper` https://www.baeldung.com/spring-boot-exit-codes – Ori Marko Jun 15 '20 at 10:08
1

Eventually, I manually wired the bean, caught the exception, printed the exception and exit myself (close() or System.exit(1)) :(

I wish spring-boot had some way to behave like a normal java main.

@SpringBootApplication
public class SqlInserterMain
{
    private static JdbcTemplate jdbcTemplate;

    public static void main(String[] args)
    {
        ConfigurableApplicationContext context = SpringApplication.run(SqlInserterMain.class, args);

        try
        {
            jdbcTemplate = context.getBean(JdbcTemplate.class);

            insertData();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            System.exit(1);
        }

        context.close();
    }

    private static void insertData()
    {
        // Do something with jdbcTemplate.
        // If jdbcTemplate fails on exception, the app should fail and return some error code.
        System.out.println("YOYO" + jdbcTemplate);
    }
}
AlikElzin-kilaka
  • 34,335
  • 35
  • 194
  • 277
0

I don't think SqlInserterMain is considered to be a bean managed by Spring (well, it's not instantiated by Spring, is it?). Just create an additional bean (as yAzou mentioned) or manually extract the JdbcTemplate from the Spring context.

Marek Puchalski
  • 3,286
  • 2
  • 26
  • 35
  • 1
    I eventually did `jdbcTemplate = context.getBean(JdbcTemplate.class);` but I was wondering if there's a way to do this using `@Autowired`. – AlikElzin-kilaka Jun 15 '20 at 07:26
  • 1
    There is a way to do it using @Autowired: Put it in another class and make it non-static. –  Jun 15 '20 at 07:37
  • @Taschi - How do you instantiate that other class? – AlikElzin-kilaka Jun 15 '20 at 07:45
  • You do not. Annotate it with @Component, and Spring will instantiate it for you. –  Jun 15 '20 at 07:46
  • @Taschi - As required by the question, will it fail the whole main on exception? – AlikElzin-kilaka Jun 15 '20 at 08:03
  • If Spring Boot tries and fails to autowire something, your application will always exit with rc != 0, so yes. In your case, Spring Boot does not even try because you use @Autowired in a context where it is not actually allowed. I suggest reading up on how Spring CDI actually works. –  Jun 15 '20 at 08:09
  • 1
    @Taschi - An exception can be thrown in the code logic, regardless of the `@Autowired`. I'd like the whole spring application to fail if my code have thrown an exception. – AlikElzin-kilaka Jun 15 '20 at 08:17
  • If you use Spring Batch, it'll generally do that if there's an error inside a batch step. –  Jun 15 '20 at 08:23
  • How about manually calling `System.exit(foo);` or https://www.baeldung.com/spring-boot-shutdown in case of errors (in the exception catch block)? – Marek Puchalski Jun 15 '20 at 10:01