Properties file not getting loaded

10,240

You have <context:component-scan base-package="com.onmobile" /> in the carpool-application-context.xml which is imported from carpool-application-context1.xml so that forces your controller to be created in the root web app context, because "com.onmobile" includes "com.onmobile.carpool.controller", and there is no property-placeholder config for the root context.

You have a property placeholder configurer in the servlet context(spring-servlet.xml). Property placeholder configurers(defined by the context:property-placeholder tag) are bean postprocessors and work on per container basis, so they can't modify the bean definitions of context they are not defined in. So it can't modify the bean definition of controller instance declared in the root context(carpool-application-context.xml, carpool-application-context1.xml). So because of the double scanning your controller is created twice - both in root and servlet context, and only one is processed by the correct placeholder configurer.

As a fix, you can use filter expressions in component-scan to pick up @Controller annotated classes only only in the spring-servlet.xml, and exclude it from carpool-application-context.xml/carpool-application-context1.xml

See @Service are constructed twice for examples of filters

Please keep your Spring configuration simple, your configuration is very puzzling.

update you are confusing controllers (which are annotated with @Controller and I think should be better put into aaa.bbb.controllers package) with services which should be annotated with @Service in the util package. My advice is to move your services to the root web app context(carpool-application-context1.xml) and put the property placeholder configurer declaration there.

Share:
10,240
Jayesh
Author by

Jayesh

Updated on June 04, 2022

