by Guest » 13 Jan 2025, 13:33
Ich arbeite an der Optimierung einer Spring Boot-Anwendung, indem ich Abhängigkeiten zur Laufzeit herunterlade, anstatt sie in die endgültige JAR-Datei zu packen. Obwohl ich den Download-Mechanismus erfolgreich implementiert habe, erkennt Spring Boot diese dynamisch geladenen Abhängigkeiten nicht, obwohl sie über den Java ClassLoader zugänglich sind.
Ziel:
Reduzieren Sie die endgültige JAR-Größe durch:
- Abhängigkeiten aus dem kompilierten JAR ausschließen
- Erforderliche Abhängigkeiten herunterladen unter Laufzeit
- Dynamisches Laden mit URLClassLoader
Mein Hintergrund
Ich habe online nach möglichen Lösungen gesucht, aber keine gefunden. Ich habe zuvor bei der Entwicklung von Minecraft-Plugins mit Libby etwas Ähnliches mit Core Java gehandhabt, bin mir aber nicht sicher, ob das mit Spring Boot machbar ist. Obwohl ich KI-Tools verwendet habe, um einige Abhängigkeitsprobleme zu lösen, stecke ich jetzt an diesem Punkt fest.
Meine aktuelle Implementierung
DependancyLoader.java
Code: Select all
package com.hapangama.sunlicense.boot;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.CollectResult;
import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.collection.DependencySelector;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyFilter;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.resolution.DependencyResult;
import org.eclipse.aether.util.filter.DependencyFilterUtils;
import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator;
import org.springframework.stereotype.Service;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@Service
public class DependencyLoader {
private static final Logger LOGGER = Logger.getLogger(DependencyLoader.class.getName());
private static final String DEPENDENCIES_DIR = "BOOT-INF/lib";
public static void initializeDependencies() throws Exception {
// Create libs directory if it doesn't exist
File libsDir = new File(DEPENDENCIES_DIR);
if (!libsDir.exists()) {
libsDir.mkdirs();
}
// Initialize Maven components
RepositorySystem system = Booter.newRepositorySystem();
DefaultRepositorySystemSession session = Booter.newRepositorySystemSession(system);
session.setLocalRepositoryManager(
system.newLocalRepositoryManager(
session,
new LocalRepository(libsDir.getAbsolutePath())
)
);
// Define repositories
List repositories = Arrays.asList(
new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2/")
.setPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.build(),
new RemoteRepository.Builder("spring-releases", "default", "https://repo.spring.io/release")
.setPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.build(),
new RemoteRepository.Builder("jcenter", "default", "https://jcenter.bintray.com")
.setPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.build(),
new RemoteRepository.Builder("vaadin-addons", "default", "https://maven.vaadin.com/vaadin-addons")
.setPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.build()
);
// Define dependencies
List dependencies = Arrays.asList(
// Spring Boot dependencies
new Dependency(new DefaultArtifact("org.springframework.boot:spring-boot-starter-data-jpa:2.5.4"), "runtime"),
new Dependency(new DefaultArtifact("org.springframework.boot:spring-boot-starter-security:2.5.4"), "runtime"),
// Vaadin and related dependencies
new Dependency(new DefaultArtifact("com.vaadin:vaadin-spring-boot-starter:24.0.0"), "runtime"),
new Dependency(new DefaultArtifact("in.virit:viritin:2.10.1"), "runtime"),
new Dependency(new DefaultArtifact("com.github.appreciated:apexcharts:24.0.1"), "runtime"),
new Dependency(new DefaultArtifact("org.parttio:starpass-theme:1.0.4"), "runtime"),
new Dependency(new DefaultArtifact("org.vaadin.crudui:crudui:7.1.2"), "runtime"),
// Database
new Dependency(new DefaultArtifact("com.h2database:h2:2.1.214"), "runtime"),
// Utility libraries
new Dependency(new DefaultArtifact("org.modelmapper:modelmapper:3.2.0"), "runtime"),
// Discord integration
new Dependency(new DefaultArtifact("net.dv8tion:JDA:5.2.1"), "runtime")
);
// Create collection request
CollectRequest collectRequest = new CollectRequest();
collectRequest.setRepositories(repositories);
dependencies.forEach(collectRequest::addDependency);
// Resolve dependencies
DependencyResult result = resolveDependencies(system, session, collectRequest);
// Get resolved artifact files
List artifactFiles = getArtifactFiles(result);
// Create and set up the custom ClassLoader
URL[] urls = artifactFiles.stream()
.map(file -> {
try {
return file.toURI().toURL();
} catch (MalformedURLException e) {
LOGGER.warning("Failed to convert file to URL: " + file);
return null;
}
})
.filter(Objects::nonNull)
.toArray(URL[]::new);
URLClassLoader classLoader = new URLClassLoader(urls, DependencyLoader.class.getClassLoader());
Thread.currentThread().setContextClassLoader(classLoader);
// Verify critical dependencies
verifyDependencies(classLoader);
}
private static DependencyResult resolveDependencies(RepositorySystem system,
RepositorySystemSession session,
CollectRequest collectRequest) throws Exception {
CollectResult collectResult = system.collectDependencies(session, collectRequest);
DependencyRequest dependencyRequest = new DependencyRequest(collectResult.getRoot(),
DependencyFilterUtils.classpathFilter("compile", "runtime"));
return system.resolveDependencies(session, dependencyRequest);
}
private static List getArtifactFiles(DependencyResult result) {
PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
result.getRoot().accept(nlg);
return nlg.getArtifacts(false).stream()
.map(Artifact::getFile)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private static void verifyDependencies(ClassLoader classLoader) {
try {
// Verify JDA
Class.forName("net.dv8tion.jda.api.hooks.ListenerAdapter", true, classLoader);
LOGGER.info("JDA dependency loaded successfully");
// Verify Spring Boot
Class.forName("org.springframework.boot.SpringApplication", true, classLoader);
LOGGER.info("Spring Boot dependency loaded successfully");
// Add other critical dependency verifications as needed
} catch (ClassNotFoundException e) {
LOGGER.severe("Failed to verify critical dependency: " + e.getMessage());
throw new RuntimeException("Critical dependency verification failed", e);
}
}
}
Booter.java
Code: Select all
package com.hapangama.sunlicense.boot;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
import org.eclipse.aether.impl.DefaultServiceLocator;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
import org.eclipse.aether.util.listener.ChainedRepositoryListener;
import org.eclipse.aether.util.listener.ChainedTransferListener;
import java.io.File;
// Booter.java
public class Booter {
public static RepositorySystem newRepositorySystem() {
DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
locator.addService(TransporterFactory.class, FileTransporterFactory.class);
locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
return locator.getService(RepositorySystem.class);
}
public static DefaultRepositorySystemSession newRepositorySystemSession(RepositorySystem system) {
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
LocalRepository localRepo = new LocalRepository("target/local-repo");
session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
session.setTransferListener(new ChainedTransferListener());
session.setRepositoryListener(new ChainedRepositoryListener());
return session;
}
}
Hauptklasse
Code: Select all
package com.hapangama.sunlicense;
import com.hapangama.sunlicense.boot.DependencyLoader;
import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.theme.Theme;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collections;
import java.util.Properties;
@Theme(value = "sun")
@SpringBootApplication(exclude = ErrorMvcAutoConfiguration.class)
public class SunLicenseApplication implements AppShellConfigurator {
public static void main(String[] args) {
try {
// Initialize dependencies before starting Spring
DependencyLoader.initializeDependencies();
// Get the context class loader that has our dependencies
ClassLoader customClassLoader = Thread.currentThread().getContextClassLoader();
// Create Spring application
SpringApplication app = new SpringApplication(SunLicenseApplication.class);
Properties properties = new Properties();
properties.put("spring.main.allow-bean-definition-overriding", "true");
properties.put("spring.main.allow-circular-references", "true");
app.setDefaultProperties(properties);
// Important: Set both resource loader and context class loader
app.setResourceLoader(new DefaultResourceLoader(customClassLoader));
Thread.currentThread().setContextClassLoader(customClassLoader);
ConfigurableApplicationContext context = app.run(args);
if (context != null && context.isActive()) {
System.out.println("Application started successfully");
System.out.println("Active profiles: " + Arrays.toString(context.getEnvironment().getActiveProfiles()));
}
} catch (Exception e) {
System.out.println("Failed to start application");
e.printStackTrace();
System.exit(1);
}
}
}
Protokoll der Startkonsole
Java konnte JDA laden (eine der Bibliotheken erfolgreich)
Code: Select all
INFO: JDA dependency loaded successfully
aber es wirft die Klasse aus, die später aus irgendeinem Grund nicht gefunden wurde.
Code: Select all
Caused by: java.lang.ClassNotFoundException: net.dv8tion.jda.api.hooks.ListenerAdapter
https://paste.hapangama.com/egewawovif.properties
Pom.xml
Code: Select all
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.3.5
com.hapangama
SunLicense
0.0.1-SNAPSHOT
SunLicense
SunLicense
17
24.5.4
Vaadin Directory
https://maven.vaadin.com/vaadin-addons
false
org.springframework.boot
spring-boot-starter-data-jpa
provided
org.springframework.boot
spring-boot-starter-security
provided
com.vaadin
vaadin-spring-boot-starter
provided
com.h2database
h2
provided
org.projectlombok
lombok
true
Ich arbeite an der Optimierung einer Spring Boot-Anwendung, indem ich Abhängigkeiten zur Laufzeit herunterlade, anstatt sie in die endgültige JAR-Datei zu packen. Obwohl ich den Download-Mechanismus erfolgreich implementiert habe, erkennt Spring Boot diese dynamisch geladenen Abhängigkeiten nicht, obwohl sie über den Java ClassLoader zugänglich sind.
[b]Ziel:[/b]
Reduzieren Sie die endgültige JAR-Größe durch:
[list]
[*]Abhängigkeiten aus dem kompilierten JAR ausschließen
[*]Erforderliche Abhängigkeiten herunterladen unter Laufzeit
[*]Dynamisches Laden mit URLClassLoader
[/list]
[b]Mein Hintergrund[/b]
Ich habe online nach möglichen Lösungen gesucht, aber keine gefunden. Ich habe zuvor bei der Entwicklung von Minecraft-Plugins mit Libby etwas Ähnliches mit Core Java gehandhabt, bin mir aber nicht sicher, ob das mit Spring Boot machbar ist. Obwohl ich KI-Tools verwendet habe, um einige Abhängigkeitsprobleme zu lösen, stecke ich jetzt an diesem Punkt fest.
[b]Meine aktuelle Implementierung[/b]
DependancyLoader.java
[code]package com.hapangama.sunlicense.boot;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.CollectResult;
import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.collection.DependencySelector;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyFilter;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.resolution.DependencyResult;
import org.eclipse.aether.util.filter.DependencyFilterUtils;
import org.eclipse.aether.util.graph.selector.ScopeDependencySelector;
import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator;
import org.springframework.stereotype.Service;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@Service
public class DependencyLoader {
private static final Logger LOGGER = Logger.getLogger(DependencyLoader.class.getName());
private static final String DEPENDENCIES_DIR = "BOOT-INF/lib";
public static void initializeDependencies() throws Exception {
// Create libs directory if it doesn't exist
File libsDir = new File(DEPENDENCIES_DIR);
if (!libsDir.exists()) {
libsDir.mkdirs();
}
// Initialize Maven components
RepositorySystem system = Booter.newRepositorySystem();
DefaultRepositorySystemSession session = Booter.newRepositorySystemSession(system);
session.setLocalRepositoryManager(
system.newLocalRepositoryManager(
session,
new LocalRepository(libsDir.getAbsolutePath())
)
);
// Define repositories
List repositories = Arrays.asList(
new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2/")
.setPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.build(),
new RemoteRepository.Builder("spring-releases", "default", "https://repo.spring.io/release")
.setPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.build(),
new RemoteRepository.Builder("jcenter", "default", "https://jcenter.bintray.com")
.setPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.build(),
new RemoteRepository.Builder("vaadin-addons", "default", "https://maven.vaadin.com/vaadin-addons")
.setPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.build()
);
// Define dependencies
List dependencies = Arrays.asList(
// Spring Boot dependencies
new Dependency(new DefaultArtifact("org.springframework.boot:spring-boot-starter-data-jpa:2.5.4"), "runtime"),
new Dependency(new DefaultArtifact("org.springframework.boot:spring-boot-starter-security:2.5.4"), "runtime"),
// Vaadin and related dependencies
new Dependency(new DefaultArtifact("com.vaadin:vaadin-spring-boot-starter:24.0.0"), "runtime"),
new Dependency(new DefaultArtifact("in.virit:viritin:2.10.1"), "runtime"),
new Dependency(new DefaultArtifact("com.github.appreciated:apexcharts:24.0.1"), "runtime"),
new Dependency(new DefaultArtifact("org.parttio:starpass-theme:1.0.4"), "runtime"),
new Dependency(new DefaultArtifact("org.vaadin.crudui:crudui:7.1.2"), "runtime"),
// Database
new Dependency(new DefaultArtifact("com.h2database:h2:2.1.214"), "runtime"),
// Utility libraries
new Dependency(new DefaultArtifact("org.modelmapper:modelmapper:3.2.0"), "runtime"),
// Discord integration
new Dependency(new DefaultArtifact("net.dv8tion:JDA:5.2.1"), "runtime")
);
// Create collection request
CollectRequest collectRequest = new CollectRequest();
collectRequest.setRepositories(repositories);
dependencies.forEach(collectRequest::addDependency);
// Resolve dependencies
DependencyResult result = resolveDependencies(system, session, collectRequest);
// Get resolved artifact files
List artifactFiles = getArtifactFiles(result);
// Create and set up the custom ClassLoader
URL[] urls = artifactFiles.stream()
.map(file -> {
try {
return file.toURI().toURL();
} catch (MalformedURLException e) {
LOGGER.warning("Failed to convert file to URL: " + file);
return null;
}
})
.filter(Objects::nonNull)
.toArray(URL[]::new);
URLClassLoader classLoader = new URLClassLoader(urls, DependencyLoader.class.getClassLoader());
Thread.currentThread().setContextClassLoader(classLoader);
// Verify critical dependencies
verifyDependencies(classLoader);
}
private static DependencyResult resolveDependencies(RepositorySystem system,
RepositorySystemSession session,
CollectRequest collectRequest) throws Exception {
CollectResult collectResult = system.collectDependencies(session, collectRequest);
DependencyRequest dependencyRequest = new DependencyRequest(collectResult.getRoot(),
DependencyFilterUtils.classpathFilter("compile", "runtime"));
return system.resolveDependencies(session, dependencyRequest);
}
private static List getArtifactFiles(DependencyResult result) {
PreorderNodeListGenerator nlg = new PreorderNodeListGenerator();
result.getRoot().accept(nlg);
return nlg.getArtifacts(false).stream()
.map(Artifact::getFile)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
private static void verifyDependencies(ClassLoader classLoader) {
try {
// Verify JDA
Class.forName("net.dv8tion.jda.api.hooks.ListenerAdapter", true, classLoader);
LOGGER.info("JDA dependency loaded successfully");
// Verify Spring Boot
Class.forName("org.springframework.boot.SpringApplication", true, classLoader);
LOGGER.info("Spring Boot dependency loaded successfully");
// Add other critical dependency verifications as needed
} catch (ClassNotFoundException e) {
LOGGER.severe("Failed to verify critical dependency: " + e.getMessage());
throw new RuntimeException("Critical dependency verification failed", e);
}
}
}
[/code]
Booter.java
[code]package com.hapangama.sunlicense.boot;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
import org.eclipse.aether.impl.DefaultServiceLocator;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
import org.eclipse.aether.util.listener.ChainedRepositoryListener;
import org.eclipse.aether.util.listener.ChainedTransferListener;
import java.io.File;
// Booter.java
public class Booter {
public static RepositorySystem newRepositorySystem() {
DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class);
locator.addService(TransporterFactory.class, FileTransporterFactory.class);
locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
return locator.getService(RepositorySystem.class);
}
public static DefaultRepositorySystemSession newRepositorySystemSession(RepositorySystem system) {
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
LocalRepository localRepo = new LocalRepository("target/local-repo");
session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
session.setTransferListener(new ChainedTransferListener());
session.setRepositoryListener(new ChainedRepositoryListener());
return session;
}
}
[/code]
Hauptklasse
[code]package com.hapangama.sunlicense;
import com.hapangama.sunlicense.boot.DependencyLoader;
import com.vaadin.flow.component.page.AppShellConfigurator;
import com.vaadin.flow.theme.Theme;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collections;
import java.util.Properties;
@Theme(value = "sun")
@SpringBootApplication(exclude = ErrorMvcAutoConfiguration.class)
public class SunLicenseApplication implements AppShellConfigurator {
public static void main(String[] args) {
try {
// Initialize dependencies before starting Spring
DependencyLoader.initializeDependencies();
// Get the context class loader that has our dependencies
ClassLoader customClassLoader = Thread.currentThread().getContextClassLoader();
// Create Spring application
SpringApplication app = new SpringApplication(SunLicenseApplication.class);
Properties properties = new Properties();
properties.put("spring.main.allow-bean-definition-overriding", "true");
properties.put("spring.main.allow-circular-references", "true");
app.setDefaultProperties(properties);
// Important: Set both resource loader and context class loader
app.setResourceLoader(new DefaultResourceLoader(customClassLoader));
Thread.currentThread().setContextClassLoader(customClassLoader);
ConfigurableApplicationContext context = app.run(args);
if (context != null && context.isActive()) {
System.out.println("Application started successfully");
System.out.println("Active profiles: " + Arrays.toString(context.getEnvironment().getActiveProfiles()));
}
} catch (Exception e) {
System.out.println("Failed to start application");
e.printStackTrace();
System.exit(1);
}
}
}
[/code]
Protokoll der Startkonsole
Java konnte JDA laden (eine der Bibliotheken erfolgreich)
[code]INFO: JDA dependency loaded successfully[/code]
aber es wirft die Klasse aus, die später aus irgendeinem Grund nicht gefunden wurde.
[code]Caused by: java.lang.ClassNotFoundException: net.dv8tion.jda.api.hooks.ListenerAdapter[/code]
https://paste.hapangama.com/egewawovif.properties
Pom.xml
[code]
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
org.springframework.boot
spring-boot-starter-parent
3.3.5
com.hapangama
SunLicense
0.0.1-SNAPSHOT
SunLicense
SunLicense
17
24.5.4
Vaadin Directory
https://maven.vaadin.com/vaadin-addons
false
org.springframework.boot
spring-boot-starter-data-jpa
provided
org.springframework.boot
spring-boot-starter-security
provided
com.vaadin
vaadin-spring-boot-starter
provided
com.h2database
h2
provided
org.projectlombok
lombok
true