Passing Env. into my application-config.xml - java

I'm currently working on a java application. The application has 3 different properties files. I want to be able to set the name of the properties file based on the name of the server the app is running on.
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/config/InfSit.properties</value>
</list>
</property>
</bean>
This is from my application-config.xml and currently works fine. I want to be able to change the name of the properties file based on the server the application is running on. So "InfSit.properties" would be "Inf${Env}.properties" (or something along these lines) - But I need a way to pass in the ${Env} parameter (could even be a string from another class). Can anyone suggest the best way to do this?
Thanks.

Set system property in java args
java -Denv=Sit ...
and it will replace ${env} in location expr
<context:property-placeholder location="classpath:/config/Inf${env}.properties" />

Just set the variable and reference it, I do similar with CATALINA_HOME :
<context:property-placeholder location="file:${catalina.home}/conf/database_UAT.properties"
ignore-unresolvable="true"/>
Just make sure you set the variable correctly ...

Related

Niolocker is not working in spring boot application

Trying to test file lock mechanism in spring boot application by starting two instances of same application pointing to same source path which contains 10 files. Expecting only one instance should process a file and once processed it will be deleted from source. Same file should not be processed by other instance.So added Niolocker to the scanner. Tested in both windows and linux environments.But in windows, facing below exception in both the instances... In Linux, same file is polled/processed by both instances. No impact in Linux. Have implemented the below logic to acquire lock.
Please suggest on this.
Windows exception:
java.io.IOException: The process cannot access the file because another process has locked a portion of the file
Linux:
Both instance poller picks the same file and processing it
<file:inbound-channel-adapter id="filesInChannel" directory="file:${base.path}" auto-startup="false" scanner="recursiveScanner" auto-create-directory="true">
<integration:poller id="poller" max-messages-per-poll="${max.messages.per.poll}" fixed-rate="${message.read.frequency}" task-executor="pollingExecutor">
<integration:transactional transaction-manager="transactionManager" />
</integration:poller>
</file:inbound-channel-adapter>
<bean id="inboundFilter" class="org.springframework.integration.file.filters.CompositeFileListFilter">
<constructor-arg>
<list>
<bean class="org.springframework.integration.file.filters.AcceptOnceFileListFilter"/>
<bean class="org.springframework.integration.file.filters.RegexPatternFileListFilter">
<constructor-arg value="${file.type}"/>
</bean>
</list>
</constructor-arg>
</bean>
<bean id="inboundChannelNioLocker" class="org.springframework.integration.file.locking.NioFileLocker" />
<bean id="recursiveScanner" class="org.springframework.integration.file.RecursiveDirectoryScanner">
<property name="filter" ref="inboundFilter" />
<property name="locker" ref="inboundChannelNioLocker"/>
</bean>
The NioLocker is really operation system dependent and doesn't guarantee exclusive access to the file. Well, only Windows does that for us properly.
I even start considering to deprecate and remove it altogether from the Framework. It causes too much confuses for target users...
Instead of file locker you need to consider to use a FileSystemPersistentAcceptOnceFileListFilter based on the shared ConcurrentMetadataStore. So, this way really only one instance will pick up the file for processing. All others will skip it and move on to the next files.
See Reference Manual for more info.

metrics-spring configuration via .properties file

I'm trying to configure metrics-spring via configuration file
In my spring.xml I've added
<bean id="propertyPlaceholderConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>
classpath:metrics.properties
</value>
</list>
</property>
<property name="systemPropertiesModeName"
value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="searchSystemEnvironment" value="true"/>
</bean>
filled with something like
metrics.reporter.type=console
and then I'm setting it in the spring config accessing that property via ${metrics.reporter.type}
<metrics:reporter metric-registry="metrics" type="${metrics.reporter.type}" period="1m"/>
During the startup of the web application, spring throws a BeanDefinitionParsingException due to the unresolved variable above
Configuration problem: No ReporterElementParser found for reporter type '${metrics.reporter.type}'
I'm using this configuration method (via properties file) for mongo host and port and it works like a charm.
I'm running in Tomcat7, Spring 4.0.5.RELEASE, metrics framework 3.1.0-SNAPSHOT (I need jersey 2 support) and metrics-spring 3.0.1. I also tried with a self-compiled metrics-spring 3.1.0-SNAPSHOT but doesn't solve my problem.
[EDIT]
Found this issue which explain that SpEL is not supported by the ElementParser.
I'm afraid it isn't possible to use a property placeholder in the type attribute. Spring does not resolve property placeholders or SpEL until the phase after metrics-spring reads the type attribute and parses the reporter element (which is necessary to allow placeholders and bean references to be used in all the other attributes).
A possible solution would be to configure all the reporters you might want to use, and use a placeholder in the enabled attribute:
<metrics:reporter metric-registry="metrics" type="console" period="1m"
enabled="${metrics.reporter.console.enabled}" />
<metrics:reporter metric-registry="metrics" type="slf4j" period="1m"
enabled="${metrics.reporter.slf4j.enabled}" />
And the properties file:
metrics.reporter.console.enabled=true
metrics.reporter.slf4j.enabled=false
I hope this makes sense, I've had a very long week!

How to configure properties in XML?

