Need in understanding classpath in resource location and variable value set - java

Although I have been working in java for a while, there are many small things I have been ignoring, which at times have become bottleneck in productivity. I have difficulty in understanding this:
This is one of the bean.xml which gets placed in the final .war file (in a web application, built with spring framework).
<context:property-placeholder
location="classpath:/${deploy.env}/com.example.config/db.properties"
ignore-resource-not-found="false" />
I have following doubts:
1) At the time of building the code, i did like this for passing value of deploy.env
mvn clean install -Ddeploy.env=local
I ran the mvn in debug mode and could see this set to local. Now, the thing is, in the .war that gets generated, it is still ${deploy.env} (see above snippet). Doesn't this get replaced in the final .war? If not, then how do we pass the value which we intend to set?
2) what does "classpath:/${deploy.env}/com.example.config/db.properties" mean? Who sets the value of classpath? Are classpath capable of providing the location of resource files as well?
Assuming deploy.set --> local, so would this get translated to:
classpath:"/local/com.example.config/db.properties"
So does this mean db.properties would be present at: /local/com.example.config/db.properties
Any inputs to understand this would be of great help.

deploy.env is either environment variable or system property available to the JVM at run time.
The classpath:/${deploy.env}/com.example.config/db.properties will be resolved at run when your war is running in the container.
Set deploy.env=whatever in the shell from where you starting the tomcat or set in the environment of the user which starts the tomcat.
mvn clean install -Ddeploy.env=local here the deploy.env system property is available at build time. This will not replace the value of your spring config.
classpath is where all your classes and libraries bundled in the war are available along with the tomcat libraries. The spring property configurer will look for the db.properties file in the classpath at location e.g. /local/com.example.config
Spring documentation to learn more
Some explanation on my blog post

As stated in the Oracle Web site: The CLASSPATH variable is one way to tell applications, including the JDK tools, where to look for user classes.
That classpath: is referring to that location in particular, whatever it is, so it will start looking for those resources defined by Spring from that location and on, until it finds the first match.
Also, if you have that as a property in Maven, the value can be replaced with the right plug-in and configuration; not quite useful when you want a build that can be used with many values within those .properties files for different environments.
You can use other prefixes as file:, http:, etcetera. But you are just wondering about classpath:.

Related

Can I change a database depending on the branch I am on (specified in Dockerfile)?

I would like to have my:
spring.datasource.url = jdbc:mysql://666.666.666.666/prod_very_wow
Change into:
spring.datasource.url = jdbc:mysql://666.666.666.666/dev_very_wow
According to the branch I am currently on. I think I should also have it specified within the Dockerfile - I should have a property added next to docker's RUN which should determine which data source ought to be activated.
Namely, I would like my app to be connected to prod_very_wow when I am on master branch and dev_very_wow everytime I am checking out to dev or creating a new feature branch and have it all determined by a property added to RUN mvn package within the Dockerfile.
I apologise if the question makes no sense, but, frankly - I am a little bit clueless how to ask this question and so I have troubles googling for answers.
I just found a couple of leads about "environmental variables", but I can't find any connection between the datasource connected to and the branch I am currently on.
The best way to handle different configuration based on environment is to have decoupled your code from your configuration that is one of the twelve-factor apps principles. In this case you should have an external config server, like spring cloud config server, that will host the configurations files for the different environments and the application will ask this config server for the proper config file depending on the environment where it is deployed.
However, if you don't want to follow this approach you can create the different configuration files in the application and use an environment variable that tells spring which file to use. For example, in your case you can have an application-local.yaml and application-prod.yaml, and then if you want to specify it in the dockerfile in the mvn package command, you can use:
RUN mvn -Dspring.profiles.activ=local package
RUN mvn -Dspring.profiles.activ=prod package

Java Microprofile change properties on already deployed app (Wildfly)

I have an ear artifact deployed on a wildfly server. On some beans I used the following configuration injection
#Inject
private Config config;
I want to change the properties specified on the "microprofile-config.properties" file on runtime. It is not necessary to change the file itself, I just want to change the properties. I think there might be a way using the console, but I cannot find if there is any.
If you take a look at the spec or even at articles like this, you will see that, by default, Microprofile config reads configuration values from the following 3 places in this order - i.e. from wherever it finds it first:
System.getProperties()
System.getenv()
The configuration file
So, you can override values in the configuration file in 2 ways:
Defining -D command line arguments to the VM (e.g. java -DXXX=yyy ...)
Defining system environment variables (e.g. export XXX=yyy in bash or set XXX=yyy in Windows)
Note that there are some rules for defining environment variables and matching them to actual configurations, e.g. for a configuration aaa.bbb.ccc you may need to set an environment variable as AAA_BBB_CCC. Read ch. 5.3.1 in the specs, and experiment a little.
You can always extend the configuration sources with your own custom ones (to read configuration from JNDI, DB, Zookeeper, whatever).

