Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid putting a specific version of Spring Boot in a library

I am developing a library based on Spring Boot, which could be used in multiple Spring Boot applications. The library is supposed to work with Spring Boot 1.3.0.M1 onwards.

I was thinking how to avoid putting a specific version of Spring JARs in it, and instead let the application specify the exact version. Currently I have come out with this solution, which seems to work except with certain combinations:

  1. In the library, have the Spring Boot version as 1.3.0.M1, and have the scope of all the dependencies as provided. Like this:

    ...
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.0.M1</version>
        <relativePath/>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <scope>provided</scope>
        </dependency>
    ...
    
  2. In the application, mention the actual Spring Boot version, e.g. 1.3.0.M3, and re-include all the dependencies, like this:

    ...
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.0.M3</version>
        <relativePath/>
    </parent>
    
    <dependencies>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
     ...
    

When I run the application with this 1.3.0.M1+1.3.0.M3 specific combination, I'm getting this error, which I think is just some compatibility issue:

Exception in thread "main" java.lang.NoSuchMethodError: org.springframework.core.ResolvableType.forInstance(Ljava/lang/Object;)Lorg/springframework/core/ResolvableType;

However, experimenting with stable releases, e.g. when I set the lib version to 1.2.0.RELEASE and the app version to 1.2.5.RELEASE, it works.

So, I was wondering whether this would be the right way to handle such scenario, or there is a better way.

like image 491
Sanjay Avatar asked Nov 09 '22 07:11

Sanjay


1 Answers

You're mixing optional dependencies and dependency management. If your library requires Spring Boot to run, then you must specify the dependencies with the default scope.

If the user doesn't do anything and just import your library, then he'll get 1.3.0.M1 because that's what available by default.

If you now create a project from start.spring.io using for instance 1.3.0.M3 and add your library to it, you'll see that the project is using 1.3.0.M3. This is because that project has a dependency management section that enforces the use of Spring Boot 1.3.0.M3.

In other words, the user has to specify which version of a library he wants to use; as a library developer, there is nothing you can do.

Regarding the error, it is impossible to figure out what you're doing but my best guess is that you are trying to override both Spring framework and Spring boot with incompatible versions. You may want to review and better understand what dependency management is. This question is a good starting point.

like image 169
Stephane Nicoll Avatar answered Nov 15 '22 06:11

Stephane Nicoll