How to use pom properties in spring context.xml? - java

I have pom file(pom.xml):
...
<properties>
<certificate-manager.default-client-certDN>Default Client</certificate-manager.default-client-certDN>
<certificate-manager.path-to-store>D:\Projects\PPP\apache-tomcat-7.0.29\</certificate-manager.path-to-store>
<certificate-manager.store-password>12345</certificate-manager.store-password>
<certificate-manager.alias>root</certificate-manager.alias>
</properties>
and properties file(my.properties):
certificateManager.defaultClientCertDN=${certificate-manager.default-client-certDN}
certificateManager.pathToStore=${certificate-manager.path-to-store}
certificateManager.storePassword=${certificate-manager.store-password}
certificateManager.alias=${certificate-manager.alias}
and I want to use this properties in my spring context.xml(appContext.xml):
<context:property-placeholder location="classpath:my.properties"/>
<bean id="certificateManager" class="com.exadel.mdp.security.certificate.CertificateManagerImpl">
<constructor-arg name="defaultClientCertDN" value="${certificateManager.defaultClientCertDN}"/>
<constructor-arg name="pathToStore" value="${certificateManager.pathToStore}"/>
<constructor-arg name="storePassword" value="${certificateManager.storePassword}"/>
<constructor-arg name="alias" value="${certificateManager.alias}"/>
</bean>
When I'm trying to run app, I get the next exception:
ERROR: org.springframework.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'certificateManager' defined in class path resource [appContext.xml]: Could not resolve placeholder 'certificateManager.defaultClientCertDN' in string value [${certificateManager.defaultClientCertDN}]
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:174)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:151)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:661)

I believe you use Maven Properties Plugin and configure it for initialization phase. Spring independently will read from the property file.

Related

Read PropertyPlaceholderConfigurer classpath Spring with Jboss

Using PropertyPlaceholderConfigurer to externalize spring-configuration
properties.
Added following code to spring-servlet.xml
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:environment.properties</value>
</property>
</bean>
Filter to be externalized from spring-security.xml
<security:custom-filter position="AUTH_FILTER" ref="${filter}" />
filter value is present in environment.properties
environment.properties file is present inside Jboss modules and is readable from code using resource bundle.
But, with these changes somehow properties file is not getting loaded and following error is thrown while publishing code.
Caused by: java.lang.IllegalArgumentException: Could not resolve
placeholder 'filter' in string value "${filter}"
PS:
Also tried hardcoding path as <value>file:${jboss.home.dir}/modules/system/layers/base/configuration/main/environment.properties</value> but, dosen't seems to be working.
I think your problem is that your spring-servlet.xml is not linked to your spring-security.xml. So spring-security.xml has no knowledged of the PropertyPlaceholderConfigurer.
IMO, you should configure PropertyPlaceholderConfigurer in a properties-context.xml (for instance) so you can import this new file into your spring-servlet.xml and spring-security.xml as following:
<import resource="classpath:properties-context.xml" />

Externalize properties in Tomcat

I would like to configure a series of environment-dependant settings as an external resource, so that the same WAR artifact can be configured in any application server.
In Glassfish I rememeber that I just created a .properties file using the built-in Properties Resource JNDI Factory, and it worked like a charm, but there's no such thing in Tomcat.
I tried defining a java.net.URL and a java.lang.String to define just the path that this file is held in, but I get the following error:
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/c://app.properties]
So what would be a good way to create an environment-agnostic set of properties for my application?
PS: this is how I define my properties in Spring:
<jee:jndi-lookup id="appProperties" jndi-name="java:comp/env/url/urlAppProperties" />
<bean id="application-properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>#{ appProperties }</value>
</list>
</property>
</bean>
You can add external configuration values to the JNDI context using Tomcat's resource configuration elements. As described in the Tomcat documentation, you can define a <GlobalNamingResources> element in your server.xml listing a set of configuration values which are available to all contexts (web applications) on that server:
Example taken from the Tomcat docs:
<GlobalNamingResources ...>
...
<Environment name="maxExemptions" value="10"
type="java.lang.Integer" override="false"/>
...
</GlobalNamingResources>
These environment variables are then available via JDNI in the java:comp/env context. In order to use such variables in a web application, you have to link to them in the individual context.xml configuration files using the <ResourceLink> element.
<Context>
<ResourceLink name="maxExemptions" global="maxExemptions" type="java.lang.Integer"/>
</Context>
With this set up, you can access these values through the standard JNDI API.

Spring: Nested beans reference to another bean is not working

