2

I am trying to build a standalone .jar from a multi-module Maven project.

The project structure is

ema-server/ shared/ # To share with Java clients rest-api/ # Spring REST API server/ # Provides the main() for the standalone and bundles all together web/ # A simple AngularJS web server

The server/ module exists in order to build the standalone .jar. To do so it depends on the rest-api/ module which contains the @SpringBootApplication.

You can take a look at my desperate attempts to make this work but this is my current "solution":

The pom.xml of the server/ module:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <fork>true</fork>
        <mainClass>org.ema.server.Server</mainClass>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2-beta-5</version>
    <configuration>
        <archive>
            <manifest>
                <addClasspath>true</addClasspath>
                <mainClass>org.ema.server.Server</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <id>assemble-all</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

I would like to state here that if I run this thing from within Eclipse as a Java Application everything works.

However, if I run the "standalone" java "*" org.ema.server.Server I am getting:

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to process import candidates for configuration class [org.ema.server.Server]; nested exception is java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.
    at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:488)
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:191)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:321)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:243)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:273)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:98)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:681)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:523)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151)
    at org.ema.server.Server.main(Server.java:30)
Caused by: java.lang.IllegalArgumentException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.
    at org.springframework.util.Assert.notEmpty(Assert.java:276)
    at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getCandidateConfigurations(AutoConfigurationImportSelector.java:152)
    at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.selectImports(AutoConfigurationImportSelector.java:94)
    at org.springframework.context.annotation.ConfigurationClassParser.processDeferredImportSelectors(ConfigurationClassParser.java:480)
    ... 14 common frames omitted

You can take a look at the complete output here.

Can somebody tell me how I can make this work?

Please let me know if I can provide further information.

Stefan Falk
  • 23,898
  • 50
  • 191
  • 378
  • 1
    Why do you have both the spring boot plugin and assembly plugin? They are interfering with each other. You should only use the spring boot plugin. – M. Deinum Feb 06 '17 at 07:14
  • EHrm. Yes, that is the whole point of that plugin... it creates an executable jar file... Only thing you need to do is `java -jar your-jar.jar` and your application will launch.. – M. Deinum Feb 06 '17 at 07:37
  • It indeed looks different because Spring Boot has its own jar loading mechanism for that (hence the `BOOT-INF` introduction in Spring Boot 1.4). – M. Deinum Feb 06 '17 at 08:06
  • Why would you need that? If it is a web application it will already start a tomcat. Else just make it war artifact as explained in the spring boot documentation. Looks like you are trying to solve a problem that isn't there (or making things more complex as needed). – M. Deinum Feb 06 '17 at 08:40
  • Why the separation? What is this server? Is that an artifact or just an attempt to create a jar file? I don't really get your setup. – M. Deinum Feb 06 '17 at 09:02
  • @M.Deinum I just wanted to have a separate project/module for the web client - I don't like the idea of having the web application mixed up with the REST service. That on the other hand requires me to have a `server/` module that bundles everything together in one big standalone `.jar`. I would not know how I could do this another way to be honest. – Stefan Falk Feb 06 '17 at 09:09
  • Why is the web different then the REST? REST is part of the web? Also it is weird to have an api which is an executable to be inside a non executable jar. If it is only the separation you want, just make the rest api a jar (without making it a spring boot app) and make your server a war (which it apparently it/has to be). – M. Deinum Feb 06 '17 at 09:12
  • @M.Deinum I think I have this idea from GWT where it is common to separate everything into `server`, `client` and `shared` code. Some prefer to keep that all up in one project - but once everything gets a bit bigger it's much nicer to separate this stuff into multiple modules. But I see the point that you make - I could get rid of e.g. `server/` and move the `SpringApplication` startup code into e.g. `web/`, make it a `war` and run this as a standalone. I guess that could work. – Stefan Falk Feb 06 '17 at 09:18
  • @M.Deinum Well, I've tried to remove the `server/` modules and make `web/` the "main container" of the Spring application that uses `rest-api/` as a plain dependency but I am running into a lot of problems which I am not sure if it's worth solving them. In the end, everything is working as it should if I run the project inside a servlet container from within Eclipse - the only thing left to do is to include the `web.war` and bind it to a path. The question is basically just how I can tell Spring to load that correctly. – Stefan Falk Feb 06 '17 at 10:42

0 Answers0