Jayesh
Jayesh

Reputation: 6111

Properties file not getting loaded

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

Upvotes: 2

Views: 10733

Answers (1)

Boris Treukhov
Boris Treukhov

Reputation: 17774

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.

Upvotes: 3

Related Questions