Heroku unable to access jetty-runner jar file - java

I'm deploying a Spring MVC app to Heroku using jetty-runner.jar, but I get an error in the deployment.
The Heroku logs only show:
Error: unable to access jarfile target/dependency/jetty-runner.jar
State changed from starting to crashed
Process exited with status 1
However, the app is working correctly if I run it locally using either:
heroku local web -f Procfile.windows
or
java -jar target\dependency\jetty-runner.jar target\*.war
The file under "target/dependency/jetty-runner.jar" is created correctly in my computer when running the "mvn package" command.
My Procfile looks like this:
web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war
My pom.xml file and project code are located in:
https://github.com/gfigueroa/nlp-tools-spring-heroku
ADDITIONAL DETAILS
I ran the command heroku run ls target after deploying and it only shows the .war file. The dependency folder was not created when deploying, even though it was when I packaged my project locally.

Your maven-clean-plugin is deleting the jar file in dependency directory and other required directories when you try to build your app on Heroku.
You can either remove the maven-clean-plugin in the pom.xml or you can modify it.
Best option is to remove the plugin below in pom.xml
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>clean-jar-artifacts</id>
<phase>install</phase>
<goals><goal>clean</goal></goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>target</directory>
<excludes>
<exclude>*.war</exclude>
</excludes>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
Or you can exclude the dependency/*.jar from deleting by simply adding the <exclude>..</exclude> tags as specified below. But this option might delete other required folders which are necessary for deploying the app successfully. So I would not recommend this.
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>clean-jar-artifacts</id>
<phase>install</phase>
<goals>
<goal>clean</goal>
</goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>target</directory>
<excludes>
<exclude>*.war</exclude>
<exclude>dependency/*.jar</exclude>
</excludes>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
Look at this page for more information.

I had the similar problem , until I add into pom.xml file with latest jetty-runner (org.eclipse.jetty)
<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.eclipse.jetty</groupId>
<artifactId>jetty-runner</artifactId>
<version>9.4.4.v20170414</version>
<destFileName>jetty-runner.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Procfile contains only:
web: java $JAVA_OPTS -jar target/dependency/jetty-runner.jar --port $PORT target/*.war

Related

Copy file to jar root when building spring-boot project with Maven

I have a Spring Boot project and I'm building the jar file with mvn clean build.
I need to copy a folder and a file to the root of the jar, where META-INF is located. I tried maven-resources-plugin but I can't reach my goal.
For war files I used maven-war-plugin in the past but I can't find something similar for jars.
Can anybody give me an idea?
Thanks.
I could manage to add files after the repackage goal of the spring-boot-maven-plugin using the maven-antrun-plugin and the Jar tool included in the JDK.
Updating a JAR File
The Jar tool provides a u option which you can use to update the contents of an existing JAR file by modifying its manifest or by adding files.
The basic command for adding files has this format:
jar uf jar-file input-file(s)
https://docs.oracle.com/javase/tutorial/deployment/jar/update.html
Using Maven-Antrun-Plugin
This command can be executed using the maven-antrun-plugin together with the exec task, which allows you to execute commands via Runtime.exec(..).
The entry may look like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>package</phase>
<configuration>
<target>
<exec executable="jar" vmlauncher="false">
<arg value="uf" />
<arg value="${project.build.directory}/myprogram.jar" />
<arg value="-C" />
<arg value="${project.build.directory}/classes" />
<arg value="org/company/app/Main.class" />
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Notice the -C option, which allows you to change the directory that should not be included in the jar.
https://maven.apache.org/plugins/maven-antrun-plugin/usage.html
https://ant.apache.org/manual/Tasks/exec.html
Using Exec-Maven-Plugin
Alternatively the exec-maven-plugin can be used which does not require Ant to be installed.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>jar</executable>
<arguments>
<argument>uf</argument>
<argument>${project.build.directory}/myprogram.jar</argument>
<argument>-C</argument>
<argument>${project.build.directory}/classes</argument>
<argument>org/company/app/Main.class</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
The final structure may look like this:
myprogram.jar
|-BOOT-INF/..
|-META-INF/..
|-org/springframework/boot/loader/..
|-org/company/app/Main.class
That way you can add any additional files you want after the jar has been packaged.
could something like the following help?
See also maven-jar-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<includes>
<include>**/cdi/*</include>
<include>**/META-INF/*</include>
<include>*.properties</include>
</includes>
</configuration>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
I resolved my problem by using the maven-assembly-plugin. I created an assembly zip which contains the application jar and some other resources.
This solution is specific for applications which use AWS Elastic Beanstalk and need to implement the Procfile (http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/java-se-platform.html#java-se-procfile).

Fitnesse error when used with spotify maven plugin and docker

I am using spotify maven plugin to create a fitnesse docker image and run it on a container. I am able to bring the fitnesse up and run the tests successfully locally without using spotify maven plugin and docker but not when I use those.
I get the following error when I start the fitnesse
Error message
Here is the contents of FrontPage fitnesse wiki which generally generally takes care of resolving dependencies as per http://blog.xebia.com/fitnesse-and-dependency-management-with-maven/
!contents
!define TEST_SYSTEM {slim}
!pomFile pom.xml
!note Release ${FITNESSE_VERSION}
Here is the contents of my pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadeTestJar>true</shadeTestJar>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>fitnesseMain.FitNesseMain</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<baseImage>${docker.registry.host.slash}mcpi/service</baseImage>
<entryPoint>["java","-jar","${serviceBin}/${finalJarName}.jar","-p","8000"]</entryPoint>
<imageName>mcpi/${project.name}</imageName>
<runs>
<run>mkdir -p ${serviceHome}</run>
</runs>
<workdir>${serviceHome}</workdir>
<resources>
<resource>
<targetPath>${serviceHome}</targetPath>
<directory>${basedir}/src/test/resources</directory>
</resource>
<resource>
<targetPath>${serviceBin}</targetPath>
<directory>${basedir}/target</directory>
<include>${finalJarName}.jar</include>
</resource>
<resource>
<targetPath>${serviceBin}</targetPath>
<directory>${basedir}/target</directory>
<include>${finalTestJarName}.jar</include>
</resource>
<resource>
<targetPath>${serviceBin}</targetPath>
<directory>${basedir}</directory>
<include>pom.xml</include>
</resource>
</resources>
</configuration>
</plugin>
I believe your problem might be that you don't include your maven settings and repository in the docker image, so the !pomFile does not work inside your docker image.
Having said that: you probably don't need it, since you bundle all your classes and dependencies (at least I assume that what the 'shade plugin' does for you). So you can probably disable the 'maven class path plugin, to prevent the problem you experience now. Disabling the maven classpath plugin can be done by adding -Dfitnesse.wikitext.widgets.MavenClasspathSymbolType.Disable=true to your Java command line starting FitNesse in docker (or by removing the line from the wiki page of course, but that impacts how you work locally).
But I don't know whether your tests will work immediately, or that you have to do something extra to ensure the generated 'final jar' is on the class path of the Java process that is started once an actual test is started (but you can try that locally by running with the !pomFile removed and starting from the jar created by the shade plugin).
Fitnesse was unable to parse pom.xml as maven is not set up in docker. Instead of !pomFile pom.xml in my fitnesse wiki, I used !path path/to/jars/*.jar.
Though above error was gone, maven-shade-plugin could not resolve all the dependencies like spring-test.
I had to add maven-dependency-plugin to pom.xml so that all the dependencies are resolved <plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/dependencies</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<excludeTransitive>true</excludeTransitive>
</configuration>
</execution>
</executions>
</plugin>
and moved those to docker using spotify docker-maven-plugin
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<baseImage>${docker.registry.host.slash}service</baseImage>
<entryPoint>["java","-jar","${serviceBin}/${finalJarName}.jar","-p","8000"]</entryPoint>
<imageName>mcpi/${project.name}</imageName>
<runs>
<run>mkdir -p ${serviceHome}</run>
</runs>
<workdir>${serviceHome}</workdir>
<resources>
<resource>
<targetPath>${serviceHome}</targetPath>
<directory>${basedir}/src/test/resources</directory>
</resource>
<resource>
<targetPath>${serviceBin}</targetPath>
<directory>${basedir}/target</directory>
<include>${finalJarName}.jar</include>
</resource>
<resource>
<targetPath>${serviceBin}</targetPath>
<directory>${basedir}/target</directory>
<include>${finalTestJarName}.jar</include>
</resource>
<resource>
<targetPath>${serviceBin}</targetPath>
<directory>${basedir}/target/dependencies</directory>
</resource>
</resources>
</configuration>
</plugin>

Deploying on Heroku Java app with Angular2 fronend

i was faced with a problem, during deploying Java based app with Angular 2 fronend.
My app needs to be installed with NodeJs and it's "npm install" to fetch all it's dependencies from package.json.
And only than with maven.
Angular2 app is located in java webapp folder.
I saw buildpacks to install it. But they dont work. For example
this one
https://github.com/Vincit/heroku-buildpack-java-nodejs
It searches for *.ts files in the root, but not in the "webapp" java folder.
Is there some smart buildpacks for task like that, or others convinient ways to do it simply?
Thank you in advance!
You can do this with Heroku's support for multiple buildpacks on an app. In short, run:
$ heroku buildpacks:clear
$ heroku buildpacks:add heroku/nodejs
$ heroku buildpacks:add heroku/java
In your case, the situation is probably very similar to this JHipster example, which uses Node.js and angular. There are a few things to consider:
The Heroku Node.js buildpack will not install devDependencies by default. You either need to move them to dependencies or set the config var NPM_CONFIG_PRODUCTION=false.
If you don't need your node_modules directory or Node.js runtime at runtime, it will make your app huge. You can use Maven to remove them.
Here's an example:
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>clean-build-artifacts</id>
<phase>install</phase>
<goals><goal>clean</goal></goals>
<configuration>
<excludeDefaultDirectories>true</excludeDefaultDirectories>
<filesets>
<fileset>
<directory>node_modules</directory>
</fileset>
<fileset>
<directory>.heroku/node</directory>
</fileset>
</filesets>
</configuration>
</execution>
</executions>
</plugin>
This is described in more detail in the JHipster post.
I use this plugin:
https://github.com/eirslett/frontend-maven-plugin
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v4.4.3</nodeVersion>
<npmVersion>3.8.3</npmVersion>
</configuration>
</execution>
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>--strict-ssl=false install</arguments>
</configuration>
</execution>
<execution>
<id>npm build prod</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build.prod</arguments>
</configuration>
</execution>
</executions>
</plugin>
npm build.prod is my gulp task to build for prod deployment and is specified as a script in my package.json (I'm using the angular 2 seed): https://github.com/mgechev/angular-seed
I had to create a task to copy to a place for my java app to use the files statically:
import * as gulp from 'gulp';
let gnf = require('gulp-npm-files');
let resourceDest = 'src/main/resources/public';
export = () => {
gulp.src('**', {cwd:'./dist/prod'}).pipe(gulp.dest(resourceDest));
gulp.src(gnf(), {base:'./'}).pipe(gulp.dest(resourceDest));
};
This copies my compiled angular 2 javascript into src/main/resources/public

cannot run npm grunt bower using maven

I have a simple web application that uses npm bower and grunt. I am using this project as a module in a maven project. I searched the internet and found how to define the pom.xml for the project but I am not able to run it. Can anyone tell me the steps on how to build and run the webapp using maven.
the pom.xml
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<id>exec-npm-install</id>
<phase>generate-sources</phase>
<configuration>
<executable>npm</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
<execution>
<id>exec-bower-install</id>
<phase>generate-sources</phase>
<configuration>
<executable>bower</executable>
<arguments>
<argument>install</argument>
</arguments>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
<execution>
<id>exec-grunt</id>
<phase>process-resources</phase>
<configuration>
<executable>grunt</executable>
</configuration>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The error that I am getting is
[ERROR] Command execution failed.
java.io.IOException: Cannot run program "C:\Program Files\nodejs\npm" (in directory "C:\Users\krs\IdeaProjects\project"): CreateProcess error=193, %1 is not a valid Win32
application
How to build and run this pom using maven ?
The reason why you can't run it is because it's not an executable, it's a batch file or shell script if you're not on windows.
You can still use maven exec plugin to run it. However to do that you'll have to feed the batch file npm to cmd program (or bash or whatever is your favorite shell).
Following is the change that you'll need to make.
Actual command to feed batch to cmd
cmd /c "npm --version"
Following is the change in the plugin configuration.
<configuration>
<executable>cmd</executable> <!-- or bash -->
<workingDirectory>./</workingDirectory>
<arguments>
<argument>/c</argument>
<argument>"npm --version"</argument>
</arguments>
</configuration>
This should work.

How to customize maven-java-doc plugin, that only changed java source code sections will be updated in the complete generated java docfiles?

I have a question concerning the Maven javadoc plugin in Apache Maven. My current configuration allows to create a complete new java doc of my maven project, if the install phase will be executed. If I called the command "mvn clean install", the java doc files will be deleted completly (to do this, I have customoized the Maven clean plugin). And during the install phase, the java doc files will be generated again!
Is there a way to customized the java doc plugin in that way, that only the changed java source code sections will be updated in the existing java doc? And not the complete java doc will be generated again?
My maven-javadoc-configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<noqualifier>all</noqualifier>
<reportOutputDirectory>myJavaDocOutputDirectory</reportOutputDirectory>
</configuration>
<executions>
<execution>
<id>create-myjavadoc</id>
<phase>install</phase>
<goals>
<goal>javadoc</goal>
</goals>
</execution>
</executions>
</plugin>
My maven-clean-plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<filesets>
<fileset>
<directory>target</directory>
<includes>
<include>**/*</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
<fileset>
<directory>MySourcefolder</directory>
<includes>
<include>**/*</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
Maybe the JavaDoc must not be generated in a snapshot build - depending on your requirements. If so, add a profile for release or special builds, which includes the maven-javadoc-plugin configuration, and remove the plugin from your default build/plugins section. When you want to generate the JavaDoc run the profile with "mvn clean install -P <profile>". Otherwise just run "mvn clean install" to avoid the JavaDoc generation. Such a profile can look like this:
<profiles>
<profile>
<id>release-build</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9</version>
<configuration>
<noqualifier>all</noqualifier>
<reportOutputDirectory>myJavaDocOutputDirectory</reportOutputDirectory>
</configuration>
<executions>
<execution>
<id>create-myjavadoc</id>
<phase>install</phase>
<goals>
<goal>javadoc</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
You can run it with: "mvn clean install -P release-build"

Categories

Resources