Alan-Gomes / mcspring-boot

A Spring boot starter for Bukkit/Spigot/PaperSpigot plugins
MIT License
78 stars 25 forks source link

Feign client issues #12

Closed CC007 closed 5 years ago

CC007 commented 5 years ago

When using the feign client and properly adding the annotations (@EnableFeignClients(basePackages = "com.github.cc007.headsplugin") on the application class and @FeignClient(name="..." , url="...") on the client interfaces)

I get the following exception:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.cloud.openfeign.FeignContext' available
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:343) ~[?:?]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335) ~[?:?]
        at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123) ~[?:?]
        at org.springframework.cloud.openfeign.FeignClientFactoryBean.getTarget(FeignClientFactoryBean.java:243) ~[?:?]
        at org.springframework.cloud.openfeign.FeignClientFactoryBean.getObject(FeignClientFactoryBean.java:235) ~[?:?]
        at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:171) ~[?:?]
        at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101) ~[?:?]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1674) ~[?:?]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1216) ~[?:?]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:257) ~[?:?]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[?:?]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277) ~[?:?]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1467) ~[?:?]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1424) ~[?:?]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1207) ~[?:?]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164) ~[?:?]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593) ~[?:?]

I have added the spring cloud dependency management and openfeign dependency (using the Greenwich.RELEASE version). All fixes that google suggests for the missing FeignContext bean didn't work, so I feel like it could be something in mcspring-boot or spigot that prevents it from working.

Alan-Gomes commented 5 years ago

Hi, can you provide your pom.xml?

CC007 commented 5 years ago

Nvm, im stupid. I only had the HttpClient in my dependencyManagement, not my dependencies. It did however expose another issue where it couldn't find a bean that is definitely in the scanned packages:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.github.cc007.headsplugin.rest.clients.MineSkinClient' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1655) ~[?:?]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1214) ~[?:?]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1168) ~[?:?]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593) ~[?:?]

My Application class looks like this:

@SpringBootApplication(scanBasePackages = {"com.github.cc007.headsplugin"})
public class Application
{}

and I have a FeignConfig class like this:

package com.github.cc007.headsplugin.config;

...

@Configuration
@EnableFeignClients
public class FeignConfig
{}

With the feign client like this:

package com.github.cc007.headsplugin.rest.clients;

...

@Component
@FeignClient(name = "MineSkin", url = "http://api.mineskin.org/")
public interface MineSkinClient
{
    @RequestMapping(method = RequestMethod.GET, value = "/list?filter={searchTerm}")
    SkinListDto getSkins(@PathVariable("searchTerm") String searchTerm);

    @RequestMapping(method = RequestMethod.GET, value = "/id/{id}")
    SkinDetailsDto getSkinDetails(@PathVariable("id") long id);
}
Alan-Gomes commented 5 years ago

The @EnableFeignClients scans the current package (com.github.cc007.headsplugin.config) by default, which is not the same of the client (com.github.cc007.headsplugin.rest.clients), you missed the @EnableFeignClients(basePackages = "com.github.cc007.headsplugin")

CC007 commented 5 years ago

thx. I had that before, but I removed it when trying to fix the issues with http client. thx for your help.

But now im back to the issue I started with. Something causes the autoconfigure from feign to not be automatically included. The bean is defined in FeignAutoConfiguration. I checked, it is in the spring.factories of openfeign

Alan-Gomes commented 5 years ago

Is the feign auto configuration located at META-INF/spring.factories inside the jar file, or somewhere else?

CC007 commented 5 years ago

spring factories seems to only contain your autoconfig...

my pom.xml files look like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.github.cc007</groupId>
        <artifactId>headsplugin-parent</artifactId>
        <version>2.0.0-SNAPSHOT</version>
        <relativePath>../headsplugin-parent</relativePath>
    </parent>

    <artifactId>headsplugin-core</artifactId>

    <packaging>jar</packaging>

    ...

    <dependencies>
        <dependency>
            <groupId>org.bukkit</groupId>
            <artifactId>bukkit</artifactId>
        </dependency>

        <dependency>
            <groupId>dev.alangomes</groupId>
            <artifactId>spigot-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>
    <build>
        ...
    </build>
