Maven plugin to generate an executable web application (war->executable jar-war) - maven

I have a maven project that is generating a .war file.
I want to configure maven to generate an executable jar, that embeds a servlet container (jetty, tomcat, or others) plus my war application, and generate an executable jar that can run my web application with a command like:
java -jar mywebapp.war
Is there a maven plugin to obtain such artifact?
At the moment I'm using jetty-runner to run a test version of my app, it's quite satisfying for test, but not as as handy for redistribution as it would be an executable war (like in jenkins).
Update
#jesse-mcconnell: I don't want to change a single line in my web application (except in the pom.xml) to achieve the result. It's just a matter to package my war differently, and keep it deployable under an appserver of choice, plus having the ability to run it as an executable war.
A perfect solution should also give me the ability to choose which appserver to embed, also specifying all needed configuration files contained in the executable war itself.
#khmarbaise: I know about jenkins, I already checked the code long time back, it uses winstone servlet container, and it puts a Main.class in the war which is accessible from http (and I think it's wrong)
A perfect solution could generate a war containing stuff like this:
├── META-INF
│ └── MANIFEST.MF (Main-Class: WEB-INF.container.classes.Main)
└── WEB-INF
   ├── web.xml
   ├── classes
   ├── lib
└── container
├── lib (jetty.jar/tomcat.jar/whatever.jar)
   ├── etc (configuration files for the container)
└── classes
└── Main.class
Main.class should use etc configuration as default, but being able to override common parameters at the command line (port, context,etc) or specifying a new configuration.
Main.class should be able to load the container jar and configuration from inside the container (or extract into tmp.dir) and start up the appserver.
This is how I would make it.
At the end, you have a normal war, that can be deployed in any appserver, with the ability to run in a self-contained way.

Tomcat Maven plugin do that have a look here http://tomcat.apache.org/maven-plugin-2.0/executable-war-jar.html
HTH

Use the maven jar plugin to set the Main-Class in the manifest, and then write a main method with something akin to this (or that calls into code like this):
http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneServletContext.java?h=jetty-8
You can register your servlets and wire up the webapp accordingly.
The issue with bundling a war file proper inside of a jar file is that you would need a specialized deployer that understands deploying a war file from within a jar, not a common thing. So creating an uber type jar is probably the better way to go. Besides, one of the big reasons of the actual WebAppContext is the classloader isolation which is kinda moot in these cases.
You can use the maven-dependency-plugin to unpack the various dependencies you need. There are other plugins you can use like the maven-uberjar-plugin (I think that was the name) but you can do it simply with the maven-dependency-plugin + a custom main class akin to something like the above.
I like this approach as you end up with a main method that you can run in eclipse that starts up the whole application and lets you debug the whole thing as well, often quite a win.
Edit: for posterity, jetty also releases with an artifact called jetty-runner that allows for running war files directly off of the command line

No that i know but check the jenkins source code which supports starting directly from command like you expected to work.

Related

Overriding a configuration property from inside the parent project in SpringBoot

I have the following SpringBoot project structure ..
dependencyProject is packaged as a .jar and contains property configuration files:
.
└── dependencyProject
└── src
└── main
└── resources
├── application-dev.yml
└── application.yml
application-dev.yml contains
app-configuration.org.app.shell: true
Then mainProject consumes dependencyProject i.e dependencyProject is on the classpath.
.
├── config
│   └── application.yml
└── src
└── main
└── java
└── Main.java
application.yml contains
app-configuration.org.app.shell: false
By default my app runs in dev profile.
When I run the app, the value for app-configuration.org.app.shell is true.
Why is it not using the value obtained from application.yml, inside the main/root project?
Is there a way I can override the property value from inside my main project, without having to edit the version inside the jar project?
Why is it not using the value obtained from application.yml, inside the main/root project?
Spring loads configuration properties in the following order:
1. Application properties packaged inside your jar (application.properties and YAML variants).
2. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
3. Application properties outside of your packaged jar (application.properties and YAML variants).
4. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).
Source: Spring-boot. Externalized Configuration
Your properties in dev profile are loaded later and override the value.
Is there a way I can override the property value from inside my main project, without having to edit the version inside the jar project?
You probably can do some workaround but be aware that this could result in reverse confusion for others (e.g. why my profile-specific properties do not override those defined in application properties as Spring claims to be)
Well if I understood your question correctly, you can override the value using an environment variable. Like this,
-Dapp-configuration.org.app.shell=false

How can I exclude resource files from being included in .war?