I am trying to use nested beans with a profile to setup an embedded jms broker when I am in dev mode. Here is my xml:
<beans ...>
...
other bean definition
...
<beans profile="embeddedBroker">
<!-- Configure an embedded ActiveMQ Broker with a TCP connector.
This broker is never set to start automatically by default, it is the broker service wrapper that
will take care to start it if configured to do so.
-->
<amq:broker id="jmsBroker" brokerId="EmbeddedBroker" brokerName="EmbeddedBroker"
persistent="false" useJmx="true" start="false">
<amq:plugins>
<!-- lets enable detailed logging in the broker but ignore ConnectionEvents -->
<amq:loggingBrokerPlugin logMessageEvents="true" logConnectionEvents="false"/>
<amq:timeStampingBrokerPlugin zeroExpirationOverride="1000" ttlCeiling="60000" futureOnly="true"/>
<amq:traceBrokerPathPlugin />
</amq:plugins>
<!-- Create a connector to give an external remote access to this broker. -->
<amq:transportConnectors>
<amq:transportConnector uri="tcp://127.0.0.1:35000" />
</amq:transportConnectors>
</amq:broker>
<!-- This broker service (wrapper) control the lifecycle of the jms broker defined above.
By default the internal broker will be initialized, but not started. It will usually be started only for
internal integration and unit tests.
-->
<bean id="jmsBrokerService" class="com.imetrik.global.common.jms.AMQBrokerService"
init-method="start"
destroy-method="stop">
<property name="broker" ref="jmsBroker" />
<property name="enabled" value="true" />
</bean>
</beans>
</beans>
But when I run my application with the correct profile, spring complain that the jmsBroker reference cannot be found!
Error creating bean with name 'jmsBrokerService' defined in class path resource [jms-beans.xml]: Cannot resolve reference to bean 'jmsBroker' while setting bean property 'broker';
Is there a way to fix that? Is it because the reference bean is not in the same namespace?
I know that if I put it out of the nested beans, it is working fine.
I am using Spring 4.1

Load internal (Classpath) and external property file in a Spring Application

I need to load both external and internal property files in my spring application. Once I declare the external file as below
<context:property-placeholder location="file:${JBOSS_HOME}/123.properties" />
I can access the properties defined in this external file. But all properties related to the property file in my class path Could not resolved.
My Application Context
** <!--Refer External File --> **
<context:property-placeholder location="file:${JBOSS_HOME}/123.properties" />
<!--Refer Internal File -->
<bean id="helloWorldBean"
class="com.javacodegeeks.snippets.enterprise.services.HelloWorld">
<property name="internalProperty1" value="${internalProperty1}" />
<property name="**externalProperty**" value="${**externalProperty**}" />
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>constants.properties</value>
</property>
</bean>
I am getting property value of the external property file but not the value of the internal property file.
Exception in thread "main"
Exception in thread "main" org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'helloWorldBean' defined in class path resource [applicationContext.xml]: Could not resolve placeholder 'internalProperty1' in string value "${internalProperty1}"
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.processProperties(PropertySourcesPlaceholderConfigurer.java:174)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.java:151)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:694)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:669)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:461)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplsamicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
at com.javacodegeeks.snippets.enterprise.App.main(App.java:13)
Cannot I load external(non-class path) and internal (Class path) property file together ?
What you need is something like this:
<!--Order matters, properties in the second file will override the first -->
<context:property-placeholder location="file:${JBOSS_HOME}/123.properties,classpath:configuration.properties"
ignore-unresolvable="false" ignore-resource-not-found="true" />

How to initialize property-placeholder with environment attached to the current application context in Spring?

I'm using Spring Framework 3.2.6.RELEASE.
I'm trying to set properties using command line interface (using JOptCommandLinePropertySource) via
PropertySource<?> propertySource = new JOptCommandLinePropertySource(options);
final GenericApplicationContext context = new GenericApplicationContext();
context.getEnvironment().getPropertySources().addFirst(propertSource);
...
I have this beans configurer:
package com.example;
#Configuration
public class AppConfig {
#Value("${prop1}")
private String prop1;
#Bean
public MyBean myBean() {
MyBean ret = new MyBean();
ret.init(prop1);
return ret;
}
}
I'm starting my program with command line argument: --prop1=prop_value
If I do initialization with this xml:
<beans>
<context:annotation-config />
<context:property-placeholder />
<context:component-scan base-package="com.example" />
</beans>
Then I get this error: Could not resolve placeholder 'prop1' in string value "${prop1}"
13:47:36.932 [main] DEBUG o.s.b.f.annotation.InjectionMetadata - Processing injected method of bean 'AppConfig': AutowiredFieldElement for private java.lang.String com.example.AppConfig.prop1
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'AppConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String com.example.AppConfig.prop1; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'prop1' in string value "${prop1}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289) ~[spring-beans-3.2.6.RELEASE.jar:3.2.6.RELEASE]
...
But with this xml all works fine:
<beans>
<context:annotation-config />
<context:component-scan base-package="com.example" />
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="environment" ref="environment" />
</bean>
</beans>
Why PropertySourcesPlaceholderConfigurer does not check current application context's environment as it defined in Javadoc?
Specialization of PlaceholderConfigurerSupport that resolves ${...} placeholders within bean definition property values and #Value annotations against the current Spring Environment and its set of PropertySources.
When using namespace configuration it is recommended to use the version-less xsd. So instead of http://www.springframework.org/schema/context/spring-context-2.5.xsd one is adviced to use http://www.springframework.org/schema/context/spring-context.xsd. This ensures that spring will use the most recent version of the xsd available on the classpath.
With regard to <context:property-placeholder /> there where some, breaking(?), changes in Spring 3.1 in regards to the default configuration. Prior to Spring 3.1 the default-value for the system-properties-mode attribute was FALLBACK, which in Spring 3.1 leads to the creation of a PropertyPlaceholderConfigurer instead of a PropertySourcesPlaceholderConfigurer. The default is configured in the specific xsd. (As if Spring 3.1 it is ENVIRONMENT).
So using an older xsd leads to the default behavior belonging to that specific version of the xsd, switch to either the 3.2 xsd or the version-less xsd. (As mentioned the latter is recommended).

Categories