</project>

With dep management for versions in the parent.

This is the spring.factories from openfeign that doesnt seem to be included into my jar:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration,\
org.springframework.cloud.openfeign.FeignAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignAcceptGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignContentGzipEncodingAutoConfiguration
CC007 commented 5 years ago

Could it be because the spring-boot-maven-plugin isn't added? Since it is a plugin, the jar doesn't have a main method and therefore that plugin doesn't work properly.

Alan-Gomes commented 5 years ago

This seems to be caused by the manual build configured. Since the spring-boot-maven-plugin is not used, the spring.factories is not merged in the final artifact.

Try using the official plugin:

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

And add a empty main method (as required by the spring-boot-maven-plugin) in your plugin class:

public static void main(String[] args) {
}

I will change the documentation to suggest this way.

CC007 commented 5 years ago

Ok, so my hunch was right :D

Alan-Gomes commented 5 years ago

Ok, so my hunch was right :D

Yes, it is! I recommended a manual configuration to make the integration of spring and spigot less "painful", but I think there's no other way rather than using the official maven plugin.

CC007 commented 5 years ago

Yea, it would be a hassle to go through all your dependencies and check if there is any spring.factories file and then add those files to your context.

CC007 commented 5 years ago

When using the plugin after having added the main method, the program does build, but the plugin now breaks, because the resources aren't added anymore.

CC007 commented 5 years ago

This is because the files were moved to BOOT-INF\classes

Alan-Gomes commented 5 years ago

I noticed that now, I'm trying to find a workaround...

CC007 commented 5 years ago

I think finding a way to move the contents of BOOT-INF/classes to the root of the jar and add the lib file to the root as well. then you can use something similar to https://bukkit.org/threads/tutorial-use-external-library-s-with-your-plugin.103781/ to load the libraries

It would of course be nice if you could make a maven plugin that does the file moving for you and processes and edits the onEnable to automatically load the jars :D

CC007 commented 5 years ago

If you get this working, I think it is also not necessary anymore to shade the jar anymore

CC007 commented 5 years ago

Also important to note: since the maven jar plugin, maven shade plugin and the spring boot maven plugin all act on the package goal, it matters in which order these are added to the build section in the pom. Something that you could add to your "known issues" section in your wiki.

Alan-Gomes commented 5 years ago

After some digging, I managed to make the shading works:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.0</version>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring.version}</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.handlers</resource>
                    </transformer>
                    <transformer
                            implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
                        <resource>META-INF/spring.factories</resource>
                    </transformer>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                        <resource>META-INF/spring.schemas</resource>
                    </transformer>
                    <transformer
                            implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                </transformers>
                <shadedArtifactAttached>true</shadedArtifactAttached>
                <shadedClassifierName>shaded</shadedClassifierName>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

I think finding a way to move the contents of BOOT-INF/classes to the root of the jar and add the lib file to the root as well. then you can use something similar to https://bukkit.org/threads/tutorial-use-external-library-s-with-your-plugin.103781/ to load the libraries

It would of course be nice if you could make a maven plugin that does the file moving for you and processes and edits the onEnable to automatically load the jars :D

I don't think that writing code to dynamic load libraries is the right way, I want this project to be a "out of the box" support for spring, adding so much boilerplate code will not help starting new projects. I hope that this maven configuration will work for all cases.

CC007 commented 5 years ago

This does indeed generate the factories file now. In this case, since you're not running a goal in the spring-boot-maven-plugin, that plugin can be removed I think.

Also, with that I get the following error:

