We have executable spring boot jars. Some environment variables are provided via the runtime account's .bashrc , including SPRING_PROFILES_ACTIVE . This is set at runtime through checking some system parameters.
In order to enable a truly portable application, we would like to set these variables inside a custom version of the Spring Boot executable launch script (launch.script) instead of relying upon a custom .bashrc being deployed somewhere.
i.e. the launch script runs the custom shell code that is currently in our bashrc .
We could then throw the Spring Boot executable jar on one of our boxes without having to deploy the custom .bashrc .
We have copied the default Spring Boot launch.script and prepended setting our environment variables. We replace the default script with our custom one by using the spring-boot-maven-plugin. Using echo statements, we know that the new launch.script replaces the default one.
One environment variable we are setting dynamically is SPRING_PROFILES_ACTIVE . Through an echo statement, I know that the variable is being set correctly inside of our custom launch.script. However, that value is not being propagated to the application. i.e. the spring profile at application startup is always 'default', versus L0, L1 or whatever we're trying to set.
I have exported the variable using export and declare -x .
Is what we are doing at all feasible, or is setting SPRING_PROFILES_ACTIVE in the launch.script too late ?
In the snapshot version(2.0.0.M7) there is a new property substitution named inlinedConfScript, we can use this feature to set some environment variables before application startup.
The <build> setting in pom.xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<embeddedLaunchScriptProperties>
<inlinedConfScript>${project.basedir}/my.script</inlinedConfScript>
</embeddedLaunchScriptProperties>
</configuration>
</plugin>
</plugins>
</build>
Create my.script in the the same directory of the project's pom.xml
export SPRING_PROFILES_ACTIVE=production
Related
I am trying to run a Spring boot application on my local machine. When I use the following syntax for a property it resolves well:
username: ${project.db.user}
However the following raises an exception:
username: ${PROJECT_DB_USER}
Is there any way to use uppercase here? My CI/CD pipelines defines all its variables with uppercase
I've had similar problems, and from what I've understood, since springBoot v2.1, the application.properties files don't handle environement variables well. The solution is to use Spring Profiles.
You need to add as many .properties files as you have environments, like so :
application.properties
application-staging.properties
application-prod.properties
If you have a staging and prod profiles. The .properties of the profile overrides the basic application.properties, so be sure not to forget anything in each file !
There may be other solutions as well.
You can set the profiles using various methods, in Spring boot, with Maven (sorry, the only one I'm familiar with) you can simply add it to the pom.xml like this :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<profile>staging</profile>
</profiles>
</configuration>
</plugin>
According to the Spring boot documentation, it's possible to define additional command when using a remote shell based on Crash.
Default locations for these commands are classpath*:/commands/,classpath*:/crash/commands/
A property can be used to override the default locations but in the provided example, the custom command is located in resources.
In my opinion, custom commands (at least java commands) shouldn't be located in resources but in src/main/java.
It works fine when defining a custom path in resources but how can I define a custom path in src/main/java? Didn't find a way to do it for now!
If they're under src/main/java, they'll be compiled automatically which is not what you need. My solution was to simulate that directory as a resources folder, which in short translates to:
configure the compiler plugin to ignore that particular folder
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<excludes>
<exclude>crash/commands/*</exclude>
</excludes>
</configuration>
</plugin>
copy the files just like any regular resources in the target directory
<resource>
<directory>src/main/java/crash/commands</directory>
<targetPath>crash/commands</targetPath>
<filtering>false</filtering>
</resource>
Minor update & disclaimer:
As you may already know, there are a couple of closures which are executed on login/logout. At least with v1.3.1, which is what I'm blindly inheriting from spring-boot, it will pick the first login.groovy it finds in the classpath. My project's artifact is packaged in an RPM along with all the other dependencies. Since its name begins with r, it comes after crash.shell-1.3.1.jar which is where the defaults reside, so I had to do the following small hack to make it pick up my own scripts instead of the default ones:
<!-- hack to make CRaSH pick up login.groovy from our jar instead of the default one -->
<finalName>0_${project.artifactId}-${project.version}</finalName>
You can try to put your command at src/main/resources/commands/
Following is the error log I'm getting:
I'm using
wrapper-windows-x86-32-3.5.25-pro
in order to make my already developed application in Spring-boot. I wanted to execute this application as a windows service but I'm not.
This problem is specific to Tanukisoftware as I'm unable to configure it.
PFB the configuration I'm using for setting up the class path here:
wrapper.java.classpath.1=../lib/wrappertest.jar
wrapper.java.classpath.2=../lib/wrapper.jar
wrapper.java.classpath.3=../lib/slf4j-api-1.7.5
wrapper.java.classpath.4=../lib/myApp.jar
even if myApp.jar contains the slf4j classpath already and its running already. I think this is library specific problem and its not finding up the classpath even if I explicitly set it like did above.
Can you please let me know how it can be solved?
Did you try building a fat jar of your application ? You can add following lines to your Spring Boot project's pom.xml to repackage jar file:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Besides, your following property line seems invalid:
wrapper.java.classpath.3=../lib/slf4j-api-1.7.5
Is it pointing a jar file actually ?
slf4j-api-1.7.5 should have a .jar extension. That is possibly confusing things.
Also, even just as a debugging step, try running your Windows service using Apache ProcRun to see if your results are any different.
Maven Jetty plugin is very nice (I'm using version 6.1.26). The only annoying thing concerns static files' modifications.
My web application uses Spring, follows the standard webapp Maven layout and I basically do not want the whole context to be reloaded whenever I change a JSP or a CSS file.
I checked the configuration settings, but didn't find anything about this.
Any idea ?
Thanks in advance !
Rolf
You can set manual reload and:
Your IDE (i.e. Eclipse) will copy static resources to target directory so they will be updated transparently.
When you make changes in Java classes you only need to hit enter in the jetty process to reload.
To set manual reloading:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.26</version>
<configuration>
<reload>manual</reload>
</configuration>
</plugin>
I understand your need about CSS files or maybe html files, but take care, JSP files are actually Servlets. And a Servlet has to be undeployed in a way or another before reloading it.
Set scanIntervalSeconds to -1
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
from http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin :
scanIntervalSeconds Optional. The pause in seconds between sweeps of the webapp to check for changes and automatically hot redeploy if any are detected. By default this is 0, which disables hot deployment scanning. A number greater than 0 enables it.
I've ported a project from Eclipse to Maven and I need to set an environment variable to make my project work.
In Eclipse, I go to "Run -> Run configurations" and, under the tab "environment", I set "WSNSHELL_HOME" to the value "conf".
How can I do this with Maven?
You can just pass it on the command line, as
mvn -DmyVariable=someValue install
[Update] Note that the order of parameters is significant - you need to specify any options before the command(s).[/Update]
Within the POM file, you may refer to system variables (specified on the command line, or in the pom) as ${myVariable}, and environment variables as ${env.myVariable}. (Thanks to commenters for the correction.)
Update2
OK, so you want to pass your system variable to your tests. If - as I assume - you use the Surefire plugin for testing, the best is to specify the needed system variable(s) within the pom, in your plugins section, e.g.
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
...
<configuration>
...
<systemPropertyVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</systemPropertyVariables>
</configuration>
</plugin>
...
</plugins>
</build>
The -D properties will not be reliable propagated from the surefire-pluging to your test (I do not know why it works with eclipse). When using maven on the command line use the argLine property to wrap your property. This will pass them to your test
mvn -DargLine="-DWSNSHELL_HOME=conf" test
Use System.getProperty to read the value in your code. Have a look to this post about the difference of System.getenv and Sytem.getProperty.
You could wrap your maven command in a bash script:
#!/bin/bash
export YOUR_VAR=thevalue
mvn test
unset YOUR_VAR
For environment variable in Maven, you can set below.
http://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#environmentVariables
http://maven.apache.org/surefire/maven-failsafe-plugin/integration-test-mojo.html#environmentVariables
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
...
<configuration>
<includes>
...
</includes>
<environmentVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</environmentVariables>
</configuration>
</plugin>
Following documentation from #Kevin's answer the below one worked for me for setting environment variable with maven sure-fire plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<environmentVariables>
<WSNSHELL_HOME>conf</WSNSHELL_HOME>
</environmentVariables>
</configuration>
</plugin>
Another solution would be to set MAVEN_OPTS (or other environment variables) in ${user.home}/.mavenrc (or %HOME%\mavenrc_pre.bat on windows).
Since Maven 3.3.1 there are new possibilities to set mvn command line parameters, if this is what you actually want:
${maven.projectBasedir}/.mvn/maven.config
${maven.projectBasedir}/.mvn/jvm.config
There is a maven plugin called properties-maven-plugin this one provides a goal set-system-properties to set system variables. This is especially useful if you have a file containing all these properties. So you're able to read a property file and set them as system variable.
in your code add:
System.getProperty("WSNSHELL_HOME")
Modify or add value property from maven command:
mvn clean test -DargLine=-DWSNSHELL_HOME=yourvalue
If you want to run it in Eclipse, add VM arguments in your Debug/Run configurations
Go to Run -> Run configurations
Select Tab Arguments
Add in section VM Arguments
-DWSNSHELL_HOME=yourvalue
you don't need to modify the POM
You can pass some of the arguments through the _JAVA_OPTIONS variable.
For example, define a variable for maven proxy flags like this:
_JAVA_OPTIONS="-Dhttp.proxyHost=$http_proxy_host -Dhttp.proxyPort=$http_proxy_port -Dhttps.proxyHost=$https_proxy_host -Dhttps.proxyPort=$http_proxy_port"
And then use mvn clean install (it will automatically pick up _JAVA_OPTIONS).
I suggest using the amazing tool direnv. With it you can inject environment variables once you cd into the project. These steps worked for me:
.envrc file
source_up
dotenv
.env file
_JAVA_OPTIONS="-DYourEnvHere=123"
As someone might end up here changing his global Java options, I want to say defining _JAVA_OPTIONS is a bad idea. Instead define MAVEN_OPTS environment variable which will still be picked up automatically by Maven but it won't override everything like _JAVA_OPTS will do (e.g. IDE vm options).
MAVEN_OPTS="-DmyVariable=someValue"