Comments

  • Jayesh
    Jayesh almost 2 years

    I have Two projects, CarpoolDB and Carpool.

    CarpoolDB : contains backend stuff and has

    carpool-application-context.xml

    <context:annotation-config />
    <context:component-scan base-package="com.onmobile" />
    <context:property-placeholder location="classpath:server.properties" />
    

    server.properties

    cm.db.driverClassName=com.mysql.jdbc.Driver
    cm.db.url=jdbc:mysql://localhost:3306/carpool1
    cm.db.username=abc
    cm.db.password=xyz
    

    I make a jar of carpoolDB and place in Carpool Application

    Carpool: contains UI thing and for backend contact carpoolDB jar and has

    carpool-application-context1.xml

    <import resource="classpath:carpool-application-context.xml"/>
    <context:annotation-config />
    <context:component-scan base-package="com.onmobile.carpool.authentication" />
    

    spring-servlet.xml

    <context:property-placeholder location="classpath:carpool.properties" /> 
    
    <context:annotation-config />
    <context:component-scan base-package="com.onmobile.carpool.controller, com.onmobile.carpool.util" />
    

    carpool.properties

    cm.email.sender.mail.smtp.host=mail.on.com
    

    Now, I have one class com.onmobile.carpool.util.EmailSender, it has one property smtpHost and want the value to get injected by Spring using @Value but it is not getting injected.

    @Controller
    public class EmailSender {
    
        public static final Log logger = LogFactory.getLog(EmailSender.class);
    
        @Value("${cm.email.sender.mail.smtp.host}")
        private String smtpHost;
    
    }
    

    I am getting error as

    java.lang.IllegalArgumentException: Could not resolve placeholder 'cm.email.sender.mail.smtp.host'
    

    carpool.properties is present in src folder.

    Why it is not picking the cm.email.sender.mail.smtp.host from carpool.properties file. is there any relation with properties file present in jar file.

    Actually properties file is loaded as I can't see in logs like file not found but field is not getting autowired.



    Posting updated complete configuration files after removing import

    web.xml

      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
                /WEB-INF/carpool-application-context1.xml
                /WEB-INF/applicationContext-security.xml
            </param-value>
      </context-param>
      <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>
      </filter-mapping>
      <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/jsp/*</url-pattern>
      </servlet-mapping>
      <listener>
        <listener-class>
        org.springframework.web.context.ContextLoaderListener
        </listener-class>
      </listener>
      <listener>
        <listener-class>
            org.springframework.security.web.session.HttpSessionEventPublisher
            </listener-class>
      </listener>
    

    carpool-application-context1.xml

    <!-- Configure annotated beans --> 
    <context:annotation-config />
    <context:component-scan base-package="com.onmobile.carpooldb.db" />
    <context:property-placeholder location="classpath:carpool.properties" />
    
    
       <beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
            <beans:property name="driverClassName"><beans:value>${cm.db.driverClassName}</beans:value></beans:property>
            <beans:property name="url"><beans:value>${cm.db.url}</beans:value></beans:property>
            <beans:property name="username"><beans:value>${cm.db.username}</beans:value></beans:property>
            <beans:property name="password"><beans:value>${cm.db.password}</beans:value></beans:property>
            <beans:property name="testOnBorrow"><beans:value>true</beans:value></beans:property>
            <beans:property name="testOnReturn"><beans:value>true</beans:value></beans:property>
            <beans:property name="validationQuery"><beans:value>select 1</beans:value></beans:property>
            <beans:property name="maxIdle"><beans:value>-1</beans:value></beans:property>
            <beans:property name="maxActive"><beans:value>-1</beans:value></beans:property>
            <beans:property name="maxOpenPreparedStatements"><beans:value>-1</beans:value></beans:property>
            <beans:property name="maxWait"><beans:value>30000</beans:value></beans:property>
        </beans:bean>
    
        //session factory bean and other configuration 
    

    spring-servlet.xml

    <context:property-placeholder location="classpath:carpool.properties" />
    
    <context:annotation-config />
    <context:component-scan base-package="com.onmobile.carpool.authentication, com.onmobile.carpool.controller, com.onmobile.carpool.util" />
    
    
    <!-- Declare a view resolver -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
    p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
    
    <bean id="multipartResolver"
        class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    
        <!-- one of the properties available; the maximum file size in bytes -->
        <property name="maxUploadSize" value="100000"/>
    </bean>
    

    carpool.properties

    cm.db.driverClassName=com.mysql.jdbc.Driver
    cm.db.url=jdbc:mysql://localhost:3306/carpool
    cm.db.username=abc
    cm.db.password=xyz
    
    user.profile.pic.base.folder=D:\\carpoolRepository\\carpoolProfilePicUpload
    google.places.autocomplete.response.xml.base.folder=D:\\carpoolRepository\\googleMapXML
    
    #EMAIL - FORGOT PASSWORD 
    cm.email.sender.mail.smtp.host=mail.on.com
    

    I am trying to inject value of cm.email.sender.mail.smtp.host in EmailSender "smtpHost" property way mentioned above, when i read it it says null. other properties like cm.db.driverClassName etc get properly injected in carpool-application-context1.xml.

    I am attaching the snap containing location for configuration filesenter image description here

  • ach
    ach over 11 years
    "Please keep your Spring configuration simple, your configuration is very puzzling." +1 to that.
  • Jayesh
    Jayesh over 11 years
    Hey Boris, Thanks for explaining and pointing to references which helped in getting the problem but still i am not very clear. can you please elaborate your first paragraph....please it will be lot helpful...thanks
  • Boris Treukhov
    Boris Treukhov over 11 years
    It seems that the tag has been swallowed by the markdown, I'll fix it when I get to PC. The problem is that the first configuration file scans "com.onmobile" and that includes your controller class that has value annotation. Configurer is not defined in the root context(which processes appcontext and appcontext1 files), the situation is the similar as in the first link of the answer. No placeholder configurer in the root context, the configurer in servlet context can't do anything with the controller mistakingly created in the root context because postprocessors work on per app context basis.
  • Jayesh
    Jayesh over 11 years
    Hey Boris, really appreciated for your quick reply.I have restructured my app and now i have only carpool-application-context1.xml with data <context:annotation-config /> <context:component-scan base-package="com.onmobile.carpooldb.db" /> <context:property-placeholder location="classpath:carpool.properties" /> and spring-servlet.xml with data <context:property-placeholder location="classpath:carpool.properties" /><context:annotation-config /> <context:component-scan base-package="com.onmobile.carpool.authentication,com.onmobi‌​le.carpool.controlle‌​r, com.onmobile.carpool.util"/>
  • Jayesh
    Jayesh over 11 years
    still I am facing issue of @Value not working. what i should do to make it work.
  • Boris Treukhov
    Boris Treukhov over 11 years
    You need to have the property placeholder configurer in the same app context where the controller declared.
  • Boris Treukhov
    Boris Treukhov over 11 years
    Are you sure that carpool-application-context.xml is out of the game?