I have an application in java 21 that is a minecraft spigot plugin. I use spring framework 6.1.10. These are my dependencies:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>6.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.1.10</version>
</dependency>
That is my plugin main class:
package xyz.abc;
import org.mineacademy.fo.Common;
import org.mineacademy.fo.plugin.SimplePlugin;
import org.mineacademy.fo.remain.Remain;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import xyz.abc.commands.CommandTest;
public class SparkCore extends SimplePlugin {
@Override
protected void onPluginStart() {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
Common.log("Available beans:");
for (String beanName : applicationContext.getBeanDefinitionNames()) {
Common.log(beanName);
}
Remain.registerCommand(applicationContext.getBean(CommandTest.class));
}
}
This is my Spring config:
package xyz.abc;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "xyz.abc")
public class SpringConfig {
@Bean
Test test() {
return new Test("Test");
}
}
And this is CommandTest annotated with @Component
package xyz.abc.commands;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.mineacademy.fo.command.SimpleCommand;
import org.mineacademy.fo.menu.model.ItemCreator;
import org.mineacademy.fo.remain.CompMaterial;
import org.springframework.stereotype.Component;
import xyz.abc.Test;
@Component
public final class CommandTest extends SimpleCommand {
private static final ItemStack wing = ItemCreator.of(CompMaterial.DIAMOND)
.modelData(2).make();
public CommandTest(Test test) {
super("test|test2");
System.out.println(test.name());
}
@Override
protected void onCommand() {
System.out.println(12);
checkConsole();
Player player = getPlayer();
}
}
As you could see onPluginLoad print all available beans and this is result:
[22:16:42 INFO]: Available beans:
[22:16:42 INFO]: org.springframework.context.annotation.internalConfigurationAnnotationProcessor
[22:16:42 INFO]: org.springframework.context.annotation.internalAutowiredAnnotationProcessor
[22:16:42 INFO]: org.springframework.context.annotation.internalCommonAnnotationProcessor
[22:16:42 INFO]: org.springframework.context.annotation.internalPersistenceAnnotationProcessor
[22:16:42 INFO]: org.springframework.context.event.internalEventListenerProcessor
[22:16:42 INFO]: org.springframework.context.event.internalEventListenerFactory
[22:16:42 INFO]: springConfig
[22:16:42 INFO]: test
But then I get an error:
[22:31:37 INFO]: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xyz.abc.commands.CommandTest' available
As you can see bean named "test" has been initialized by @Bean annotation in configuration but class CommandTest annoteted with @Component has not.
I don't know what am I supposed to do with that.
Here is the answer: Spring @ComponentScan does not scan
To Summarize, I've just added Thread.currentThread().setContextClassLoader(getClassLoader());
In my onPluginStart method.