I created a library with these pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>spring.boot</groupId>
<artifactId>jwt</artifactId>
<version>0.0.1</version>
<name>jwt</name>
<description>A library of the boilerplate configuration for securing a Spring Boot API with JWT </description>
<properties>
<java.version>21</java.version>
</properties>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I packaged it via mvn clean install
. Then, to test it, I added it to my local maven repository: ~/.m2/repository
by running: mvn install:install-file -Dfile=jwt-0.0.1.jar -DgroupId=spring.boot -DartifactId=jwt -Dversion=0.0.1 -Dpackaging=jar
and included it in a different project's pom.xml like so:
<dependency>
<groupId>spring.boot</groupId>
<artifactId>jwt</artifactId>
<version>0.0.1</version>
</dependency>
But, IntelliJ still shows can't find symbol
when I try to use the classes in the library.
My trouble-shooting so far:
How can I fix this guys?
TLDR:
Remove spring-boot-maven-plugin
in your library pom and you are done.
Full answer:
You used spring-boot-maven-plugin
which creates an executable uber-jar in a special format.
The Nested JARs section explains:
Java does not provide any standard way to load nested jar files (that is, jar files that are themselves contained within a jar). This can be problematic if you need to distribute a self-contained application that can be run from the command line without unpacking.
To solve this problem, many developers use “shaded” jars. A shaded jar packages all classes, from all jars, into a single “uber jar”. The problem with shaded jars is that it becomes hard to see which libraries are actually in your application. It can also be problematic if the same filename is used (but with different content) in multiple jars. Spring Boot takes a different approach and lets you actually nest jars directly.
The Executable Jar File Structure
Spring Boot Loader-compatible jar files should be structured in the following way:
example.jar | +-META-INF | +-MANIFEST.MF +-org | +-springframework | +-boot | +-loader | +-<spring boot loader classes> +-BOOT-INF +-classes | +-mycompany | +-project | +-YourClasses.class +-lib +-dependency1.jar +-dependency2.jar
Application classes should be placed in a nested
BOOT-INF/classes
directory. Dependencies should be placed in a nestedBOOT-INF/lib
directory.
This is precisely the format you see in your IDE.
Unfortunately, this jar in this format cannot be consumed as a library.
You need to package your library as a regular jar (ideally, not an uber-jar - maven will resolve the transitive dependencies)