I have a small Spring/Gradle Liberty web service that is to be deployed to multiple environments. I'd like to keep all the environment-specific resources out of the .war that contains the service. The project structure is:
src/main/java/
src/main/resources
...resources used in all environments
resources/
resources_deployment1
...resources used for deployment1
resources_deployment2
...resources used for deployment2
...
...
I have tried putting the following in my build.gradle:
war {
rootSpec.exclude( "resources/**" )
}
but when I look into the .war that gets deployed, I still see files
that come from resources/resources_deployment1.
What else can I try?
Did you try this?
war {
rootSpec.exclude("**/resources/**")
rootSpec.exclude("**/resources/**")
}
Hope this worked!
You can refer this

spring boot does not read the correct property file

[root#xx ~]# tree /data/portal/
/data/portal/
├── portal.jar
└── config
   └── application.properties // I wish it read this
java -jar portal.jar does not read properties in config folder, it stubbornly reads the same file in jar package. However, based on 24.3 Application Property Files jar should read the configuration in config folder. Maven project too. Now I have to manually configure the file location by --spring.config.location.
EDIT:
I have just found that, by using --spring.config.location=file:/absolutepath/config/application.yml does not actually load any included property files. like this:
spring.profiles.include: 'routes'
does not load application-routes.yml, even though log says The following profiles are active: routes

Maven war has META-INF folder in two places

I'm working on a project which uses JAAS and unfortunately for me Tomcat requires a file to be put in a META-INF folder in the root of the war
app.war
|__META-INF
| |___context.xml
...
I think that it's already weird since the default META-INF location for WAR's is in the classes folders.
app.war
|__WEB-INF
| |__classes
| |__META-INF
...
So I'm using Maven, which states that anything in src/main/resources/META-INF will be copied to the appropriate place, which it does. The weird thing is that it is also creating a META-INF folder in the root of the file structure leaving me with 2 META-INF folders.
Project Structure
app
|__src/main/java
|__src/main/resources
| |__META-INF
| |__context.xml
...
After mvn package
app
|__META-INF [1]
|__WEB-INF
| |__classes
| |__META-INF [2]
| |__context.xml
...
So, if the war standard states that META-INF should be under classes folder, as in #2, why maven war creates the #1 folder. And is there a way to make it copy files into that folder instead of #2?
Regards
So I found this:
Two Meta-Inf folders - normal structure?
which states that having 2 META-INF folders is not a problem. Digging a little I found:
JAR File Specification
which states about the META-INF folder:
A JAR file is essentially a zip file that contains an optional META-INF directory. ...The META-INF directory, if it exists, is used to store package and extension configuration data, including security, versioning, extension and services.
and this:
JSR-000315 JavaTM Servlet 3.0
which, on section 10.6, states about the WAR file structure:
When packaged into such a form, a META-INF directory will be present which
contains information useful to Java archive tools. This directory must not be directly
served as content by the container in response to a Web client’s request, though its
contents are visible to servlet code via the getResource and getResourceAsStream
calls on the ServletContext. Also, any requests to access the resources in META-INF
directory must be returned with a SC_NOT_FOUND(404) response.
So from the WAR spec the right place is WEB-INF/classes/META-INF. Yet, since war is a special jar file, it makes sense to have /META-INF as a point for extensions. One can see such different uses in JPA persistence.xml vs. Tomcat context.xml files: the former should be placed in WEB-INF/classes/META-INF while the latter in /META-INF.

Create java resources webapp folder structure with maven

I want to create /java, /resources, and /webapp/WEB-INF/web.xml folder structure under src.
I have used the -DarchetypeArtifactId=maven-archetype-webapp but it creates /resources /webapp/WEB-INF/web.xml but doesn't create /java folder.
So in spite of creating the folder /java in eclipse manually is there any other way to create with some -DarchetypeArtifactId= so that it creates the above folder structure.
I'll be thankful if someone can tell me how can I customize and design my folder structure and create it with maven without using existing template.
When you use -DarchetypeArtifactId=maven-archetype-webapp, java folder wont be created. It needs to be created manually.
It created the following structure
src
└── main
└── resources
└── webapp
└── WEB-INF
Best choice is to follow Maven standard directory layout:
http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
Archetypes are minimized due different programming languages can be used for web development:
http://cvs.peopleware.be/training/maven/maven2/standardDirLayout.html (link goes to web.archive since the main link is dead)
It will minimize configuration of plugins and also will simplify understanding and maintenance of Maven projects
you can create a Maven Webapp using following archetype
-DarchetypeArtifactId=maven-archetype-webapp
which will automatically creates the desired folder structure
in your case its apart from src\main\java
src\main\resources
src\main\webapp

Resources