How can I pass VM args to applicationContext in spring - spring

How can I pass vm args (java -Dport = 5) to the application context?
I want to configure the port dynamically by the user, using the application context.

In case you trying to access the VM arguments in spring application context, then just add the below bean definition in context file:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="true"></property>
</bean>
And access the VM args as ${vm_property}.
e.g if you passed the –Dport=5, which can be accessed as
<bean class="com.testing.test.MyClass">
<property name="myProperty" value="${port}"></property>
</bean>

I think There is only one way in spring using injection. and get the property value from any property file

Related

Apache Camel Spring DSL, referring to an environment variable HOSTNAME

I am using Apache Camel 2.16.0 with Spring DSL
I have a Spring context XML in which I have defined a Property PlaceHolder to read the properties from various files as follows-
<bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="ignoreResourceNotFound" value="false"/>
<property name="locations">
<list>
<value>classpath:/properties/versioning.properties</value>
<value>classpath:/properties/#{inetAddress.hostName}.properties</value>
</list>
</property>
</bean>
<bean id="inetAddress" class="java.net.InetAddress" factory-method="getLocalHost"/>
The property values are used to construct other beans such as -
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="${${LIVE_}DATASOURCE_URL}"/>
<property name="username" value="${${LIVE_}DATASOURCE_USERNAME}"/>
<property name="password" value="${${LIVE_}DATASOURCE_PASSWORD}"/>
</bean>
This works fine, I can see the beans being created.
I also have another Spring Context XML in the same app which has a camel context and I want to use the some other properties defined in the same properties files. I know that camel supports Spring Property Placeholder, see below excerpts from the context -
<camelContext id="charge-process-context" xmlns="http://camel.apache.org/schema/spring">
<propertyPlaceholder id="properties"
location="classpath:/properties/versioning.properties,
properties/${env:HOSTNAME}.properties"
xmlns="http://camel.apache.org/schema/spring" />
.....
.....
</camelContext>
As part of this context, I have a route that uses https component that uses the values from the property file such as below -
<to uri="https4:{{LIVE_AUTH_RESPONSE_HOST}}:{{LIVE_AUTH_RESPONSE_PORT}}/{{LIVE_AUTH_RESPONSE_CONTEXT_PATH}}"/>
This route does not start and throws following exception -
Caused by: java.lang.IllegalArgumentException: Cannot find system environment with key: HOSTNAME
at org.apache.camel.util.FilePathResolver.resolvePath(FilePathResolver.java:54)
at org.apache.camel.component.properties.PropertiesComponent.parseLocations(PropertiesComponent.java:434)
at org.apache.camel.component.properties.PropertiesComponent.parseUri(PropertiesComponent.java:163)
at org.apache.camel.component.properties.PropertiesComponent.parseUri(PropertiesComponent.java:148)
at org.apache.camel.impl.DefaultCamelContext.resolvePropertyPlaceholders(DefaultCamelContext.java:2261)
at org.apache.camel.model.ProcessorDefinitionHelper.resolvePropertyPlaceholders(ProcessorDefinitionHelper.java:730)
at org.apache.camel.model.ProcessorDefinition.createOutputsProcessorImpl(ProcessorDefinition.java:427)
at org.apache.camel.model.ProcessorDefinition.createOutputsProcessor(ProcessorDefinition.java:413)
at org.apache.camel.model.ProcessorDefinition.createOutputsProcessor(ProcessorDefinition.java:165)
at org.apache.camel.model.ExpressionNode.createFilterProcessor(ExpressionNode.java:109)
at org.apache.camel.model.WhenDefinition.createProcessor(WhenDefinition.java:74)
at org.apache.camel.model.WhenDefinition.createProcessor(WhenDefinition.java:32)
at org.apache.camel.model.ProcessorDefinition.createProcessor(ProcessorDefinition.java:483)
at org.apache.camel.model.ChoiceDefinition.createProcessor(ChoiceDefinition.java:135)
at org.apache.camel.model.ProcessorDefinition.makeProcessorImpl(ProcessorDefinition.java:534)
at org.apache.camel.model.ProcessorDefinition.makeProcessor(ProcessorDefinition.java:495)
at org.apache.camel.model.ProcessorDefinition.addRoutes(ProcessorDefinition.java:219)
at org.apache.camel.model.RouteDefinition.addRoutes(RouteDefinition.java:1069)
Please Note: I am deploying my application as a war file on Tomcat 8 on an AWS instance.
I have a Dev Environment on Windows 10 and I have found this working on the Windows OS. I have also seen that the file FilePathResolver.java in Apache Camel 2.16 uses System.getenv(key) to obtain the value i.e. System.getenv("HOSTNAME") which returns a null on AWS instance and a correct value on Windows 10. I also tried using env:hostname (small case letters for unix) but still no luck ...
I found a solution at http://camel.apache.org/using-propertyplaceholder.html
at Bridging Spring and Camel Property Placeholders
It mentions following -
The Spring Framework does not allow 3rd party frameworks such as Apache Camel to seamless hook into the Spring property placeholder mechanism. However you can easily bridge Spring and Camel by declaring a Spring bean with the type org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer, which is a Spring org.springframework.beans.factory.config.PropertyPlaceholderConfigurer type.

