Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jib packages spring boot devtools #2336

Closed
saturnism opened this issue Mar 17, 2020 · 12 comments
Closed

jib packages spring boot devtools #2336

saturnism opened this issue Mar 17, 2020 · 12 comments

Comments

@saturnism
Copy link

Environment:

  • Jib version: 2.1.0
  • Build tool: maven
  • OS: macos

Description of the issue:
I created a Spring Boot app w/ devtools dependency:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <scope>runtime</scope>
  <optional>true</optional>
</dependency>

In the resulting image, devtool is actually activated. The dependency is in the image's /app/libs directory.

Expected behavior:
Optional dependency ignored? Spring Boot's plugin excludes devtool by default.
https://docs.spring.io/spring-boot/docs/2.2.5.RELEASE/maven-plugin/repackage-mojo.html

Steps to reproduce:

  1. Create a new spring boot app w/ devtool
  2. Package w/ Jib
  3. See that Jib includes Devtool

jib-maven-plugin Configuration:

<plugin>
  <groupId>com.google.cloud.tools</groupId>
  <artifactId>jib-maven-plugin</artifactId>
  <version>2.1.0</version>
  <configuration>
    <from><image>openjdk:8u222-slim</image></from>
    <to><image>gcr.io/wise-coyote-827/jib-demo</image></to>
    <container><user>nobody:nogroup</user></container></configuration>
</plugin>

Log output:

Additional Information:

@loosebazooka
Copy link
Member

Yeah that makes sense, our logic considers it a runtime dependency. We're not checking for optional. How would this work in a container environment? Someone would inject the dependency at runtime?

@chanseokoh
Copy link
Member

chanseokoh commented Mar 17, 2020

Someone asked this before: #1254 (comment)

Before we start, let's get clear about an optional dependency.

I've seen people mistakenly assume that the <optional>true in Maven implies the dependency should not be included, e.g., at compile-time or runtime. That is not true; with <scope>runtime, it still tells Maven that the dependency is required at runtime when it is a direct dependency.

How do optional dependencies work?

Project-A -> Project-B

The diagram above says that Project-A depends on Project-B. When A declares B as an optional dependency in its POM, this relationship remains unchanged. It's just like a normal build where Project-B will be added in Project-A's classpath.

Therefore, it is correct for Maven and Jib to include spring-boot-devtools as a runtime dependency. It is just that Spring Boot runs a proprietary logic to exclude spring-boot-devtools by default only for their repackaged fat JAR.

To properly resolve this issue, the user should correctly set up the spring-boot-devtools dependency to tell Maven whether they want it at runtime or not, e.g., by setting up two Maven profiles (e.g., dev and prod).


(UPDATE) X-ref: GoogleContainerTools/jib-extensions#31 (comment)

@loosebazooka
Copy link
Member

Oh this is more about development vs deployment.
I feel like the springboot team should've used profiles in their example, not optional.

Anyway, it still seems within the scope of optional use as an exclusionary mechanism for packaging.
See: Why use optional dependencies? at https://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html

@saturnism
Copy link
Author

how can we resolve this? thinking of..

  • explicit exclusions by groupId:artifactId
  • or, simply ignore optionals
  • or, simply jib the produced JAR, which is something i've been advocating :) since the JAR is what user expects to turn into container.

@hjannasch
Copy link

As a workaround use this solution https://blog.frankel.ch/spring-devtools-jib-intellij-idea/

@loosebazooka
Copy link
Member

Yeah, profiles should be the way to go.

@chanseokoh chanseokoh changed the title jib packages spring boot devtool when optional is set to true jib packages spring boot devtools Jul 25, 2020
@chanseokoh
Copy link
Member

We have published a Jib extension for Spring Boot (Maven and Gradle) that covers this issue. You can apply the extension on recent Jib versions.

Details

As discussed in this thread and #1254, Jib is working as intended to package spring-boot-devtools in the image, and the user should properly configure the dependency if they do not want it at runtime. However, we decided to create the extension to help people avoid the chore of manually setting up profiles in their projects.

@beku8
Copy link

beku8 commented Dec 30, 2020

For future reference, I solved the issue with maven profile & scope.

I have two profiles local (active by default for local development) & cloud in my pom.xml.

<profiles>
  <profile>
    <id>local</id>
    <activation>
      <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
      <dev-tools.scope>compile</dev-tools.scope>
    </properties>
  </profile>
  <profile>
    <id>cloud</id>
    <properties>
      <dev-tools.scope>provided</dev-tools.scope>
    </properties>
  </profile>
</profiles>

When scope is provided jib won't include it in the apps/lib folder

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <scope>${dev-tools.scope}</scope>
</dependency>

Then build my docker image with -P cloud like

mvn package myproject -P cloud jib:build -Dimage=myproject

@ChristianCiach
Copy link
Contributor

ChristianCiach commented May 27, 2021

For future reference: When using the Gradle plugin org.springframework.boot, you can configure Jib to use a configuration called productionRuntimeClasspath that doesn't include the devtools (and possibly other dependencies of the developmentOnly configuration).

Example in build.gradle:

jib {
    configurationName = org.springframework.boot.gradle.plugin.SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_NAME
    from {
        image = 'amazoncorretto:16'
    }
    to {
        image = 'myimage'
    }

The referenced constant is not public, which is why I've created an issue at the spring boot project: spring-projects/spring-boot#26686

Instead of referencing the constant, you may just as well just use the string "productionRuntimeClasspath".

@goto1134
Copy link

goto1134 commented Aug 9, 2021

update: use jib-spring-boot-extension to exclude spring-boot-devtools

johnnymillergh added a commit to johnnymillergh/muscle-and-fitness-server that referenced this issue Sep 15, 2021
cuz the existence of spring-boot-devtools causes the
following exception:

java.lang.ClassCastException: class
com.jmsoftware.maf.authcenter.role.entity.RoleExcelBean cannot be cast
to class com.jmsoftware.maf.authcenter.role.entity.RoleExcelBean
(com.jmsoftware.maf.authcenter.role.entity.RoleExcelBean is in unnamed
module of loader 'app';
com.jmsoftware.maf.authcenter.role.entity.RoleExcelBean is in unnamed
module of loader
org.springframework.boot.devtools.restart.classloader.RestartClassLoader
@4ba1c32c)

https://stackoverflow.com/questions/57750294/class-loader-error-unnamed-module-of-loader-org-springframework-boot-devtools

GoogleContainerTools/jib#2336
@StringKe
Copy link

In the latest version configurationName is defined by val it is not modifiable, how do I set configurationName?

@artemptushkin
Copy link

artemptushkin commented Aug 30, 2024

This is not only about devtools but docker-compose too, the default is runtimeclasspath I will open a dedicated issue to question it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants