Sprint-boot executable same sources multiple jars - spring-boot

I did the following steps in order to run 2 instances of my spring-boot application on the same host:
build jar with spring-boot maven plugin repackage goal
copy application.jar to application-0.jar on my remote server
created a application-0.conf file with APP_NAME=application-0
start application-0.jar as a service
copy application.jar to application-1.jar on my remote server
created a application-1.conf file with APP_NAME=application-1
start application-1.jar as a service
Then I got the following error upon application-1 start: service application already provided!
So I realized that:
linux service name is hard coded in the jar so no matter how many times you copy the jar en rename it, the service will remain the same (in our case application service)
APP_NAME has no effect on the service name. The APP_NAME in the .conf files were respectively set to application-0 and application-1. I still got the issue.
I read the spring-boot plugin documentation and tried an unsuccessful compination of attach, classifier and embeddedLaunchScriptProperties.initInfoProvides options on different spring-boot maven plugin executions of the same build.
I also tried to encapsulate different executions on separate maven profiles. I still got one original jar file and one single spring-boot jar.
So if anyone knows how to achieve my goal (same source, multiple well configured linux services since I run on the same host) I would really appreciate the help.
Below an example of unsuccessful configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>classic</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<executable>true</executable>
</configuration>
</execution>
<execution>
<id>instance-0</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<finalName>${project.artifactId}-0</finalName>
<executable>true</executable>
<classifier>exec</classifier>
<attach>false</attach>
</configuration>
</execution>
<execution>
<id>instance-1</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<finalName>${project.artifactId}-1</finalName>
<executable>true</executable>
<classifier>exec</classifier>
<attach>false</attach>
</configuration>
</execution>
</executions>
</plugin>
Thank you

I solved the issue by using systemd:
build single executable jar (no multiple spring boot plugin execution, no maven profile, just regular repackage executable goal)
make it available at an absolute path (/var/xxx/application.jar)
create any /etc/systemd/system/application-{i}.service you wish with the following config
[Unit]
Description=application-{i}
After=syslog.target
[Service]
ExecStart=/var/xxx/application.jar --server.port=4500{i} -- logging.file=/var/log/xxx/application-{i}.log
[Install]
WantedBy=multi-user.target
Note the place holders {i} to avoid conflicts on service name, linstening ports and log file.
Systemd solved my issue.
Note: you are only concerned with my issue if you run same instances of your service on the same host. All this config is not needed if you run one service instance per host (common microservice approach).
Hope this helps anyone with the same issue.

Related

How to specify WARs built in another project for integration test using tomcat8-maven-plugin? [duplicate]

This question already has answers here:
Maven deploy multiple wars to embedded server for integration tests
(2 answers)
Closed 3 years ago.
I have two applications (Maven 'war' artifact), let's call them Api and Ui.
I want to setup a fully automated integration test that fires up Api and Ui locally before executing integration tests.
The applications are losely-coupled and so I don't want to introduce any dependency on Api in Uis build or vice-versa.
So I want to setup a third project, IntegratedQA which will have dependencies on both apps.
My initial POM contains:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat8-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/</path>
</configuration>
<executions>
<execution>
<id>start-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<fork>true</fork>
</configuration>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
</plugin>
My question is... How exactly do I tell tomcat to launch Api.war and Ui.war, which are built in separate projects?
Using tomcat7-maven-plugin you can customize the tomcat7:deploy to provide the war files path to deploy into tomcat environment.
browse this link for the documentation.
Linking another stackoverflow answer where it is specified how it will work with tomcat 8 or 9
Jenkins deploy war file to Tomcat 8

How to stop Maven Execution

I have a mock server which I need to start in Jenkins before running my Automation tests and then stop the mock server after my tests have run.
This mock server is a maven project and is using exec-maven-plugin. I am able to start this server by running the command mvn exec:java. However I am unable to stop this maven project through Jenkins. I have read about it and most answers tell to find the Process ID of this Maven project and then kill it. Is there a cleaner and easier way to stop this project ?
You need to start and stop your sever using goals which are part of the maven life cycle.
An example taken from this answer
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>tomcat-run</id>
<goals>
<goal>run-war-only</goal>
</goals>
<phase>pre-integration-test</phase>
<configuration>
<fork>true</fork>
</configuration>
</execution>
<execution>
<id>tomcat-shutdown</id>
<goals>
<goal>shutdown</goal>
</goals>
<phase>post-integration-test</phase>
</execution>
</executions>
</plugin>
The key to this issue is indeed that you don't know the processId. Consider using exec:exec instead with async. You'll see that asyncDestroyOnShutdown is set to true by default, meaning it'll shut down once Maven is shutting down.
If you are running linux:
ps aux |grep <project-name> and then kill -9 <process id>

How to setup a Java agent in a Spring boot app deployed in PCF cloud

I have a Spring boot app deployed into PCF cloud. I need to setup a Java agent on it. How do I give the JVM options? How to include the agent jar in the deployed jar file? I use Maven to build.
You will have to pass the JVM options as env settings in the application manifest file.
This link provides details on manifest options
- https://docs.cloudfoundry.org/devguide/deploy-apps/manifest.html
And here's an article that has tips for java developers. It has examples on setting memory and other settings for java app.
- https://docs.cloudfoundry.org/buildpacks/java/java-tips.html
To run a spring boot app with a javagent use following jvm option.
-javaagent:<name-of-the-jar>
Use following plugin in your maven project to copy agent jar file on compile.
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<id>copy</id>
<phase>compile</phase>
<configuration>
<tasks>
<copy file="${basedir}/src/path-to-jar" tofile="${basedir}/target/jar-file"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