Can/should I depend on WebLogic's bundled modules

My target platform is a WebLogic 12c application server.
I have an ear-project, which on startup requires e.g. org.apache.commons.logging.LogFactory.
I know that this class - an related classes - can be found in <WL_HOME>/modules/com.bea.core.apache.commons.logging.api_1.1.1.jar, but it is not by default available on the classspath.
In such cases - am I supposed to somehow make the jar file in <WL_HOME>/modulesavailable on the classpath - or should I provide whatever jar file I find suitable - either bundled in the application, or placed in <WL_HOME>/user_projects/domains/<mydomain>/lib?
If I am to use the one in the <WL_HOME>/modules folder - how do I configure my domain to make it available?
To me it seems reasonable that the jar files in the modules folder should be considered provided dependencies, but so far I have been unable to find the right way to enable them as such - I have been browsing for an answer for hours:-)
UPDATE:
I know I can simply add them to the CLASSPATH variable in the server startup script - my question is more like - should I? Is there a better way - or should I completely forget about <WL_HOME>/modules?
That's a short-sighted approach.
you need to reboot the server to upgrade libraries
every app on the server must be okay with those libraries in their claspath
Weblogic has the concept of Shared JEE Libraries (example). In short, you add extra lines to MANIFEST.MF and configure the jar differently, then you can reference it in other apps using weblogic-application.xml or whatever.
The point is that you can upgrade the library without restarting the server (provided you gave it a version like 1.1 (there were bugs last time I named it 1.1.1 - it needed to be able to cast it to a floating-point number to seamlessly upgrade)).
If you just want to include some libraries but not share them outside the app, then just specify the correct <prefer-application-packages> or < prefer-web-inf-classes> element, depending on whether you have an EAR or a WAR.

Setting system property get agent in teamcity maven build

I am trying to create plugin, which deploys my application in pre-integration-phase and runs the test against it. Now my application requires some property called LOOKUPLOCATOR which should be unique per envrionment. Now i have multiple agents configured in teamcity and many builds can run in parallel and if all the builds will have same property they will interfere with each other and test results will be unexpected.
Is there a way so that when my build run and in my java code if somehow get to know the agent name, and i will maintain a hardcoded value for LOOKUPLOCATOR for each agent, we can set that value. So my property will be per agent
Teamcity has some pre-defined variables which are available while a build is running. Agent name can be found in %teamcity.agent.name%.
Here is how to set agent-specific parameters
If additional applications/libraries are available in the environment, the administrator can manually define the property in the /conf/buildAgent.properties file. These properties can be used for setting various build configuration options, for defining build configuration requirements (for example, existence or absence of some property) and inside build scripts.

config.ini file properties being replaced by another file properties in OSGI Run Time

I have an option in my config.ini file to set proxy settings in my OSGI application, eg:
http:proxyHost= 192.168......
However, when I set them, out of nowhere in "org.eclipse.core.net.prefs" file they are overridden, eg:
proxyData/http/host=something else ...
I am wondering whether somehow eclipse thinks that I am trying to reconfigure its own proxy settings, if they exist ? I am not really confident what I am doing in the moment, so any help is appreciated.
The name of the preference file clearly states the name of the bundle that is using it. You are talking about org.eclipse.core.net.prefs meaning that the bundle using these properties is org.eclipse.core.net
You are talking about your OSGi application and Eclipse. Are you using Eclipse as an IDE to run your application or you have standalone OSGi application running in equinox?
In general the answer to your question is that if you need to have system variables for proxy e.g. http.proxyHost and http.proxyPort you will need to find out if you really need this bundle "org.eclipse.core.net".
If you do not need it just remove it from your launch configuration and the proxy settings will not be overwritten. If this is not possible try to configure it using the file you've mentioned "org.eclipse.core.net.prefs" or even better you can do it programmatically using org.eclipse.core.net.proxy package services.

Categories