Can not load property file in spring-context.xml. Property file Path is given as a placeholder in dev.properties

I am loading property file in spring-context.xml and i am giving
external property file location in
${spring.profiles.active}.properties which is in classpath and using the location as a placholder in spring-context.xml. My spring-context.xml is:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreResourceNotFound" value="true" />
<property name="ignoreUnresolvablePlaceholders" value="true" />
<property name="searchSystemEnvironment" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="locations" ref="propertyConfigurerFiles" />
</bean>
<bean id="propertyConfigurerFiles" class="java.util.ArrayList">
<constructor-arg>
<list>
<value>/WEB-INF/properties/common.properties</value>
<!--In Developemnet Enviroenment it will be dev.properties-->
<value>/WEB-INF/properties/${spring.profiles.active}.properties</value>
<!--External Property File Location as a Placeholder-->
<value>${app.config.batch.location}</value>
</list>
</constructor-arg>
</bean>
And my dev.properties is:
app.config.batch.location=E:/project/properties/config.properties
My problem is that is ${app.config.batch.location} placeholder is not
resolved in spring-context.xml and its trying to load file
${app.config.batch.location} in place of
E:/project/properties/config.properties.
I hope I explained the problem well. Please help!
Thanks in Advance!!!
You need to create bean of class PropertyPlaceHolderConfigurer.
Not just some ArrayList bean. Why do you think you need this ArrayList bean?
It seems you are using spring profiles, instead of messing with initialization time property value binding what you can do is ...
1) read the property file(profile's)
/WEB-INF/properties/${spring.profiles.active}.properties
2) create a java class that can read these property values. (don't forget to use spring profiles interfacing class)
3) as you are trying to read a property file whose location is embedded in property file(step-1), object created at step-2 will give value for key <value>${app.config.batch.location}</value>
now you can load this property file using available file reader class.
4) create Properties object and access the values in it.
Note:: if any of your bean initialization depends on key-value read at step-4, do initialization manually or create your ***custom class(servlet) that get loaded before any other class (even spring's DispactherServlet).

Jasypt and Weblogic environment variables

I am using jasypt 1.9.2 to encrypt a password in a property file for my spring REST service. I've added an environment variable to Weblogic via the Server startup arguments text box called APP_ENCRYTPION_PASSWORD, but that environment variable is not getting read by the jasypt. Here is the error:
ERROR o.s.web.servlet.DispatcherServlet - Context initialization failed
java.lang.NullPointerException: null
at org .jasypt.encryption.pbe.config.SimplePBEConfig.getPasswordCharArray(SimplePBEConfig.java:434) ~[jasypt-1.9.2.jar:na]
Here is the Weblogic environment variable logged during when the server starts up:
JAVA_OPTIONS= -Dother.vars=xxx -DAPP_ENCRYPTION_PASSWORD=password -Dmore.vars=yyy
I've traced the jasypt code and it seems jasypt does not parse the environment variables within JAVA_OPTIONS. I know this works for other frameworks like spring since we have other environment variables within JAVA_OPTIONS that spring has no issue reading.
I could add the environment variable to the startup scripts (setEnv.sh I think) for weblogic, but that will add the variable for all managed nodes instead of the one cluster my app is deployed to.
Is there a different way to configure jasypt within spring to get the environment variables within JAVA_OPTIONS?
Here is my spring config:
<bean
class="org.jasypt.spring31.properties.EncryptablePropertyPlaceholderConfigurer">
<constructor-arg>
<bean class="org.jasypt.encryption.pbe.StandardPBEStringEncryptor">
<property name="config">
<bean class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<property name="algorithm" value="PBEWithMD5AndTripleDES" />
<property name="passwordEnvName" value="APP_ENCRYPTION_PASSWORD" />
</bean>
</property>
</bean>
</constructor-arg>
<property name="location">
<value>application.properties
</value>
</property>
</bean>
My application.properties file contents:
username=someuser
password=ENC(encryptedstring)
UPDATE for clarity:
Adding the environment variable to weblogic via setEnv.sh or Eclipse works just fine. It's only when I use the weblogic console to add the environment variable for a cluster that jasypt fails to parse the value since it is within JAVA_OPTIONS.
You can use passwordSysPropertyName instead of passwordEnvName. This way you can use -DpasswordSysPropertyName="mysecret"
<bean id="environmentVariablesConfiguration"
class="org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig">
<property name="algorithm" value="PBEWithMD5AndDES" />
<property name="passwordSysPropertyName" value="APP_ENCRYPTION_PASSWORD" />
</bean>

Spring PropertyPlaceholderConfigurer not replacing placeholder

I want to pass the WSDL url for an internal web service into my Spring beans.xml dynamically, using a PropertyPlaceHolderConfigurer.
Here's the scenario:
My web application is deployed in WebLogic 10.3.
The WSDL url is contained in a properties file that is located outside my application (directly under the corresponding domain folder, while my application is inside the autodeploy folder). I set the location of this properties file in my domain's setDomainEnv.cmd file like below:
set JAVA_PROPERTIES=%JAVA_PROPERTIES% %CLUSTER_PROPERTIES% -Dproperty.file.path.config=%DOMAIN_HOME%\Service.properties
This is what my Service.properties file contains:
Service.WSDL.PATH=http://localhost:8088/mockServiceSoap?WSDL
My Spring beans.xml configuration:----
<bean id="file.path" class="java.lang.System" factory-method="getProperty">
<constructor-arg index="0"><value>property.file.path.config</value></constructor-arg>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" ref="file.path"/>
</bean>
<bean id="myServiceId" class="com.test.service.ServiceImpl">
<property name="myServiceSoap">
<ref bean="myService"/>
</property>
</bean>
<bean id="myService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
<property name="serviceInterface" value="com.test.service.ServiceSoap"/>
<property name="wsdlDocumentUrl" value="${Service.WSDL.PATH}"/>
</bean>
I enabled DEBUG log specifically for PPC and this is what I saw in my application log:
INFO org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 178 - Loading properties file from URL [file:D:/bea10.3/user_projects/domains/my_domain/Service.properties]
So, it seems that although the Service.properties file is getting loaded by PPC, the ${Service.WSDL.PATH} is NOT getting replaced.
What am I doing wrong here?
Also, how can I find out if PPC tried replacing the value of the placeholder and with what value? I was hoping the log file would contain that info but there was nothing there.
Any help is appreciated.
I've figured out, that PropertyPlaceholderConfigurer needs to be declared first in the application Context file, otherwise there's no guarantee of the load order. It took me a few hours to realize this.
Try moving the "file.path" bean into the PropertyPlaceHolderConfigurer's location property.

spring configuration with system property

I have a question. Currently i start jboss with -P property that links to file with properties.
In this property file i have property - mongo.server.list=127.0.0.1. In Spring configuration i try to set this property as value of constructor of bean. But spring treat ${mongo.server.list} as value itself.
Here is the code
<bean id="systemPropertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
</bean>
<bean id="mongo" class="com.mongodb.Mongo">
<constructor-arg index="0">
<value>${mongo.server.list}</value>
</constructor-arg>
</bean>
You should set your property file as a JVM property and read it in spring mvc configuration file as:
<context:property-placeholder location="file:///${-P}" />
You should specify the property as a JVM arg as -Dmongo.server.list=....
Did you try to start your server using -Dmongo.server.list=127.0.0.1 ? (i.e. using -D instead of -P, and no space between -D and the property name)

Resources