How to restart JBoss with maven-as plugin before redeploy

I am having headaches trying to setup maven-as-plugin.
My goal is to redeploy an ear before running integration tests.
I want this process to be automatic to integrate it into CI.
The server is a JBoss server (AS 7) running remotely.
Thanks to infamous PermGen space issues of Jboss, I need to restart the server before
deploying the ear. Otherwise, the server will explode every 5 runs or so ...
For that purpose, I have tried to setup a goal "shutdown", with reload=true.
The issue is that maven plugin won't wait for it to be finished before running the next goal (cleaning previous artifacts).
Here is an excerpt of my POM :
<!-- Jboss Deploy/undeploy application EAR -->
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.5.Final</version>
<configuration>
<!-- JBoss management -->
<hostname>${sanity.tests.jboss.host}</hostname>
<port>${sanity.tests.management.port}</port>
<username>${sanity.tests.jboss.username}</username>
<password>${sanity.tests.management.password}</password>
</configuration>
<executions>
<!-- Reload Jboss to avoid permgen space -->
<execution>
<id>restart</id>
<phase>pre-integration-test</phase>
<goals><goal>shutdown</goal></goals>
<configuration>
<reload>true</reload>
</configuration>
</execution>
<!-- Undeploy previous ear -->
<execution>
<id>undeploy</id>
<phase>pre-integration-test</phase>
<!-- Cleanup : Undeploy -->
<goals>
<goal>undeploy</goal>
</goals>
<configuration>
<matchPattern>rm-app.*.ear</matchPattern>
<ignoreMissingDeployment>true</ignoreMissingDeployment>
</configuration>
</execution>
<!-- Deploy before int test -->
<execution>
<id>deploy</id>
<phase>pre-integration-test</phase>
<goals>
<goal>deploy-artifact</goal>
</goals>
<configuration>
<name>xxxx</name>
<groupId>xxxxx</groupId>
<artifactId>xxxx</artifactId>
<version>${project.version}</version>
</configuration>
</execution>
</executions>
</plugin>
Any help would be much appreciated.
Try running your undeploy first. If that's the only ear on the AS then the reload will most likely be quick enough for the deploy goal to not timeout.
<goals>
<goal>undeploy</goal>
<goal>shutdown</goal>
<goal>deploy</goal>
</goals>
Unfortunately, I do not know how to increase the timeout of the deploy goal.
I had exactly the same issue. switangs suggestion (first undeploy before restarting JBoss) for sure helps. Another thing i did to add some time between server restart and redeployment was to bind the undeploy and restart of the server to a very early step of the build process (e.g. initialize), whereas the deployment step was bind to process-resources or pre-integration-test as in your case. That worked because i was deploying my artifacts in a separate integration test module, which first copied all relevant server artifacts with maven-dependency-plugin plugin to the ${project.build.directory}/dependency folder as one of the first steps.
But i agree that this is not a very good solution, a blocking restart cli command for standalone JBoss nodes would be much better.
In fact, the shutdown goal won't solve the PermGen issue.
I worked this out by use cli.
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.5.Final</version>
<configuration>
<afterDeployment>
<commands>
<command>/host=master:shutdown(restart=true)</command>
</commands>
</afterDeployment>
<!-- your configuration -->
...
</configuration>
<plugin>
and "master" is the name of host in domain mode.

maven-install-plugin: Can i define a custom packaging type but get the artifact installed as jar in the repo?

I am trying to come out with a plugin to detect and process Java EE application clients.
I created a new packaging type called 'car' through META-INF/plexus/components.xml (http://maven-car-plugin.googlecode.com/svn/trunk/maven-car-plugin/src/main/resources/META-INF/plexus/components.xml) and a corresponding mojo for Java EE app clients. I have pretty much followed the same steps as the maven-ejb-plugin.
The behaviour i want is the same as the maven-ejb-plugin: Defines an ejb packaging type but the artifact gets installed in the repo as a .jar and gets bundled in the ear as .jar too.
I believe must be configurable some how because ejb packaging type gets installed as .jar but war packaging type produces a .war.
The problem in my case is that a .car file gets installed in the repo and a .car file gets bundled in the ear.
Does anyone know how to make sure it gets installed in the repo as a .jar file?
I ran into the same issue you have, except, I'm building a .war file and wanted a .jar file installed into my local repo. What I did was use the maven-jar-plugin to create a jar file in addition to a war file, it's generated in my /target directory. I also used the maven-install-plugin to install the outputted jar to my local repo.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>make-jar</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<id>install-jar</id>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<packaging>jar</packaging>
<artifactId>${project.artifactId}</artifactId>
<groupId>${project.groupId}</groupId>
<version>${project.version}</version>
<file>${project.build.directory}/${project.artifactId}.jar</file>
</configuration>
</execution>
</executions>
</plugin>
Perhaps you could try using the packaging parameter in maven install plugin to see if that helps in your case?
I would assume you would have to specify
<packaging>jar</packaging>
as well in the component descriptor. Otherwise it looks correct to me..

Resources