java.lang.IllegalStateException: Cannot load configuration class: org.springframework.cloud.bootstrap.BootstrapImportSelectorConfiguration
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:413)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(ConfigurationClassPostProcessor.java:253)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:286)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:130)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:705)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:531)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
        at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:139)
        at org.springframework.cloud.bootstrap.BootstrapApplicationListener.bootstrapServiceContext(BootstrapApplicationListener.java:191)
        at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:105)
        at org.springframework.cloud.bootstrap.BootstrapApplicationListener.onApplicationEvent(BootstrapApplicationListener.java:71)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
        at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:75)
        at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:54)
        at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:347)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:306)
        at com.github.cc007.headsplugin.HeadsPlugin.onEnable(HeadsPlugin.java:32)
        at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:265)
        at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:347)
        at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:410)
        at org.bukkit.craftbukkit.v1_13_R2.CraftServer.enablePlugin(CraftServer.java:436)
        at org.bukkit.craftbukkit.v1_13_R2.CraftServer.enablePlugins(CraftServer.java:350)
        at net.minecraft.server.v1_13_R2.MinecraftServer.l(MinecraftServer.java:580)
        at net.minecraft.server.v1_13_R2.MinecraftServer.a(MinecraftServer.java:542)
        at net.minecraft.server.v1_13_R2.MinecraftServer.a(MinecraftServer.java:420)
        at net.minecraft.server.v1_13_R2.DedicatedServer.init(DedicatedServer.java:294)
        at net.minecraft.server.v1_13_R2.MinecraftServer.run(MinecraftServer.java:698)
        at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.ClassNotFoundException: org.springframework.cloud.bootstrap.BootstrapImportSelectorConfiguration
        at java.net.URLClassLoader$1.run(URLClassLoader.java:372)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:360)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:340)
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:275)
        at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:438)
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(ConfigurationClassPostProcessor.java:400)

I checked and the file IS actually there in the jar under org/springframework/cloud/bootstrap/BootstrapImportSelectorConfiguration.

Alan-Gomes commented 5 years ago

Some starters don't support a custom classloader (due to a bad implementation), a definitive workaround for this is changing the thread class loader (which spring uses by default):

public class TestPlugin extends JavaPlugin {

    private ClassLoader defaultClassLoader;

    @Override
    public void onEnable() {
        defaultClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(getClassLoader());
        // init code
    }

    @Override
    public void onDisable() {
        // disable code
        Thread.currentThread().setContextClassLoader(defaultClassLoader);
    }

}

It should work without any problems, since each plugin has it's own class loader.

CC007 commented 5 years ago

Ok, now I added that, here is the next issue :D

[04:46:55 INFO]: 2019-06-01 04:46:55.464  WARN 11288 --- [  Server thread] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mineSkinApiTestCommand': Unsatisfied dependency expressed through field 'mineSkinCl
ient'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.github.cc007.headsplugin.rest.clients.MineSkinClient': FactoryBean threw exception on object creation; nested exception is org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'feign.client-org.springfr
amework.cloud.openfeign.FeignClientProperties': Could not bind properties to 'FeignClientProperties' : prefix=feign.client, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'feign.client.config' to java.util.Map<java.lang.String, org.springframework.cloud.open
feign.FeignClientProperties$FeignClientConfiguration>

[04:46:55 INFO]: 2019-06-01 04:46:55.474  INFO 11288 --- [  Server thread] ConditionEvaluationReportLoggingListener :

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.

[04:46:55 INFO]: 2019-06-01 04:46:55.479 ERROR 11288 --- [  Server thread] o.s.b.d.LoggingFailureAnalysisReporter   :

***************************
APPLICATION FAILED TO START
***************************

Description:

Failed to bind properties under 'feign.client.config' to java.util.Map<java.lang.String, org.springframework.cloud.openfeign.FeignClientProperties$FeignClientConfiguration>:

    Reason: No converter found capable of converting from type [org.bukkit.configuration.MemorySection] to type [java.util.Map<java.lang.String, org.springframework.cloud.openfeign.FeignClientProperties$FeignClientConfiguration>]

Action:
Update your application's configuration
Alan-Gomes commented 5 years ago

Can you provide your config.yml?

CC007 commented 5 years ago

I found a mapper implementation: convertMapsToSections in YamlConfiguration:72

CC007 commented 5 years ago
# plugin specific config
...

# feign config
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: basic
Alan-Gomes commented 5 years ago

