WebSphere Application Server & Liberty

WebSphere Application Server & Liberty

Join this online group to communicate across IBM product users and experts by sharing advice and best practices with peers and staying up to date regarding product enhancements.

 View Only

Injecting Spring Beans to JAX-RS resource running on Websphere Application Server 9 , JDK 1.8

  • 1.  Injecting Spring Beans to JAX-RS resource running on Websphere Application Server 9 , JDK 1.8

    Posted Thu September 21, 2023 12:47 PM
    Edited by Sibi Vaithara Fri September 22, 2023 09:33 AM

    Hi all

    I have a JAX-RS application running on Websphere Application Server 9.0.5 (Java 1.8). I would like to make use of spring for the backing business classes and hence was attempting to inject Spring (Core – version 5.3.27) beans into the JAX-RS application

    I understand that theIBM JAX-RS  implementation relies on the com.ibm.websphere.jaxrs.server.IBMRestServlet for its initialization. Following post at http://www.javavillage.in/spring-ioc-on-servlets.php ,  I tried  creating a custom servlet extending the IBMRestServlet and adding Spring autowiring to its init method

    package org.my.example;
    
    
    
    
    import org.springframework.beans.factory.annotation.Configurable;
    import org.springframework.web.context.support.SpringBeanAutowiringSupport;
    
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import com.ibm.websphere.jaxrs.server.IBMRestServlet;
    @Configurable
    public class MyHttpServlet extends IBMRestServlet {
    
        @Override
        public void init(ServletConfig config) throws ServletException {
    
            super.init(config);
            SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    
        }
    
    }

    This required, the IBM Websphere jars ( From "Websphere installation folder/Dev")  to be added to my POM along with spring-web, aspectjweaver, spring-aspects , spring-context-support, spring-context etc as mentioned in link

    <dependency>
                    <groupId>com.ibm.websphere</groupId>
                    <artifactId>j2ee</artifactId>
                    <version>1.0.0</version>
                    <scope>system</scope>
                    <systemPath>C:/IBM/WebSphere/AppServer/dev/JavaEE/j2ee.jar</systemPath>
    </dependency>
    
    
    <dependency>
                    <groupId>com.ibm.websphere.appserver.api</groupId>
                    <artifactId>com.ibm.websphere.appserver.api.jaxrs</artifactId>
                    <version>1.0.80</version>
    </dependency>
    <dependency>
                    <groupId>org.apache.wink</groupId>
                    <artifactId>wink-server</artifactId>
                    <version>1.4</version>
    </dependency>
    <dependency>
                    <groupId>com.ibm.websphere.appserver</groupId>
                    <artifactId>was_public</artifactId>
                    <version>9.0.0</version>
    </dependency>

    Following was added to web.xml

    <listener>
                    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
                    <param-name>contextConfigLocation</param-name>
                    <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    
    
    <servlet>
           <servlet-name>JAXRSConfiguration</servlet-name>
           <servlet-class> org.my.example.MyHttpServlet </servlet-class>
           <init-param>
               <param-name>javax.ws.rs.Application</param-name>
               <param-value> org.my.example.RestConfig </param-value>
           </init-param>
           <load-on-startup>1</load-on-startup>

    Note: org.my.example.RestConfig is my class that extends javax.ws.rs.core.Application

    Unfortunately the build fails with following error which I am unable to resolve with any dependencies

    java: cannot access com.ibm.ws.ras.instrument.annotation.InjectedFFDC
    
      class file for com.ibm.ws.ras.instrument.annotation.InjectedFFDC not found

    As an alternate approach, I tried injecting spring to Rest Resource

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.stereotype.Component;
    
    @Component
    
    @Path("/mypath")
    
    public class MyResource {
      
                    @Autowired
                    TestClass testClass;
    
    private static final Logger LOGGER = LoggerFactory.getLogger(MyResource.class);
    
                    @POST
    
                    @Path("/subpath")
    
                    @Consumes(MediaType.APPLICATION_JSON)
    
                    @Produces(MediaType.APPLICATION_JSON)
    
                    public Response getMyResourceList(MyRequest request) {
    
                                    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
    
                                    TestClass tClass = applicationContext.getBean(TestClass.class);
    
                                    if(tClass!=null){
    
                                                    LOGGER.debug("TestClass not null");
    
                                    }
    
                                    LOGGER.debug("tClass-------->-"+tClass.testMethod());
    
                                    LOGGER.debug("testClass------>"+testClass.testMethod());
    
                    }

    The Web.xml was modified as below

    <listener>
                    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
                    <param-name>contextConfigLocation</param-name>
                    <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    
    <listener>
                    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
                    <param-name>contextConfigLocation</param-name>
                    <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    With servlet still pointing to IBMRestServlet as in original JAX-RS application

    <servlet>
           <servlet-name>JAXRSConfiguration</servlet-name>
           <servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
           <init-param>
               <param-name>javax.ws.rs.Application</param-name>
               <param-value> org.my.example.RestConfig</param-value>
           </init-param>
           <load-on-startup>1</load-on-startup>
       </servlet>

    My Bean looks as follows

    @Component
    public class TestService {
        public String testMethod(){
            return "spring class";
        }
    }

    Here I am successfully able to get the bean instance but since the Application context is created per resource, I do not think it's a good way.

    Request your help and suggestions

    Thanks in Advance

    ------------------------------
    Sibi Vaithara
    ------------------------------