Spring Boot war packaging: Execution with additional classpath - java

I would like to package my Spring Boot application as a war package in order to
deploy on existing tomcat
running standalone with java -jar application.war
with the same artifact. To achieve this I set the scope of spring-boot-starter-tomcat to provided so these dependencies are located in folder lib-provided.
I don't want to include the Database driver in the artifact. When running on existing tomcat I just add the database driver (as jar) to its lib folder.
Now my question: How can I add the additional classpath (e.g. lib/*) to the java -jar application.war command? Traditional approaches (like java -cp lib/* -jar application.war) did not work.

Found out that Spring Boot uses a WarLauncher to run executable war files. So
java -cp drivers/*:application.war org.springframework.boot.loader.WarLauncher
is a working commandline command to add additional jar files to the classpath without modifying or unpacking the war file.

Related

Spring boot JAR as windows service AND external application.yml

I packaged my spring boot application into a jar and I made it as a web service via apache tomcat 9 with a .bat file.
on the other hand the externalization of application-prod.yml does not work and the .yml file is ignored in the same path as the jar.
how can I do it please
use packaging tools to package,such as maven.
if you use maven,you should config packaging plugins
you may check the official document, and as your .yml file is already in the same path as the jar file, you may try this :
java -jar myproject.jar --spring.config.location=/path/to/your/yaml

Deploy .war file in docker container: No main manifest attribute in app.war

I have a .war-file of my java application and would like to deploy that to a docker container.
My Dockerfile looks like this:
FROM java:8
EXPOSE 8080
ADD /App.war app.war
ENTRYPOINT ["java", "-jar", "app.war"]
I have my App.war in the same directory.
When I want to run it with the following command:
docker run -p 8080:8080 -t app
it throws the following exception:
no main manifest attribute, in app.war
However, when I inspect app.war, there's a manifest in /META-INF/MANIFEST.MF stating the following options:
Manifest-Version: 1.0
Start-Class: com.package.app.AppMainClass
Spring-Boot-Classes: WEB-INF/classes/
Spring-Boot-Lib: WEB-INF/lib/
Spring-Boot-Version: 1.4.0.RELEASE
Main-Class: org.springframework.boot.loader.WarLauncher
So as far as I understand the error message it states that a Main-Class attribute is missing in the manifest (which is impossible because it's there).
I have also tried adding the real class as Main-Class.
That led to the same error.
Can someone please help me back on track?
First of all don't build a spring boot project as WAR. You would only need WAR if you had some old ancient project which forced you to deploy the app to a web server/servlet container. You'll need to remove war related logic from your build script.
Second. Make sure you're building the project correctly. If it is gradle, you need to build it with ./gradlew build, for maven use mvn package. That will package your archive as an uberjar - including all needed dependencies and making the proper archive structure.
Find more details on how to put a spring boot application to Docker in the user guides.
If and only if by some strange occurrences you need to build it as WAR and run it as an executable archive make sure you do it using the war-plugin provided by spring boot (not the built in war plugin). That's the only working way to build an executable war archive.

WAR file: Could not find or load main class, but it’s there

I have built a WAR archive artifact with Intellij IDEA that contains a Spring Boot MVC application written in Kotlin.
Here’s the relevant contents:
$ jar tvf application.war
...
1649 [timestamp] WEB-INF/classes/org/domain/apps/App00HelloMvcKt.class
2087 [timestamp] WEB-INF/classes/org/domain/apps/App00HelloMvc.class
...
App00HelloMvcKt contains fun main(...), and App00HelloMvc is the Spring Boot application class.
MANIFEST.MF contains Main-Class entry:
Main-Class: org.domain.apps.App00HelloMvcKt
However, when I run it, there is a problem:
$ java -jar application.war
Error: Could not find or load main class org.domain.apps.App00HelloMvcKt
Caused by: java.lang.ClassNotFoundException: org.domain.apps.App00HelloMvcKt
As I understand it, with this directory structure, no additional fumbling with class path is required. Then why is it unable to run?
Additional info: This is a teaching project. I am trying to serve .jsp pages from Spring Boot MVC application with embedded Tomcat. According to the internet, this setup only works if you package the app into a WAR and run it with java -jar.
Most likely IntelliJ "Web Application: Archive" doesn't fully understand Spring Boot semantics. Try packaging the WAR with Maven Spring Boot Plugin, as in explained in chapter 68.2 Packaging Executable Jar and War Files:
$ mvn clean package spring-boot:repackage
$ java -jar target/application.war
A jar file is simply a zip file, so do zip -l application.war and look to make sure your App00HelloMvcKit class is in there, and that your MANIFEST.MF is in the correct place. One of these things is probably incorrect, so fix that.
If you can't figure it out, post the output of the above command in an edit to your question.

How Can I Get Jars Inside Another Jar on the Classpath?

I have a Spring Boot application that loads zero or more external jars from a known location during startup. Application is started using PropertiesLauncher by executing java -Dloader.path=application.jar,BOOT-INF/lib,jars/ -jar application.jar -XX:PermSize=512m -XX:MaxPermSize=512m. The external jars are built in maven using the MODULE configuration.
These jars primarily contain Spring managed classes such as services and controllers. When this is the case, everything loads as expected. However, if i attempt to load a jar that needs access to the jars in its own internal /lib folder, startup fails with ClassNotFoundException. If i use the fat jar model of bundling these dependencies in application.jar, but i'd prefer not to bloat that jar with library files that may never be used if at all possible. Is it possible to get jars within a jar built as a MODULE onto the classpath where PropertiesLauncher can find them?

How to make SpringBoot project run through war package, and can also run through jar

I want my project to be launched on my personal computer via the Main function (either via java -jar or by mvn spring-boot: run), and when the development is complete, I can deploy it directly to Tomcat.
How to configure, to do this
You don't have to do anything special. Just follow the official documentation to build a deployable war. The war file created using the Spring Boot build process is executable as a regular jar file as it contains an embedded servlet container in a separate directory called lib-provided which is added to the classpath only when the war is directly executed.
Bonus: If you want to get rid of unnecessary dependencies on embedded server when creating a deployable war, you can check out a blog post, which show how to do it step-by-step.

Categories