I am planing to Maven develop a module that actually needs to read configuration data something like below, where tag <path> will be repeated multiple times with different path name and can be same <pathtype> and different URL and parameters and then attempt to access those URLs and paths in Java classes.
In Java I should be able to read all <pathurl> tags and its parameters for given type. then I will process them in Java one by one.
What is best way to configure this data and read in Java? Should it be normal properties file loading process by Java or there is any new best practice using spring or any other utility.
Basically I want to know is there any way of configuring data other than in this XML format and then parsing it? Since the data is static in that XML, my client don't want to use database.
<path>
<pathname>mypath</pathname>
<pathtype>httpfile</pathtype>
<pathurl>http://acdsds:8380/gis/</pathurl>
<params>
<user>sad</user>
<password>spwd</password>
<httprescd>100</httprescd>
<mexist>DROD_MEF.gif</mexist>
</params>
</path>
When it comes to configuring software using certain properties such as URL's, passwords and unique keys in spring PropertyPlaceHolderConfigurer is your best bet.
From spring document:
You use the PropertyPlaceholderConfigurer to externalize property values from a bean definition in a separate file using the standard Java Properties format. Doing so enables the person deploying an application to customize environment-specific properties such as database URLs and passwords, without the complexity or risk of modifying the main XML definition file or files for the container.
What you will do is, put all your configuration data in a properties file:
##JDBC related properties start here##
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.dialect=org.hibernate.dialect.MySQLDialect
jdbc.databaseURL=jdbc:mysql://localhost:3306/databaseName
jdbc.userName=root
jdbc.password=root
##JDBC related properties end here##
## path Configuration start here##
path.name=mypath
path.type=httpfile
path.url=http://acdsds:8380/gis/
## path Configuration ends here##
Then, configure spring to access external properties file(assuming your properties file is named settings.properties):
<!--settings for accessing external property files-->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>/yourPathToPropertiesFile/settings.properties</value>
</list>
</property>
</bean>
After you have configured PropertyPlaceholderConfigurer, access your properties by simple using #value annotation, wherever you want.
#Value("${path.name}")
String pathName;
You can even use properties file to configure you data source and many other stuff:
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.databaseURL}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
You should probably start by reading some basic tutorials on XML processing in Java. I'm biased, but my standard recommendation is still the material at IBM's DeveloperWorks XML site
You can use json configuration file and Google's Gson(https://code.google.com/p/google-gson/) to parse the json file. Refer to this thread Parse a nested JSON using gson on how to use Gson library & sample json format.

property not found with multiple context:property-placeholder

I am using spring 3.1 with spring profiles to load the beans. In my app context file, I load the properties like :
<context:property-placeholder order="1" location="classpath*:META-INF/spring/*_${spring.profiles.active}.properties" ignore-unresolvable="true"/>
And then I use the property value to load the data source bean like
<property name="driverClassName" value="${database.driverClassName}"/>
It works fine.
The problem starts when I add a couple of more property placeholders so that properties from some database tables can be loaded.
This uses a properties reference loaded by
<bean id="configFactoryBean"
class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="globalSystemConfiguration"/>
</bean>
To add to the details, this configFactoryBean uses the datasource to load the properties from the database.
When I do this, I have the following exception:
java.lang.ClassNotFoundException: ${database.driverClassName}
My analysis is that its trying to load the datasource before resolving the property from the first context property placeholder. I may be wrong. Or maybe spring profile variable is not resolved properly.
Can anyone please help me to fix this.
Thanks
Akki
This bug about multiple property placeholders might relate to your problem: https://jira.spring.io/browse/SPR-9989
When using multiple PropertyPlaceholderConfigurer in conjunction with
#Value annotation and default value for placeholders syntax (ie
${key:defaultValue}), only the first PropertyPlaceholderConfigurer is
used. If this configurer does not contain the desired value, it falls
back to #Value default even if the second
PropertyPlaceholderConfigurer contains the value.
Affects Version/s: 3.1.3
Each <context:property-placeholder> creates a new instance of PropertyPlaceholderConfigurer - it gets messy easily. You should have one such thing per application and on application level, not on libraries' one - that makes maintenance much easier.
For more details and a suggestion how to cope with it look here:
http://rostislav-matl.blogspot.cz/2013/06/resolving-properties-with-spring.html
In my application I am using property-placeholder configurer in following way and it works very well. You can try that.
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:META-INF/spring/*_${spring.profiles.active}.properties</value>
</list>
</property>
</bean>
I think this should resolve your problem. :)
Since you have suggested hardcoding the path to the configuration file works, try using the profiles attribute on the tag to selectively include the configuration.
<beans profile="profileName">
<context:property-placeholder order="1" location="classpath*:META-INF/spring/hardcoded.properties" ignore-unresolvable="true"/>
</beans>
<beans profile="profileName2">
<context:property-placeholder order="1" location="classpath*:META-INF/spring/hardcoded.properties" ignore-unresolvable="true"/>
</beans>
See this article explaining profiles: http://java.dzone.com/articles/using-spring-profiles-xml

Spring JMX. Set the default value of #ManagedAtrribute through XML

I'm using Spring 3.0.5
I have a #ManagedResource bean, for some of the #ManagedAttribute methods which I want to set a defaultValue. Instead of setting it to a hardcoded value I want to be able to read it from a property value at load time, since the default changes from environment to environment.
A snippet from my programs applicationContext.xml:
<context:mbean-export default-domain="sampleApp"/>
<bean id="managedBean" class="com.example.sampleBean">
<constructor-arg value="Sample Bean"/>
<constructor-arg value="${sample.property}"/>
</bean>
I believe I have to use the XML configuration to be able to do this, but haven't figured out how to do it yet.
You can add the following to your applicationContext.xml, it should expose the properties you are after:
<context:property-placeholder location="classpath:application.properties"/>
So if the application.properties file you are pointing to above contains a property called sample.property then Spring will use that to inject into your ${sample.property} placeholder.
For more details you can see the Spring reference here.

Categories

Resources