0

I am still new to java and spring and I still have some troubles with some context related topics. I am trying to have my context config files loaded from property file. I wanted to upgrade my spring 3 application to spring 4. Below configuration was working fine previously but now I get error:

INFO  [localhost-startStop-1] [CustomServletListener] Context Propery: :classpath:applicationContext.xml
ERROR [localhost-startStop-1] [ContextLoader] Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [applicationContext.xml]; nested exception is java.io.FileNotFoundException: class path resource [applicationContext.xml] cannot be opened because it does not exist

Configuration files:

web.xml

<?xml version="1.0" encoding="iso-8859-1"?>

<web-app id="myweb" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>myweb</display-name>

    <welcome-file-list>
        <welcome-file>/</welcome-file>
    </welcome-file-list>

    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>

    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>\/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>

    <filter>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>hiddenHttpMethodFilter</filter-name>
        <url-pattern>\/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>\/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ERROR</dispatcher>
    </filter-mapping>


    <context-param>
        <param-name>defaultHtmlEscape</param-name>
        <param-value>true</param-value>
    </context-param>

    <listener>
      <listener-class>
         com.mypackage.web.servlets.CustomServletListener
      </listener-class>
   </listener>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

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

    <servlet>
        <servlet-name>myServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>myServlet</servlet-name>
        <url-pattern>/</url-pattern>

    </servlet-mapping>

</web-app> 

CustomServletListener.java

 @WebListener
 @EnableWebSecurity
 @EnableGlobalMethodSecurity
 public class CustomServletListener implements ServletContextListener
 {

    Logger LOG = Logger.getLogger(CustomServletListener.class);

        @Override
        public void contextInitialized(ServletContextEvent event) {
            ServletContext servletContext = event.getServletContext();
            Properties  props = new Properties();
            try
            {
              File files = new File(System.getProperty("CONFIG_DIR")+"/servlet.properties");
               props.load(new FileInputStream(files));
            }
            catch (IOException e)
            {
                LOG.error("Error while loading property: " + e.getMessage(),e);
            }
            boolean flag = servletContext.setInitParameter("contextConfigLocation",  props.getProperty("security.configuration"));
            LOG.info("Flag: " + flag);
            LOG.info("Context Propery: :" + servletContext.getInitParameter("contextConfigLocation"));
        }

        @Override
        public void contextDestroyed(ServletContextEvent event) {
            // Empty.
        }



 }

servlet.properties

security.configuration = WEB-INF/spring-security.xml WEB-INF/myweb-web-spring.xml WEB-INF/myServlet-servlet.xml

What I found out is that applicationContext.xml is assigned to contextConfigLocation parameter before my listener runs. Do I understand it correctly that since spring 4 dispatcherServlet assigns now default value of contextConfigLocation if it is not defined? Can you give me any ideas how I can achieve this without moving whole configuration to java class ?

Leon230
  • 1
  • 2
  • 1
    Your understanding is incorrect. The `DispatcherServlet` does no such thing. The culprit here is the `ContextLoaderListener` (check the stacktrace). My guess is that your configuration isn't found and the property isn't set. Also if it would work your application would be loaded twice, the `DispatcherServlet` automatically loads the `WEB-INF/myServlet-servlet.xml` by design. So you are basically duplicating every bean in there (using up more resources etc.). – M. Deinum Jul 23 '18 at 08:21
  • @M. Deinum, Thank you for your answer. What do you mean by 'put your listener in the web.xml' ? I already have it defined right before ContextLoaderListener. – Leon230 Jul 23 '18 at 08:27
  • I noticed that afterwards (I was put off due to the `@WebListener` annotation, I would suggest removing that one) as well as the `@Enable*` annotations as those don't do anything. As mentioned in my latest comment I suspect your file isn't getting loaded, resulting in the defaults being used). – M. Deinum Jul 23 '18 at 08:27
  • I tried to remove it but it didn't help. The file is being loaded because when I debug the application it comes through it. Method setInitParameter will set the parameter only if the parameter does not exist already (there is a method parameters.putIfAbsent() inside ApplicationContext class). – Leon230 Jul 23 '18 at 17:16
  • What has `setInitParameter` from the `ServletContext` to do with the `ApplicationContext`. There is no relation between the 2. I wonder did you really **only** upgraded Spring but not another library or maybe the Servlet container you are using? – M. Deinum Jul 23 '18 at 17:45

0 Answers0