I added a converter from ConfigurationSection to Map by default on 0.18.1, will be available ASAP (https://github.com/Alan-Gomes/mcspring-boot/commit/41b5b7321fdb1782e46055c20bacdf0ac4ce5654#diff-e99133dfd499da62a0f4c9dc230e9eb4R33)

Thanks!

CC007 commented 5 years ago

This seems to be a separate issue regarding config, since without this part in the config, the server starts allright and Feign is working like a charm. I'll add a new issue and consider this one closed.

CC007 commented 5 years ago

Oh, you already fixed it. No need for that issue then. I have another one for you though :D

Djaytan commented 1 year ago

Hello!

Sorry for bringing back to life this issue, but something wrong has been mentioned in this comment which can be misleading in fact:

Some starters don't support a custom classloader (due to a bad implementation), a definitive workaround for this is changing the thread class loader (which spring uses by default):

public class TestPlugin extends JavaPlugin {

    private ClassLoader defaultClassLoader;

    @Override
    public void onEnable() {
        defaultClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(getClassLoader());
        // init code
    }

    @Override
    public void onDisable() {
        // disable code
        Thread.currentThread().setContextClassLoader(defaultClassLoader);
    }

}

It should work without any problems, since each plugin has it's own class loader.

Modifying the context class loader is definitively not the perfect way to go forward with Bukkit. It's right that it seems to be the default first place where the Spring framework take a look at when searching a class loader before loading and resolving any bean. It's mentioned in the [ClassUtils#getDefaultClassLoader()](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/util/ClassUtils.html#getDefaultClassLoader()) method which is typically used by the [DefaultResourceLoader class](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/io/DefaultResourceLoader.html#getClassLoader()) (when looking at the implementation):

    /**
     * Return the ClassLoader to load class path resources with.
     * <p>Will get passed to ClassPathResource's constructor for all
     * ClassPathResource objects created by this resource loader.
     * @see ClassPathResource
     */
    @Override
    @Nullable
    public ClassLoader getClassLoader() {
        return (this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader());
    }

But there is certainly a cleaner way to customize the bean class loader by customizing the ApplicationContext at initialization time before starting to process any bean:

  @Override
  public void onEnable() {
    applicationContext =
        new SpringApplicationBuilder(MyApplication.class)
            .bannerMode(Mode.OFF)
            .initializers(appContext -> appContext.setClassLoader(getClassLoader()))
            .build()
            .run();
  }

Still, I'm not able to provide guarrantee that if it will work for all the Spring Boot starters (e.g. Feign here) since the default behavior can be overridden. You mentioned it typically: Some starters don't support a custom classloader (due to a bad implementation. I would be curious to learn more about your experience on this front.

But anyway, one thing which is wrong is saying that the context class loader is dedicated to a specific plugin. The thread is shared between all the plugins which implies that it's the same for the context class loader. I have made some experimentations on my side and here are my findings:

[21:53:53] [Server thread/INFO]: [TemplateSpringPlugin] [STDOUT] Context classloader: java.net.URLClassLoader@759ebb3d [21:53:53] [Server thread/INFO]: [TemplateSpringPlugin] [STDOUT] System classloader: jdk.internal.loader.ClassLoaders$AppClassLoader@2a139a55 [21:53:53] [Server thread/INFO]: [TemplateSpringPlugin] [STDOUT] Plugin's classloader: PaperPluginClassLoader{libraryLoader=java.net.URLClassLoader@5fe36d7e, seenIllegalAccess=[], loadedJavaPlugin=TemplateSpringPlugin v0.1.0-SNAPSHOT}

As you can see, the PaperMC class loader dedicated to the plugin is not the same than the context class loader one. So, it's better to keet context class loader untouched in order to avoid potential conflicts with other plugins (especially when they are relying on Spring Boot while trying to alter all together the context class loader).

But anyway thanks a lot for this message since it gave me an hint for the solution to implement in order to make Spring Boot working with Bukkit! :)

CC007 commented 1 year ago

I've moved to using Dagger2 about 2 years ago, but I hope your comments will help anyone else with similar issues.