I followed this Tutorial:
As init.d service
The executable jar has the usual start, stop, restart, and status
commands. It will also set up a PID file in the usual /var/run
directory and logging in the usual /var/log directory by default.
You just need to symlink your jar into /etc/init.d like so
Assuming that you have a Spring Boot application installed in
/var/myapp, to install a Spring Boot application as an init.d service
simply create a symlink:
$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp
Then start the Service with:
/etc/init.d/myapp start
When I do this exactly like it is described there, I get following error in the Ubuntu 14.04 console:
ubuntu#spring:/var/myapp$ /etc/init.d/myapp start
-bash: /etc/init.d/myapp: cannot execute binary file: Exec format error
You can't run a jar this way, since it's just a binary file. You have to run it with the installed java (as it's mentioned in the MrPsion's answer)
java -jar /var/myapp/myapp.jar
But you can't create a symlink to such a command. You can create a bash script, with the command above, make it executable and create a symlink to this script.
Alternatively, in Ubuntu you may use a binfmt-support. Just install it first
sudo apt-get install binfmt-support
Then make your jar executable
chmod a+x myapp.jar
And then you can run it (and use for the symlink) just as:
/var/myapp/myapp.jar
Update:
Since you have a Spring Boot application, check whether your jar is build with the executable property set to true
springBoot {
executable = true
}
This should let you run your jar the way you wanted, whitout make it an executable or require any additional libraries.
One more, according to the comments, the plugin version you're using doesn't support this feature yet. You have to update a plugin version in order to get an executable jar. According to the plugin sources and commit history you need atleast 1.3 version
The answers are incorrect, you can indeed launch a spring boot application jar as a service with init.d. There is even a spring tutorial explaining how to do it, as pointed out by Stanislav: https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html
The problem was probably in your maven file. I had the same issue and solved it adding the following to my maven file:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.7.RELEASE</version>
<configuration>
<executable>true</executable>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
Detailed instructions here: https://springjavatricks.blogspot.com/2017/11/installing-spring-boot-services-in.html
You need to "execute" the jar using java
java -jar /var/myapp/myapp.jar
and init scripts are not generally links to executable.
This post will show you how to create an init script for java applications.
Run a Java Application as a Service on Linux
Related
I've recently moved to Java 17 and with it came a couple restrictions requiring me to use --add-opens because of one dependency when running my application.
I need to add this when the java -jar command is ran. For now I found these solutions:
I can add it to the command line argument in my Dockerfile that runs the project
java --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/sun.util.calendar=ALL-UNNAMED -jar my.jar
I can add it in my MANIFEST.MF through my maven pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Add-Opens>java.base/sun.util.calendar java.base/java.util</Add-Opens>
</manifestEntries>
</archive>
</configuration>
</plugin>
Both work fine for production apparently. However when running my app through IntelliJ, it's not picking up the options which is normal I guess. I have to set them in my run configuration (which is also committed to my project by the way) as VM arguments.
I'm looking for a way to ensure consistency automatically and not have to maintain in parallel two places where I declare my add-opens.
EDIT: I'm wondering if something is doable with argfiles. Like have an argfile inside my project that would be referenced in the jar and that could be referenced in an y run configuration. I haven't found much evidence yet but that's the path I'm currently pursuing.
EDIT 2: I added an addopens file at the root of my project and can now reference this from the various points where I need it. For tests, I added this and it worked out of the box with IntelliJ tests AND maven tests together:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- This adds the options contained in the addopens file to the test JVM arguments -->
<argLine>#addopens #{argLine}</argLine>
</configuration>
</plugin>
I also can ship that addopens file in my docker to use in production. I still need to add to my Run configuration in IntteliJ the #addopens manually.
You can use the option to add the JDK parameters in the maven plugins like surefire plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>
--add-opens java.base/java.time=ALL-UNNAMED
${surefireArgLine}
</argLine>
</configuration>
</plugin>
I have tried the above approach for IntelliJ IDE and Java 17 (Temurin-17.0.1). It works fine on running via java -jar command, as well as on running the app via IDE.
If you have multiple such JVM options to add, try keeping those assigned to a property and use that property here in the argLine.
Follow steps: edit run/debug configuration -> add the below option in VM options:
--add-opens java.base/java.lang=ALL-UNNAMED
I can make the Azure ops pipeline but my question is I have checkedin my code into repository where we should not checkin the application property file.
That means on the deployment time i should have to download the application property file from some secure place and build my spring boot app before i deploy into app engine right.
So, what i did so far is, I downloaded my application property file into azure agent at run time. I passed the property file into maven build command but it did not work out. [Note: I already searched a lot read a lot of answers and applied as well but nothing worked]
Command line I used:
mvn -f myapp-springboot-api/pom.xml
-Dspring-boot.run.jvmArguments="-Dspring.config.location=file:/home/username/application.properties"
clean package appengine:deploy
I also tried with
mvn -f myapp-springboot-api/pom.xml
--spring.config.location=file:/home/username/application.properties
clean package appengine:deploy
This also did not workout.
Also, I tried passing the whole property file location via pom.xml
pom.xml changes:
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>1.1.1.RELEASE</spring-cloud.version>
<property.file.location>${property.file.location}</property.file.location>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-1</version>
<configuration>
<files>
<file>${property.file.location}</file>
</files>
</configuration>
</plugins>
</build>
Than I tried to build with:
mvn -f myapp-springboot-api/pom.xml
-Dproperty.file.location="/home/username/application.properties" clean package appengine:deploy
Than also I was not able to load the define external property file.
Thanks in advance, please help your help is highly appreciated.
The commands you are using won't actually pass the external properties files to the application engine (As it exists on a different server) and would only be scoped to the running maven process that is packaging + deploying.
So if you have copied your property file onto the external agent before building I would just replace the default one you have checked into source control.
So your build steps would be for example:
Download property file
Overlay:
mv /home/username/application.properties myapp-springboot-api/src/main/resources/application.properties
Build + Deploy
mvn -f myapp-springboot-api/pom.xml clean package appengine:deploy
So now your compiled and deployed jar file would include your new properties file, an alternative that recently came out would be to use something like Azure App Configuration.
If you want to not have to do another command you could also use the Maven Resources Plugin to perform the copy for you.
Simple as that, I am trying to deploy this app https://github.com/pac4j/spark-pac4j-demo to my heroku instance.
I can run it locally with: mvn compile exec:java
But on heroku, there is no maven installed:
2016-04-12T18:34:21.074629+00:00 heroku[web.1]: Starting process with command `mvn compile exec:java`
2016-04-12T18:34:23.303776+00:00 app[web.1]: bash: mvn: command not found
2016-04-12T18:34:23.303620+00:00 app[web.1]: Setting JAVA_TOOL_OPTIONS defaults based on dyno size. Custom settings will override them.
I have no clue how to set all the class paths per hand. I would appreciate some help here.
You'll first need to vendor your dependencies (i.e. copy them into the target/ directory). You can do so by adding this to your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals><goal>copy-dependencies</goal></goals>
</execution>
</executions>
</plugin>
Then the correct command to run the app will probably be something like java -cp target/classes:target/dependency/* Main (where Main should be replaced with your class that contains the public static void main method).
Here is a sample app using Spark so you can see how this all comes together.
Maven is not a good way to run an application in production. It creates an additional dependency for your app and adds layers of indirection to the process execution.
i´m new around here, so i will try to ask in the right way ;)
I´m doing an app on facebook, and i´m using jetty, here is the guide that i´m using : Heroku jetty deploy guide. In this guide, the way to start jetty it´s this:
java -jar jetty-runner.jar application.war
and this is exactly the same way recomended for the jetty howto guide:
java -jar jetty-runner.jar my.war
So i believe that until here, i´m doing everything fine. The war it´s an application that i´m developing, and the jetty runner jar i obtained through maven, here the tags of my pom.xml, extracted from the heroku guide:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-runner</artifactId>
<version>8.1.12.v20130726</version>
<destFileName>jetty-runner.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
So, the reason that i´m asking here, it´s that i can´t start jetty neither from command line nor in a remote way (through a deploy on heroku). The error i get, when i execute (with master admin privileges in windows 7) java jar jetty-runner.jar my.war is the following:
Failed to load Main-Class manifest attribute from jetty-runner.jar
And i don´t understand this, i´m using the jar downloaded through maven, it´s supose to work in the right way, right?
I open the manifest of the jetty-runer.jar and it doesnt have a Main-class attribute, so? what should i do? I believe that i´m doing something really stupid because i can´t find this error anywhere, but i don´t know what :D
Latest versions of jetty-runner in maven central seem to miss Main-Class attribute in jar manifest for some reason. However you can run it manually specifying main class:
java -cp jetty-runner.jar org.eclipse.jetty.runner.Runner application.war
You could try a different version. I have an old one (7.5.4.v20111024), and it does have the Main-Class attribute in the manifest, and works as expected at the command line.
The latest version, 8.1.14.v20131031 also has the Main-Class attribute.
Thanks for this question.
I was having the same problem trying to deploy the war file with jetty-runner on Heroku.
The pom.xml setting that Heroku suggests doesn't seem to pull the jetty-runner.jar with the main class attribute and increasing the version number didn't work either.
However, downloading the latest version of jetty-runner from maven repository directly and running it as java -jar jettty-runner.jar myapp.war worked for me.
This is my first time using maven on a project. Basically, I am working in the src on a webapp and when I am ready to push a change to the target i do a mvn clean install (this was what I was told to do).
The issue is that if I am just making a minor html tweak in a jsp and want to see the results I have to wait for tests, compile copy the war over deploy, server restart and then I have to log in again.
There's got to be a better way to do this. It's making my development speed slow to a crawl.
You can use maven tomcat plugin to run an in-memory tomcat over your maven project. Any jsp or static resource changes will apply immediately. Java code changes still require you to manually stop and start the server.
To do so use following maven goal
mvn clean tomcat:run
One other choice is jetty plugin. add jetty plugin to pom.xml,and run,that's ok.
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.11.v20130520</version>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<contextPath>/</contextPath>
</configuration>
</plugin>
</plugins>
</build>
run your application:
mvn jetty:run