andreybleme
andreybleme

Reputation: 689

How to generate a JAR using maven

I have a Springboot application that runs a CLI app.

Here's my main class:

@SpringBootApplication
public class MyApplication {

    @Autowired
    GameClient gameClient;

    @PostConstruct
    public void postConstruct(){
       gameClient.runGame(); 
    }

    public static void main(String[] args) {
        SpringApplication.run(GameApplication.class, args);         
    }
}

When I run the command mvn package to generate a JAR, Spring executes the postConstruct() method and starts my CLI application instead of properly generating my JAR.

When I remove the postConstruct() the JAR is successfully generated, but I need this method becaus it is responsible for running my CLI app.

How can I solve it?

Upvotes: 2

Views: 1396

Answers (3)

Tayyab Shahbaz
Tayyab Shahbaz

Reputation: 11

First you need to update in pom file.

<modelVersion>4.0.0</modelVersion>
    <groupId>com.example.eg</groupId>
    <artifactId>eg</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

then run this command (mvn package -Dmaven.test.skip=true)

Upvotes: 0

Dimitri Mestdagh
Dimitri Mestdagh

Reputation: 44665

The issue is that gameClient.runGame() appears to block your test, either by running infinitely, or by requesting user input. If you have any tests running your Spring boot application, your test (and your build) will block as well.

Even though you can pass the -Dmaven.test.skip=true parameter to skip tests (as mentioned in this answer), it still means that that specific test is broken. Either remove it if you don't need it, or make sure that gameClient.runGame() isn't invoked during a test by doing the following:

Move your logic to a separate class that implements the CommandLineRunner (or ApplicationRunner) interface:

@Component
public class GameRunner implements CommandLineRunner {
    @Autowired
    GameClient gameClient;

    @Override
    public void run(String...args) throws Exception {
        gameClient.runGame();
    }
}

After that, annotate the component with the @Profile annotation, for example:

@Component
@Profile("!test") // Add this
public class GameRunner implements CommandLineRunner {
    @Autowired
    GameClient gameClient;

    @Override
    public void run(String...args) throws Exception {
        gameClient.runGame();
    }
}

By using the @Profile annotation, you can tell Spring to only load the component when certain profiles are active. By using the exclamination mark !, we tell Spring to only load the component if the test profile is not active.

Now, within your test, you can add the @ActiveProfiles("test") annotation. This will enable the test profile when running the test, and that means that the GameRunner bean will not be created.

Upvotes: 2

andreybleme
andreybleme

Reputation: 689

I solved it by skiping the tests when generationg the JAR:

mvn package -Dmaven.test.skip=true

mvn package was invoking my tests, which internally initialized all the beans and, as part of initialization, Spring invokes @PostConstruct methods.

Upvotes: 2

Related Questions