Jetty Run War Using only command line - jetty

Is it possible to use only the command line to Run jetty with only a specified war file and Context Path.
Something like :
java -jar $jettyHome/start.jar -Dwar.location=myApp.war -DcontextPath=/myApp OPTIONS=default,plus,jsp

Use the jetty runner.
java -jar jetty-runner.jar my.war
With Maven, you can install by adding to your pom.xml:
<build>
...
<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>7.5.4.v20111024</version>
<destFileName>jetty-runner.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Run:
mvn package
And use as:
java -jar target/dependency/jetty-runner.jar target/*.war
http://www.eclipse.org/jetty/documentation/current/runner.html
http://central.maven.org/maven2/org/eclipse/jetty/jetty-runner/

I've written a tiny command line app / Maven archetype which works like how I thought this all should have in the first place. The bootstrap app lets you launch your servlet container of choice (Jetty, Tomcat, GlassFish) by just passing it the path to the WAR and your port.
Using Maven, you can create and package your own instance of this simple app:
mvn archetype:generate \
-DarchetypeGroupId=org.duelengine \
-DarchetypeArtifactId=war-bootstrap-archetype \
-DarchetypeVersion=0.2.1
Then you launch it like this:
java -jar bootstrap.jar -war myapp.war -p 8080 -c /myapp --jetty
Here's the source for the utility and the archetype: https://bitbucket.org/mckamey/war-bootstrap

install maven from command line:
sudo apt install maven
run war from command line on folder, where pom.xml:
mvn jetty:run-war

Using jetty-runner-minimal:
$ git clone https://github.com/kissaten/jetty-runner-minimal
$ cd jetty-runner-minimal
$ mvn package
$ wget https://tomcat.apache.org/tomcat-7.0-doc/appdev/sample/sample.war
$ java -jar target/dependency/jetty-runner.jar sample.war

It's possible, if you have the appropriate start config (jetty.xml) set up.
Out of the box, jetty doesn't ship with a jetty.xml that does that, but you could write one easily enough.
That would mean you'd either
Have a command line that was more like
java -jar $jettyHome/start.jar -Dwar.location=myApp.war -DcontextPath=/myApp jetty-myapp.xml
or
java -jar $jettyHome/start.jar -Dwar.location=myApp.war -DcontextPath=/myApp etc/jetty.xml etc/jetty-plus.xml jetty-deploy-app.xml
Override the etc/jetty.xml yourself and put the info you want in there.
Jetty startup is pretty straight forward, so it's really just about producing an XML file that does what you want.
That XML file can read values from system properties, so you can use your various "-D" options.

Related

SpringBoot fails to deploy after adding .ebextensions for ngingx SSL -[An error occurred during execution of command [app-deploy]]

I have a SpringBoot app that deploys just fine to AWS Beanstalk, and the default nginx proxy works, allowing me to connect via port 80.
Following the instructions here: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/https-singleinstance.html, and verifying with another of my projects that works with this exact config, Beanstalk fails to deploy the app with error:
2020/05/29 01:27:56.418780 [ERROR] An error occurred during execution of command [app-deploy] - [CheckProcfileForJavaApplication]. Stop running the command. Error: there is no Procfile and no .jar file at root level of your source bundle
The contents of my war file are as such:
app.war
-.ebextensions
-nginx/conf.d/https.conf
-https-instance-single.config
-https-instance.config
-web-inf/
My config files pass as valid yaml files. (These files are identical to those in the AWS doc, and those that work in other project on mine.)
I am using a single instance, with port 443 set open.
These are the errors reported throughout the various log files:
----------------------------------------
/var/log/eb-engine.log
----------------------------------------
2020/05/29 01:37:53.054366 [ERROR] /usr/bin/id: healthd: no such user
...
2020/05/29 01:37:53.254965 [ERROR] Created symlink from /etc/systemd/system/multi-user.target.wants/healthd.service to /etc/systemd/system/healthd.service.
...
2020/05/29 01:37:53.732794 [ERROR] Created symlink from /etc/systemd/system/multi-user.target.wants/cfn-hup.service to /etc/systemd/system/cfn-hup.service.
----------------------------------------
/var/log/cfn-hup.log
----------------------------------------
ReadTimeout: HTTPSConnectionPool(host='sqs.us-east-1.amazonaws.com', port=443): Read timed out. (read timeout=23)
Taking count #Dean Wookey's answer for Java 11, I have successfully deployed Spring Boot application jar along with .ebextensions folder. I just added maven antrun plug to my maven build configurations and for output I am receiving .zip file, which contains .ebextensions folder and spring Boot .jar file at the same level. Just deploying this final zip file to AWS UI Console.
The following is the maven antrun plugin configuration
....
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>prepare</id>
<phase>package</phase>
<configuration>
<tasks>
<copy todir="${project.build.directory}/${project.build.finalName}/" overwrite="false">
<fileset dir="./" includes=".ebextensions/**"/>
<fileset dir="${project.build.directory}" includes="*.jar"/>
</copy>
<zip destfile="${project.build.directory}/${project.build.finalName}.zip" basedir="${project.build.directory}/${project.build.finalName}"/>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
....
Issue with Java and Linux version
If you are using Java 8 and Linux 2.10.9 code will work and override ngingx configuration but if you choose Corretto 11 and Linux 2.2.3 get following error.
Error: there is no Procfile and no .jar file at root level of your
source bundle
Create new environment with Java 8 and deploy app again will resolve issue.
Instead of changing to java 8 as described in vaquar khan's answer, an alternative is to package your source jar inside a zip that also contains the .ebextensions folder.
In other words:
source.zip
-.ebextensions
-nginx/conf.d/https.conf
-https-instance-single.config
-https-instance.config
-web-inf/
-app.war
If you look at the latest documentation https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/platforms-linux-extend.html, you'll see that the nginx config now goes in the .platform folder instead, so your structure would be:
source.zip
-.ebextensions
-https-instance-single.config
-https-instance.config
-.platform
-nginx/conf.d/https.conf
-web-inf/
-app.war
After following vaquar's answer above, also change the 'buildspec.yml' file to have the correct java version. E.g:
runtime-versions:
java: corretto8 # previously this was openjdk8
Should work.
It is still possible to use .ebextensions within your war file.
Add following to your pom.xml in the <build><plugins> section:
<build>
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-resource-ebextensions</id>
<phase>generate-resources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${basedir}/.ebextensions</directory>
<targetPath>.ebextensions</targetPath>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
</build>
This will copy .ebextensions folder to WEB-INF/classes folder. There AWS picks it up while starting and applies scripts from there.

Not able to run Jmeter Performance Test directly using the JAR created from MAVEN

I have been trying to run one Jmeter script through MAVEN, I was able to do that using command
"mvn verify" and able to see the reports also inside /target folder
However, I want to run the Jmeter Performance Test directly through the JAR which is created after running the "mvn verify" command.
Below is my POM.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>jmeter-testproject</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>jmeter-testproject</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<version>2.1.0</version>
<executions>
<execution>
<id>jmeter-tests</id>
<goals>
<goal>jmeter</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
A /target folder is being generated after running "mvn verify" and also jmeter-testproject-1.0-SNAPSHOT created.
However, if I want to run the package by directly executing the JAR, it's giving just "Hello World" as an output which is present in the main class. I want the Jmeter Performance Test also to execute after directly clicking the JAR. Please help.
enter image description here
You can't do this with the jmeter-maven-plugin.
The jmeter-maven-plugin is taking your test plan/configuration and then running a JMeter process for you.
It is not physically building a runnable jar with everything that you need inside it to be able to run performance tests.

I'm getting error 404 while trying to access my spring boot app on Amazon Elastic Bean Stalk

I developed a spring boot application and I've put the following entries in src/main/resources/application.properties:
spring.mvc.view.prefix: /
spring.mvc.view.suffix: .jsp
server.port=5000
Now when I start it (mvn clean spring-boot:run) locally, I'm getting the output Tomcat started on port(s): 5000 (http) and the app is accessible in the browser under http://localhost:5000/welcome .
I created a Java instance in Amazon Elastic Bean Stalk, I've uploaded war, I even opened the port 5000 in the corresponding Security Group on EC2 instance:
but when I now go to http://my-aws-ebs-instance.com/welcome:5000, I'm getting the following message:
Whitelabel Error Page This application has no explicit mapping for
/error, so you are seeing this as a fallback.
Thu Dec 20 16:30:33 UTC 2018 There was an unexpected error (type=Not
Found, status=404). /welcome.jsp
Why oh why does it happen like this? What did I forget to configure?
----EDIT
as requested, here's the root java class:
package com.hellokoding.auth;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;
#SpringBootApplication
public class WebApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WebApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(WebApplication.class, args);
}
}
Here is also the structure of my project with highlighted welcome.jsp page:
When I unzip the generated war file, this is the file structure on my hard drive:
My pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>auth</artifactId>
<name>auth</name>
<description>my descr</description>
<packaging>war</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
and the UserController class contains:
...
#Controller
#Scope("session")
public class UserController {
#RequestMapping(value = {"/", "/welcome"}, method = RequestMethod.GET)
public String welcome(Model model) {
return "welcome";
}
...
I added some logs inside the welcome method and I see it is running correctly. Also, in log files I can see the following entry:
Mapped "{[/ || /welcome],methods=[GET]}" onto public java.lang.String com.hellokoding.auth.web.UserController.welcome(org.springframework.ui.Model)
so I have no idea why this thing does not work. After trying for 11 hours straight to make it work I'm questioning my life choices, and also I'm wondering why anyone would ever use such a stupid framework since it doesn't work ootb.
--- edit:
I've uploaded a simplified code to github https://github.com/nalogowiec/springbootProblem
Solution 1:
If you want Spring Boot With JSPs in Executable Jars
Keep in mind that we will ultimately place the JSP templates under src/main/resources/META-INF/resources/WEB-INF/jsp/
Note :
define the template prefix and suffix for our JSP files in application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
Then your can run jar file using below command :
java -jar <your jar name>
for your project you can below command
java -jar auth-1.3.5.RELEASE.jar
For More reference : https://dzone.com/articles/spring-boot-with-jsps-in-executable-jars-1
Solution 2:
JSP Limitations
When running a Spring Boot application that uses an embedded servlet container (and is packaged as an executable archive), there are some limitations in the JSP support.
With Jetty and Tomcat, it should work if you use war packaging. An executable war will work when launched with java -jar, and will also be deployable to any standard container. JSPs are not supported when using an executable jar.
Undertow does not support JSPs.
Creating a custom error.jsp page does not override the default view for error handling. Custom error pages should be used instead.
I have clone your GitHub project able to run project(if you follow below steps your problem will get solve definitely)
Step To run your project :
Step 1 : Create war package of your project
Step 2 : Run your war package using below command
java -jar <your war file name>
i.e for your project command should be like :
java -jar auth-1.3.5.RELEASE.war
Step 3 : Hit the URL http://localhost:5000/
You can see the result in browser.
More reference : https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-developing-web-applications.html#boot-features-jsp-limitations
Nice explanation #dipak-thoke.
Just to add if anyone automating the deployment process (In my case, it was through CodeBuild And CodeDeploy), you can create Procfile and deploy the war. I have added Procfile into the root directory of the project and added it as an artifact.
Hope this helps someone looking for same usage case :)
ProcFile:
web: java -jar <your_war_file>.war
This is how my CodeBuild Buildspec looks like:
version: 0.2
phases:
build:
commands:
# - command
- ./gradlew bootWar
post_build:
commands:
# - command
- echo Build must be completed
- mv build/libs/*.war <WarFileName>.war
artifacts:
files:
# - location
- <WarFileName>.war
- Procfile
#name: $(date +%Y-%m-%d)
#discard-paths: yes
#base-directory: location
#cache:
#paths:
# - paths
If you check the Spring Boot docs, its clear that you are using the wrong directory structure.
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc
By default, Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext ... Do not use the src/main/webapp directory if your application is packaged as a jar. Although this directory is a common standard, it works only with war packaging, and it is silently ignored by most build tools if you generate a jar.
Since you have your app on port 5000 it is accessible on that port, not default http port 80.
Either access it with
http://my-aws-ebs-instance.com:5000/welcome
or create port forwarding rune in AWS so traffing going to port 80 will be pushed you application server's port 5000.

Can maven surefire plugin run multiple test executions when invoked directly? (Sonar + Jenkins not running all unit tests)

I have a maven project that uses the surefire plugin for unit testing. Currently the testing is split into two executions default-test and unitTests, both bound to the test goal, as follows:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<!-- Test one set of files -->
<execution>
<id>default-test</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes> ... </includes>
</configuration>
</execution>
<!-- Test a different set of files -->
<execution>
<id>unitTests</id>
<goals>
<goal>test</goal>
</goals>
<configuration>
<includes> ... </includes>
</configuration>
<execution>
</executions>
</plugin>
</plugins>
This works fine when running mvn test:
$ mvn test
...
[INFO] maven-surefire-plugin:2.13:test (default-test)
...
[INFO] maven-surefire-plugin:2.13:test (unitTests)
I am using the Sonar plugin on Jenkins to generate code metrics, and Jenkins is set up as follows:
run the build action mvn clean install -DskipTests
run the Sonar plugin as a post-build action
This means that the Sonar plugin runs the unit tests, and the unit tests are run once only. And I see the following output when the Sonar plugin runs:
[INFO] maven-surefire-plugin:213:test (default-cli)
Note that only the default-cli execution is invoked rather than default-test + unitTests, because (I assume) the surefire plugin is invoked directly via mvn surefire:test instead of via the mvn test lifecycle.
I can add a default-cli execution to the POM file, and copy the configuration from the default-test execution, but this will only run one set of unit tests. The unit tests configured in the unitTests execution are not run at all, even though that execution is bound to the same goal.
How can I ensure that the both the default-cli and unitTests executions are invoked when the Sonar plugin invokes mvn surefire:test ?
I am thinking that perhaps my Jenkins setup should change, so that the unit tests are run in the normal build action, which generates code coverage reports, and then the Sonar plugin runs as a post-build action and loads these reports to perform analysis. Not sure if this is possible, or what changes are required to my POM files to support this (hoping to make minimal changes to POM files is another goal).
I am thinking that perhaps my Jenkins setup should change, so that the
unit tests are run in the normal build action, which generates code
coverage reports, and then the Sonar plugin runs as a post-build
action and loads these reports to perform analysis.
That seems like a good idea. You could use maven profiles to do this. You can configure the surefire plugin in different profiles and make the one you want your tools to use active by default.

Lauching a map reduce job in amazon elastic map reduce

I am trying to launch a map reduce job in amazon map reduce cluster. My map reduce job does some pre-processing before generating map/reduce tasks. This pre-processing requires third party libs such as javacv, opencv. Following the amazon's documentation, I have included those libraries in HADOOP_CLASSPATH such that I have a line HADOOP_CLASSPATH= in hadoop-user-env.sh in the location /home/hadoop/conf/ of master node. According to the documentation, the entry in this script should be included in hadoop-env.sh. Hence, I assumed that HADOOP_CLASSPATH now has my libs in the classpath. I did this in bootstrap actions. However, when i launch the job, it still complains class not found exception pointing to a class in the jar which is supposed to be in the classpath.
Can someone tell me where I am going wrong? bbtw, i am using hadoop 2.2.0. In my local infrastructure, i have a small bash script that exports HADOOP_CLASSPATH with all the libs included in it and calls hadoop jar -libjars .
I solved this with an AWS EMR bootstrap task to add a jar to the hadoop classpath:
Uploaded my jar to S3
Created a bootstrap script to copy the jar from S3 to the EMR instance and add the jar to the classpath:
#!/bin/bash
hadoop fs -copyToLocal s3://my-bucket/libthrift-0.9.2.jar /home/hadoop/lib/
echo 'export HADOOP_CLASSPATH="$HADOOP_CLASSPATH:/home/hadoop/lib/libthrift-0.9.2.jar"' >> /home/hadoop/conf/hadoop-user-env.sh
Saved that script as "add-jar-to-hadoop-classpath.sh" and uploaded it to S3.
My "aws emr create-cluster" command adds the bootstrap script with this argument: --bootstrap-actions Path=s3://my-bucket/add-jar-to-hadoop-classpath.sh
When the EMR spins up the instance will have the file /home/hadoop/conf/hadoop-user-env.sh created and my MR job was able to instantiate the thrift classes in the jar.
UPDATE : I was able to instantiate thrift classes from the MASTER node, but not from the CORE node. I sshed into the CORE node and the lib was properly copied to /home/hadoop/lib and my HADOOP_CLASSPATH setting was there, but I was still getting class not found at runtime when the mapper tried to use thrift.
Solution ended up being to the the maven-shade-plugin and embed the thrift jar:
<plugin>
<!-- Use the maven shade plugin to embed the thrift classes in our jar.
Couldn't get the HADOOP_CLASSPATH on AWS EMR to load these classes even
with the jar copied to /home/hadoop/lib and the proper env var in
/home/hadoop/conf/hadoop-user-env.sh -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>org.apache.thrift:libthrift</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
When your job is executed, the "controller" logfile contains the actually executed commandline. This could look something like:
2014-06-02T15:37:47.863Z INFO Fetching jar file.
2014-06-02T15:37:54.943Z INFO Working dir /mnt/var/lib/hadoop/steps/13
2014-06-02T15:37:54.944Z INFO Executing /usr/java/latest/bin/java -cp /home/hadoop/conf:/usr/java/latest/lib/tools.jar:/home/hadoop:/home/hadoop/hadoop-tools.jar:/home/hadoop/hadoop-tools-1.0.3.jar:/home/hadoop/hadoop-core-1.0.3.jar:/home/hadoop/hadoop-core.jar:/home/hadoop/lib/*:/home/hadoop/lib/jetty-ext/* -Xmx1000m -Dhadoop.log.dir=/mnt/var/log/hadoop/steps/13 -Dhadoop.log.file=syslog -Dhadoop.home.dir=/home/hadoop -Dhadoop.id.str=hadoop -Dhadoop.root.logger=INFO,DRFA -Djava.io.tmpdir=/mnt/var/lib/hadoop/steps/13/tmp -Djava.library.path=/home/hadoop/native/Linux-amd64-64 org.apache.hadoop.util.RunJar <YOUR_JAR> <YOUR_ARGS>
The log is located on the master node in /mnt/var/lib/hadoop/steps/ - it´s easily accessible when you SSH into the master node (requires specifying a key pair when creating the cluster).
I´ve never really worked with what´s in HADOOP_CLASSPATH, but if you define a bootstrap action to just copy your libraries into /home/hadoop/lib, that should solve the issue.