06 May 2018 | tags: Jenkins CI Maven
In one of my ${personalProject}s, I had to deal with the old Apache XMLRPC library. In fact, what’s old is the XMLRPC itself, not the Apache implementation. To force the purge of the local repository:
mvn dependency:purge-local-repository
17 Mar 2018 | tags: Jenkins CI Spring Boot Maven
In ${personalProject} I need to be able to change among Spring Boot Profiles at build time. This is because I do want to mess up with Tomcat at all, I just simply want to have a Tomcat setup as close as its original setup as possible.
I could use JAVA_OPTS
environment variable, for example. But that forces me to change the startup.sh
script or any other mechanism so that Tomcat finds the right profile to use.
Another option would be to run the multiple webapps (my app consists of multiple war components) passing the -Dspring.boot.profile
, again that forces me to change things in the Tomcat setup.
However, another option is to change the main application.yml
(or application.properties
) at build time. That way the CI/CD Jenkins can choose the profile when building. But I want that to happen without using more tools than the ones I’m using right now. Also, I want to be sure the pipeline works regardless the OS used in the CI/CD, in production or locally (I have a mixture of OSs here, production is still Linux, CI/CD is FreeBSD and local is MacOS).
To do so, I decided to use maven profiles to do that. That way it’d be just a matter of telling Maven which profile to use. The problem here is that maven profiles and Spring Boot profiles are different things.
Now we need is to tell Maven what profiles we have. In the pom.xml
we need to define the profiles we have. For each profile, the variable springProfile
will have a different value. In the main block we need to add something like this:
<profiles>
<profile>
<id>local</id>
<properties>
<springProfile>local</springProfile>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>dev</id>
<properties>
<springProfile>dev</springProfile>
</properties>
</profile>
<profile>
<id>production</id>
<properties>
<springProfile>production</springProfile>
</properties>
</profile>
</profiles>
Pay attention to two things:
- The
springProfile
tag will be used later. You can choose any name you want here, but later you need to use the same.
- The
activeByDefault
profile is the one that will be used by Maven as the default profile if none is passed to Maven with the -Pprofile
flag. Don’t use production because you may end up messing with your production environment, depending on what you are trying to do.
Next, we need to define a placeholder in the application.yml
that will be replaced as the variable springProfile
selected by the the active maven profile. In that file, put something like this:
spring.profiles.active: @springProfile@ # local dev production
Note that the placeholder variable is the one used in the pom file before. They have to match.
Right now you have a placeholder, the only thing missing is to tell Maven to replace the placeholder with the choosen profile with mvn -Pblah
.
Now, under the build
tag in the pom file, you need to add this:
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
...
</plugins>
This one is needed to tell Maven the delimiter being used in the placeholder variable.
Finally, you need to use the resource maven plugin to replace the appearances of @springProfile@
under certain directories. You need to add this:
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
That applies filtering to files under the src/main/resources
directory. So, to recap, depending on the Maven profile passed, Maven will expose the springProfile
variable with different values, that will be picked by the resource plugin that would replace the placeholder using the delimiter configured in the <plugin>
block. So at the end, in the application.dev
we’d have this:
spring.profiles.active: dev # local dev production
References:
- https://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html
22 Nov 2017 | tags: Bash Shell script IPC
At ${work}, again I needed to run a batch of commands and actions multiple times.
Like in a previous post, I have a loop that triggers a lot of actions, using a lot of functions and using many variables, the executing in serial and taking a lot of time. However, the actions do not interfere, running in parallel would save a lot of time in a multicore machine.
Using parallel
is out of scope because the subprocesses will not see the function definitions unless I export them all. Even though all the variables need to be exported: painful and dirty.
On the other hand, I’ve been think on another way to do what I want. Maybe I could use use a named pipe as a locking mechanism. Imagine that I want to allow N processes to execute inside the loop. At the beginning the pipe is empty, so the controller would fill the pipe with as N characters as processes would be allowed to run. Then, then main loop will start spawning processes executing the commands I need to run (remember, the & and the parenthesis are your friends here).
So the controller will read a character from the pipe and then spawn a worker. The worker will do its work and once it finishes it will feed a character into the pipe.
If the pipe is not empty, another worker can execute, consuming a character. If the pipe is empty, no more workers can spawn until one of the running ones finishes.
At the end of the process, the pipe will have N characters on it (the initial N character will filled the pipe with).
WARNING
The pipe, by default, is ** BLOCKING ** . That means that the initial write will block, rendering the script useless. To avoid that, the pipe has to be opened RW. That is the purpose of the exec 3<>${TEMP_FIFO}, which is to use the third file descriptor (STDOUT is 0, IN is 1 and ERR is 2) and open it RW (<>).
if [ ! -e ${TEMP_FIFO} ]; then
mkfifo ${TEMP_FIFO}
exec 3<>${TEMP_FIFO}
fi
MAX_PROCESSES=25
TOTAL_JOBS=1500
for i in $(seq 1 ${MAX_PROCESSES}); do
echo -n "0" > ${TEMP_FIFO}
for i in $(seq 1 ${TOTAL_JOBS}); do
read -u 3 -N 1 x
(echo "Process $i sleeping"; sleep $[ $RANDOM % 5) +1 ]; echo -n 0 > ${TEMP_FIFO})&
done
read -u 3 -n MAX_PROCESSES x