Move from Spring 4.xxx to Spring 5 keeping EJB and web modules
Asked Answered
K

1

1

Hi All

Server : Websphere 9.

Application works fine with Spring 4. We want move to Spring 5.

We ran into issues with DI (Dependency Injection).

We have EJB module (with Message Driven Beans) and Web Module in Spring 4.

I already know that they recommend to move to Spring fully or use some Spring CDI-Bridge. https://jira.spring.io/browse/SPR-15154

But We would like to avoid to change to much structure of our project ( regression test, small amount of time etc...).

So is there any way to keep structure and move to Spring 5.

web.xml

<web-app id="WebAppId" version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>AppWebModule</display-name>

<context-param>
    <param-name>parentContextKey</param-name>
    <param-value>ear.context</param-value>
</context-param>

<context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<!-- Start Spring MVC -->
<servlet>
    <servlet-name>Spring MVC Dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>com.organization.services.config.ServicesWebAppConfig</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

... rest of file

ServicesAppConfig EJB Module.

@Configuration
@EnableAspectJAutoProxy
@EnableTransactionManagement(proxyTargetClass = true)
@ComponentScan({ "com.organization.services.resources", "com.organizatio.services.jsf", "com.organizatio.services.snoop", "com.organizatio.services.version" })
public class ServicesWebAppConfig extends WebMvcConfigurationSupport {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        super.addDefaultHttpMessageConverters(converters); // Have to call this explicitly to register Default Message Converters.
        converters.add(new MappingJackson2HttpMessageConverter());
    }
}

beanRefContext. xml

   "bean id='ear.context' 
   class='org.spring.....AnnotationConfigApplicationContext
     constructor-arg
        list         
            type="java.lang.Class">com.organization.services.config.ServicesAppConfig
        list
     constructor-arg

Error:

ERROR

   [6/18/18 12:30:57:980 CEST] 0000012c SystemOut     O [2018-06-18 12:30:57,976] 
   [WebContainer : 5] [ERROR] [] 
   [org.springframework.web.servlet.DispatcherServlet:initServletBean:503]: 
   Context initialization failed
   org.springframework.beans.factory.UnsatisfiedDependencyException: Error 
   creating bean with name 'adminResource1': Unsatisfied dependency expressed 
   through field 'adminService'; nested exception is 
   org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying 
   bean of type 'com.organiazation.services.business.admin.xxxx.AdminService' 
   available: expected at least 1 bean which qualifies as autowire candidate. 
   Dependency annotations: {@javax.inject.Inject()}
Kashgar answered 18/6, 2018 at 10:47 Comment(2)
I would change my mind about keeping EJBs and not changing the structure of your project. EJBs are a 1999 technology. No reason to keep them.Oersted
hmm ok that is valid pointKashgar
L
1

The previous solution doesn't work anymore with Spring 5. SpringBeanAutowiringInterceptor support has been removed.

So here my quick solution :

I inject manually the Spring bean inside my EJB (MDB here) with a setter. And my bean "injected" is a static one (it's set once and for good) during the initialization phase of Spring.

Here is my EJB :

import javax.ejb.*;
import javax.jms.*;

@TransactionManagement(value = TransactionManagementType.CONTAINER)
@TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED)
@MessageDriven(
        name = "messageListenerEJBInstance",
        activationConfig = {
                // configurations ...
        })
public class MessageListenerEJB implements MessageListener {
    // ...
    private static SpringBean springBean;

    @Override
    public void onMessage(Message message) {
        // ...
        
        springBean.someMethod();
        
        // ...
    }

    // ...

    // Setter -> to initialize my bean from the outside
    public void setSpringBean(SpringBean springBean) {
        MessageListenerEJB.springBean = springBean;
    }
}

And here is how it's initialized :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:jee="http://www.springframework.org/schema/jee"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">

    // ...

    <bean id="bean" class="your.package.SpringBean"/>
    <bean id="messageListenerEJBInstance" class="your.package.MessageListenerEJB">
        <property name="springBean" ref="bean"/>
    </bean>
    
    // ...
</beans>
Lippi answered 27/9, 2021 at 7:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.