Not able to Refer to different xml using Spring 5.2.x
Asked Answered
F

0

0

With Spring 4.3.5, we have been using an application architecture where we initialize some of the beans at a go and then use the beans as "Reference" for other beans.

Something like this

<bean id="handleUncheckedEndpointExceptionAdvice" 
    class="com.gehcit.cp.ws.infrastructure.aop.advices.HandleUncheckedEndpointExceptionAdvice">
    <constructor-arg ref="exceptionFactory"/>
    <property name="exceptionSenderService" ref="exceptionSenderService" />
</bean>

But once we upgraded our library to Spring 5.2.x, we started getting the below exception at Jboss 7.3.1 startup:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'handleUncheckedEndpointExceptionAdvice' defined in ServletContext resource [/WEB-INF/context-web.xml]: Cannot resolve reference to bean 'exceptionSenderService' while setting bean property 'exceptionSenderService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'exceptionSenderService' available

What all I did: Enabled TRACE logging and found this - 2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.annotation.InjectionMetadata] (ServerService Thread Pool -- 65) Processing injected element of bean 'exceptionSenderService': AutowiredFieldElement for private com.gehcit.cp.serviceability.service.ExceptionSenderService com.gehcit.cp.cem.aplix.jms.service.Impl.AplixPublisherQueueServiceImpl.exceptionSender 2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.support.DefaultListableBeanFactory] (ServerService Thread Pool -- 65) Returning cached instance of singleton bean 'exceptionSenderServiceImpl' 2022-03-05 13:09:39,927 TRACE [org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor] (ServerService Thread Pool -- 65) Autowiring by type from bean name 'exceptionSenderService' to bean named 'exceptionSenderServiceImpl' Now the bean is getting initialized but when the reference is being searched, being searched from the Spring cache, we get nothing.

But then we tried shifting the bean initialization from a different xml to the same xml where the bean is being referred and that worked. So we concluded that somehow the cross XML configurations are not working.

Bean being referred from context-web.xml

<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:cxf="http://cxf.apache.org/core" 
    xmlns:jaxws="http://cxf.apache.org/jaxws" 
    xmlns:jaxrs="http://cxf.apache.org/jaxrs" 
    xmlns:task="http://www.springframework.org/schema/task" 
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:oauth2="http://www.springframework.org/schema/security/oauth2" 
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
        http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
        http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
        http://www.springframework.org/schema/security 
            https://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/security/oauth2 
            https://www.springframework.org/schema/security/spring-security-oauth2.xsd">

    <task:annotation-driven/>
    <!-- Define placeholder for application properties -->
    <bean 
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>/WEB-INF/web.properties</value>
                <value>classpath:application.properties</value>
            </list>
        </property>
    </bean>
    <!-- Load CXF modules from cxf.jar -->
    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
    <import resource="context-cem-web.xml"/>
    <!-- define an auto-proxy generator for our advisors -->
    <bean 
        class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        <property name="proxyTargetClass" value="false"/>
    </bean>
    <!-- id generator for exceptions -->
    <bean id="exceptionIdGenerator" 
        class="com.gehcit.cp.ws.infrastructure.exception.HostTimeExceptionIdGenerator">
        <property name="prefix" value="CEN"/>
    </bean>
    <!-- system fault factory -->
    <bean id="systemFaultFactory" 
        class="com.gehcit.cp.ws.infrastructure.exception.StandardSystemFaultFactory">
        <property name="exceptionIdGenerator" ref="exceptionIdGenerator"/>
        <property name="appendExceptionIdToErrorMessage" value="true"/>
    </bean>
    <bean id="defaultParamConverterProvider"
        class="org.apache.cxf.jaxrs.ext.search.DefaultParamConverterProvider"/>
    <!-- factory for mapping runtime exceptions to wire faults -->
    <bean id="exceptionFactory" 
        class="com.gehcit.cp.ws.infrastructure.exception.ExceptionMapperExceptionFactory">
        <property name="exceptionMappers">
            <list>
                <bean 
                    class="com.gehcit.cp.ws.infrastructure.exception.IllegalArgumentFaultFromIllegalArgumentExceptionMapper"/>
                <bean 
                    class="com.gehcit.cp.ws.infrastructure.exception.SecurityFaultFromCPSecurityExceptionMapper"/>
                <bean 
                    class="com.gehcit.cp.ws.infrastructure.exception.ApplicationFaultFromApplicationErrorMapper"/>
                <bean 
                    class="com.gehcit.cp.ws.infrastructure.exception.SystemFaultFromRuntimeExceptionMapper">
                    <constructor-arg ref="systemFaultFactory"/>
                </bean>
            </list>
        </property>
    </bean>
    <!-- aspect for handling unchecked endpoint exceptions -->
    <bean id="handleUncheckedEndpointExceptionAdvice" 
        class="com.gehcit.cp.ws.infrastructure.aop.advices.HandleUncheckedEndpointExceptionAdvice">
        <constructor-arg ref="exceptionFactory"/>
        <property name="exceptionSenderService" ref="exceptionSenderService" />
    </bean>
    <bean id="handleUncheckedEndpointExceptionPointcut" 
        class="org.springframework.aop.support.annotation.AnnotationMatchingPointcut">
        <constructor-arg type="java.lang.Class">
            <null/>
        </constructor-arg>
        <constructor-arg type="java.lang.Class" 
            value="com.gehcit.cp.ws.infrastructure.aop.annotations.HandleUncheckedEndpointException"/>
    </bean>
    <bean id="handleUncheckedEndpointExceptionAdvisor" 
        class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="advice" ref="handleUncheckedEndpointExceptionAdvice"/>
        <property name="pointcut" 
            ref="handleUncheckedEndpointExceptionPointcut"/>
    </bean>

