MinnDevelopment/discord-webhooks

On 0.4.1 WebhookClient cannot be used as a bean in Spring Boot

schnapster opened this issue · 4 comments

From the 0.4.1 update on, the WebhookClient cannot be used as a bean anymore in a Spring Boot application because it uses parameters of types of optional dependencies (other discord api libs) that are usually not included in the runtime classpath, so some Spring bean introspection fails.

I can write myself a wrapper fine, so it can be worked around easily, just thought you might want to know.

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'botStatusWebhookClient' defined in class path resource [space/npstr/aki/config/WebhookConfiguration.class]: Post-processing of merged bean definition failed; nested exception is java.lang.IllegalStateException: Failed to introspect Class [club.minnced.discord.webhook.WebhookClient] from ClassLoader [org.springframework.boot.loader.LaunchedURLClassLoader@4f2fe9c1]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:571) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$249/000000001102D280.getObject(Unknown Source) ~[na:na]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory$2.resolveCandidate(DefaultListableBeanFactory.java:1765) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1307) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.createOptionalDependency(DefaultListableBeanFactory.java:1768) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1214) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:884) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	... 42 common frames omitted
Caused by: java.lang.IllegalStateException: Failed to introspect Class [club.minnced.discord.webhook.WebhookClient] from ClassLoader [org.springframework.boot.loader.LaunchedURLClassLoader@4f2fe9c1]
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:481) ~[spring-core-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.util.ReflectionUtils.doWithLocalMethods(ReflectionUtils.java:321) ~[spring-core-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.buildLifecycleMetadata(InitDestroyAnnotationBeanPostProcessor.java:232) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.findLifecycleMetadata(InitDestroyAnnotationBeanPostProcessor.java:210) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(InitDestroyAnnotationBeanPostProcessor.java:149) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition(CommonAnnotationBeanPostProcessor.java:294) ~[spring-context-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyMergedBeanDefinitionPostProcessors(AbstractAutowireCapableBeanFactory.java:1093) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:568) ~[spring-beans-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	... 55 common frames omitted
Caused by: java.lang.NoClassDefFoundError: discord4j.core.object.entity.Webhook
	at java.base/java.lang.Class.getDeclaredMethodsImpl(Native Method) ~[na:na]
	at java.base/java.lang.Class.getDeclaredMethods(Class.java:1129) ~[na:na]
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463) ~[spring-core-5.2.8.RELEASE.jar!/:5.2.8.RELEASE]
	... 62 common frames omitted
Caused by: java.lang.ClassNotFoundException: discord4j.core.object.entity.Webhook
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:605) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClassHelper(ClassLoader.java:1180) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1095) ~[na:na]
	at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:151) ~[aki.jar:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:1078) ~[na:na]
	... 65 common frames omitted

Why does it try to load classes that are unused? This seems like a bug in spring boot or your usage of it.

Spring's reflection stuff doesn't handle it well indeed. Here's a minimal example without Spring:

public static void main(String[] args) {
    Method[] declaredMethods = WebhookClient.class.getDeclaredMethods();
}

I've made a branch to test out if an alternative implementation could work: b28c021

Can you test if this works when using WebhookClient or JDAWebhookClient as beans?

Works like a charm.