1

The task is to extend existing spring boot application and override some of the beans and deploy it in spring boot.

Kotlin language is used. So I have spring boot application (APP-A)

    @SpringBootApplication
    open class MyApp { 
        ... //start staff here 
    }

And I have a module (MODULE-B) which extends some existing logic with dependency injection

open class ExtensionModule { 
//... extension logic is here 
}

for this module, spring autoconfiguration is used. So it should be registered in spring container

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.ExtensionModule

When I have the dependency in pom.xml(APP-A) on MODULE-B everything work just fine. My goal is to build a docker image without dependency in pom.xml, so in such case APP-A will know nothing about MODULE-B but the logic will be extended, like with old spring container classpath-xml based approach I tested with next Dockerfile

FROM openjdk:8-jre

ADD app-a.jar /usr/share/jvmservice/app-a.jar
ADD module-b.jar /usr/share/jvmservice/module-b.jar

ENTRYPOINT exec /usr/bin/java $JAVA_OPTS -jar /usr/share/jvmservice/app-a.jar

The result is that app-a is successfully launched, but no changes from module-b are applied. Is it possible to compose the docker image with two jars in one spring container, without explicit dependency?

user2105282
  • 724
  • 1
  • 12
  • 26
  • forgot docker for a moment, can you give me a command how you start your APP-A locally(assuming while building APP-A module-B is not included in it's dependency) and it works the way you want? – Satish Feb 07 '19 at 08:41
  • In IntelliJ IDEA I just run the main class of spring boot application "MyApp", with dependency in pom.xml it works fine with autoconfigured MODULE-B – user2105282 Feb 07 '19 at 09:15
  • Without MyApp knowing about module B, there is no way you can use module b features in your MyApp. So, now if your ok with having module b as dependency then follow @Ilya answer given here. – Satish Feb 09 '19 at 18:42

1 Answers1

1

You need to add module-b.jar to the classpath, use the following to do that

FROM openjdk:8-jre

COPY app-a.jar /usr/share/jvmservice/app-a.jar
COPY module-b.jar /usr/share/jvmservice/ext/module-b.jar

ENTRYPOINT exec /usr/bin/java $JAVA_OPTS -Dloader.path="/usr/share/jvmservice/ext/" -jar /usr/share/jvmservice/app-a.jar

For more information see Launching Executable Jars

Ilya
  • 2,177
  • 15
  • 19
  • Thanks for the answer. Tried the solution you suggested, also tried to put just in /lib folder, which should be the default place to pass jar components. Libraries placed in the '/lib' folder can be used correctly, but the jar with some spring Autoconfigurable module doesn't autoconfigure at all. It seems that it is required to tell spring container to add the jar to the container – user2105282 Feb 11 '19 at 11:03
  • Something similar is done in this article https://aboullaite.me/the-magic-behind-the-magic-spring-boot-autoconfiguration/. Is it possible to somehow understand which jars are located in classpath? It seems that the application should work fine when autoconfigurable module is in classpath, but fo some reason nothing happens – user2105282 Feb 11 '19 at 11:26
  • Ok it seems that it should be added to manifest file, what isn't very convinient https://stackoverflow.com/questions/39716796/spring-boot-executable-jar-with-classpath – user2105282 Feb 11 '19 at 12:19
  • I'm not sure I got your comments. Do you mean that spring autoconfiguration doesn't work for jar which are loaded from `loader.path` ? – Ilya Feb 11 '19 at 16:59
  • 1
    Yes. The main reason that they should be added to classpath. See the stackoverflow link above. It can be done by modifying manifest file, or doing like ENTRYPOINT exec /usr/bin/java -cp ""$JAVA_OPTS
    . it works fine with such two options
    – user2105282 Feb 12 '19 at 05:44