The bean is being initialized in context-applix.xml

    <beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:amq="http://activemq.apache.org/schema/core" 
    xmlns:jms="http://www.springframework.org/schema/jms" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xsi:schemaLocation="
                  http://www.springframework.org/schema/beans 
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://activemq.apache.org/schema/core
                  http://activemq.apache.org/schema/core/activemq-core.xsd
                  http://www.springframework.org/schema/beans 
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/jms 
                  http://www.springframework.org/schema/jms/spring-jms.xsd">
    <!-- Activemq connection factory start -->
    <bean id ="connectionAmqFactory" 
        class="org.apache.activemq.ActiveMQConnectionFactory">
        <property name="brokerURL" 
            value="vm://broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix" 
            />
    </bean>
    <!-- A POJO that implements the JMS message listener -->
    <bean id="aplixSubscriberQueueService" 
        class="com.gehcit.cp.cem.aplix.jms.listener.AplixSubscriberQueueListener" 
        />
    <bean id="exceptionSenderService" 
        class="com.gehcit.cp.cem.aplix.jms.service.Impl.AplixPublisherQueueServiceImpl" 
        />
    <!-- A destination in ActiveMQ -->
    <!--amq:topic id="destination" physicalName="APLIX.ERRORINFO" /-->
    <!-- A destination in ActiveMQ -->
    <amq:queue id="destination" physicalName="APLIX.ERRORINFO" />
    <!-- A destination in ActiveMQ end-->
    <!-- A cached connection to wrap the ActiveMQ connection -->
    <bean id="cachedAmqConnectionFactory" 
        class="org.springframework.jms.connection.CachingConnectionFactory" 
        p:targetConnectionFactory-ref="connectionAmqFactory" 
        p:sessionCacheSize="10" />
    <!-- Adding JMS transaction Manager -->
    
    <bean id="TransactionManager" 
        class="org.springframework.jms.connection.JmsTransactionManager">
        <property name="connectionFactory" ref="cachedAmqConnectionFactory"/>
    </bean>
    <!-- Adding JMS transaction Manager -End -->
    <!-- A JmsTemplate instance that uses the connection and destination -->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate" 
        p:connectionFactory-ref="cachedAmqConnectionFactory" 
        p:defaultDestination-ref="destination" />
    <!-- A JmsTemplate instance that uses the connection and destination end -->
    <!--Cofiguring JMS container and listener-->
    <jms:listener-container container-type="default" 
        connection-factory="cachedAmqConnectionFactory" destination-type="queue" >
        <jms:listener destination="APLIX.ERRORINFO" 
            ref="aplixSubscriberQueueService" method="onMessage" />
    </jms:listener-container>
    <!--Cofiguring JMS container and listener end-->
    <!-- The Spring message listener container configuration -->
    <amq:broker start="true" persistent="false" 
        brokerName="broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix" 
        deleteAllMessagesOnStartup="false" >
        <amq:managementContext>
            <amq:managementContext createConnector="false"/>
        </amq:managementContext>
        <amq:systemUsage>
            <amq:systemUsage>
                <amq:memoryUsage>
                    <amq:memoryUsage limit="512 mb"/>
                </amq:memoryUsage>
                <amq:tempUsage>
                    <amq:tempUsage limit="2 gb"/>
                </amq:tempUsage>
            </amq:systemUsage>
        </amq:systemUsage>      
        <amq:transportConnectors>
            <amq:transportConnector name="vm" 
                uri="vm://broker#{T(com.gehcit.cp.ws.ServiceProperties).instance().getProperty(T(com.gehcit.cp.Constants).CENTRICITY_DEPLOY_ID)}-applix"/>
        </amq:transportConnectors>
    </amq:broker>
</beans>

Can someone help me find a way to refer beans from other xml files in Spring 5.2.x. Note: We have changed the classloading part with Spring 5.2.

Added this to the web.xml

    <listener-class>com.gehcit.cp.ws.infrastructure.security.BeanFactoryContextLoaderListener</listener-class>
</listener>
<!-- <context-param>
    <param-name>locatorFactorySelector</param-name>
    <param-value>/beanRefFactory.xml</param-value>
</context-param>  -->

BeanFactoryContextLoaderListener.java

package com.gehcit.cp.ws.infrastructure.security;
import javax.servlet.ServletContext;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.ContextLoaderListener;
public class BeanFactoryContextLoaderListener extends ContextLoaderListener {
private static Logger log = Logger.getLogger(BeanFactoryContextLoaderListener.class)     
    @Override
        protected ApplicationContext loadParentContext(ServletContext servletContext) { 
         log.info("Entered loadParentContext");    
         ApplicationContext ctx = new ClassPathXmlApplicationContext("beanRefFactory.xml");
         log.info("Exit loadParentContext" + ctx.toString());
         return ctx;
        }
}

This has something to do with ApplicationContext which I am unable to resolve.

Fancywork answered 5/3, 2022 at 19:36 Comment(4)
The stuff that uses the locatorFactorySelector has been removed and your BeanFactoryContextLoaderListener doesn't really replace or fix that. Just load the beanRefFactory.xml in your root application context (through an import).Tews
@M.Deinum Yes, we also suspect the same. Do you have a way to replace locatorFactorySelector is an adequate way. Becasue Spring 5.0 has made the default implementation as null and we need to override it.Fancywork
Have you actually read my comment? Just load the file as part of your regular context.Tews
I tried importing it and it failed. Because it is getting loaded initially but it not available during the whole runtime. Can you please demonstrate with an example if possible. @M.DeinumFancywork

© 2022 - 2024 — McMap. All rights reserved.