2

I'm trying migrate my spring 4 code to spring 5 (specifically latest -> 5.3.16), and most of it seems to be ok, but am having a

No default constructor found; nested exception is java.lang.NoSuchMethodException: com.acme.AcmeEventListenerFactory.<init>()

error, when trying to initialize a bean like this:

@Configuration
@Import({ EventForwardingActor.class, AcmeTopicPublisher.class, AcmeEventListenerFactory.class })
public class AcmeSpringBridgeConfiguration {
}

where, AcmeEventListenerFactory has one constructor like

    public class AcmeEventListenerFactory implements EventListenerFactory, Ordered {

        private static final Logger LOGGER = LoggerFactory.getLogger(AcmeEventListenerFactory.class);
        private int m_listenerFactoryOrder = 50;
        private final AcmeTopicPublisher m_publisher;
    
        public AcmeEventListenerFactory(AcmeTopicPublisher publisher) {
            m_publisher = publisher;
        }

The parameter should of course be the bean represented by the 2nd import (AcmeTopicPublisher)

Using

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AcmeSpringBridgeConfiguration.class)
public @interface EnableAcmeListener {
}

As this worked in spring4 i'm assuming i missed the migration doc that talked about this change. Could someone explain what i need to do here?

(Full Stack trace below)

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.acme.framework.receive.acme.AcmeEventListenerFactory': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.acme.framework.receive.acme.AcmeEventListenerFactory]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.acme.framework.receive.acme.AcmeEventListenerFactory.<init>()
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1232)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:671)
    at org.springframework.context.event.EventListenerMethodProcessor.postProcessBeanFactory(EventListenerMethodProcessor.java:113)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:325)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:198)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
    at com.acme.framework.receive.acme.AcmeEventListenerFactoryAcceptanceTest.initSpringWithListener-AcmeEventListenerFactoryAcceptanceTest.java:250)

For completeness here is the other classes

    @Component(EventForwardingActor.BEAN_NAME)
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.NO)
public class EventForwardingActor extends UntypedActorWithMetrics {
    static final String BEAN_NAME = "declarativeEventsEventForwardingActor";

    @Autowired
    private ApplicationEventPublisher m_publisher;
    private final AcmeTopic m_topic;

    public EventForwardingActor(AcmeTopic topic) {
        m_topic = topic;
    }

    ....
    }

    public class AcmeTopicPublisher {

    private final Map<AcmeTopic, ActorRef> m_topicActors = new HashMap<>();
    private final SpringActorFactory m_factory;

    public AcmeTopicPublisher(SpringActorFactory factory) {
        m_factory = factory;
    }

    ....
    }

MeBigFatGuy
  • 28,272
  • 7
  • 61
  • 66
  • 1
    Can you show the annotation on AcmeEventListenerFactory? Also you are migrating to which Spring version exactly? In the migration guide there is a warning when upgrading to version 5.2 for example related with core annotation algorithm. – pringi Feb 21 '22 at 13:03
  • there are no annotations on AcmeEventListenerFactory. And i am upgrading to the latest so 5.3.16 – MeBigFatGuy Feb 21 '22 at 14:27
  • 1
    Your other classes that are used in Import do they have the default constructor or any annotation? I've checked my code that does a similar thing, and all @Import classes have the default constructor (no arg) or have an @Configuration" annotation. Can you try to add a "@Configuration" to your AcmeEventListenerFactory class? – pringi Feb 21 '22 at 15:01
  • 1
    can you post the full stacktrace ? – Ken Chan Feb 21 '22 at 18:46
  • 1
    Do you try to add the default constructor into AcmeEventListenerFactory class? – Dmitrii B Feb 24 '22 at 20:15
  • yes and if i do, it gets called. of course this has no value, as i need the AcmeTopicPublisher injected – MeBigFatGuy Feb 25 '22 at 19:20
  • I think your problem is not the same, but it should in any way be closely related to [this Github issue](https://github.com/spring-projects/spring-framework/issues/22409). Please, instead of directly importing your beans with the `@Import` annotation, try defining `EventForwardingActor`, `AcmeTopicPublisher` and `AcmeEventListenerFactory` as `@Bean`s in `AcmeSpringBridgeConfiguration` , and keep using `@EnableAcmeListener` to register your components. Please, could you try? I think it could work properly. – jccampanero Feb 26 '22 at 22:57
  • Thanks! please add this as a real answer so that i can give you the bounty. it seems to have fixed the issue. While i still have issues around these classes and spring, the immediate problem seems fixed. – MeBigFatGuy Feb 28 '22 at 02:55
  • @MeBigFatGuy This isn't difficult to solve, are you using any DB at the backend? I am not able to recreate this problem, can you share more code or link the complete code if it is available for the public, I wish to find the root cause. – VIAGC Feb 28 '22 at 07:34
  • can you give us github source code which scoped (pom file, issue class source code) to reproduce this issue? thanks – Lam Le Feb 28 '22 at 08:48
  • sorry, it's proprietary code that i am not the owner of. Now the classes are initialized ok, but spring never calls the event syncs. – MeBigFatGuy Feb 28 '22 at 14:53

0 Answers0