Spring boot not serving static files from inside jar - java

Spring boot is not serving static files placed inside a jar.
I've had a backend app which I decided to add frontend to. Setup tasks to copy static frontend files to src/main/resources/static. Went through a bunch of answers here on SO, all of them advise the static content (index.html, .js and .css files) should reside under src/main/resources/static or src/main/resources/public, which i both tried. I open the built .jar and the static files are there, but starting application using java -jar myApp.jar and opening localhost:8080 gives me default whitelabel error page. My application works, since i can access the api i have running on it.
Application doesn't have #EnableWebMvc or any other custom configuration.
If i manually copy/paste same static resources to project's src/main/resources/static and ran the application using #SpringBootApplication class in IDE - the resources are loaded without problem and index.html opens upon visiting localhost:8080, so it's only a problem when files are in .jar.
Should the static files be somewhere different when they're in runnable spring boot .jar file?
Spring boot version 2.1.1

I am facing the same problem.
In case it is helpfull, I can manage to serve the static files properly by adding the following configuration :
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
#EnableWebMvc
public class StaticFilesConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
}
}
... but it overrides the "implicit" auto configuration from spring boot and the rest of my filters etc. doesn't work anymore... => this is because #EnableWebMvc deactivates spring's default configuration.
[EDIT] In the end, I happened to understand that the jar containing the static files was not included in the built bootJar. You may want to check that.
HTH!

Related

How to deploy spring boot app on external tomcat server?

I have a spring boot app. It only has few api.
Its running fine on embedded tomcat server.
Now I need to deploy to my external tomcat server.
So I added packaging as war in pom file
I tried making a war using export as war option and put this war file inside my external tomcat webapps folder and tried running it. It failed with 404 status.
War file Name
CghsMobileApp.war
My rest controller
#RestController
#RequestMapping("/cghs")
public class HcoRestController {
#Autowired
private hcoService hcoSrvc;
#GetMapping("/cghsCity")
public List<CghsCity> getCghsCity() {
return hcoSrvc.getCghsCity();
}
}
URL I tried to hit
http://localhost:8080/CghsMobileApp/cghs/cghsCity
There is no html page inside my api project. Do I need to add one for war file to work.
I am lost here.
Any help will be appriciated.
Looked at the spring boot specification, found out that in class annotated with #SpringBootApplication have to extend SpringBootServletInitializer, for external server war deployment.
package gov.cghs.CghsMobileApp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
#SpringBootApplication
public class CghsMobileAppApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(CghsMobileAppApplication.class, args);
}
}
but unfortunately only this will not help when working with Spring Profile. If any of your classes are using #Profile("profileName"), it needs to be passed in.
With the fat jar it was easy with the command line parameter --spring.profiles=<name>
When deployed in an external Tomcat that external tomcat has to to be modified (that is catalina.properties requires a -Dspring.profile=)

Web Page Resources Not Loading while deploying in AWS Elasticbeanstalk

I am running a Spring Boot Server with a React front-end. I've built the React Project to production and copied the contents of the build to the Webapp folder in my spring project. It worked perfectly when I ran it locally but when I'm uploading the WAR to AWS, the web content is showing a Whitelabel error page.
WhiteLabel Error Page when hosted in AWS
I tried changing the packaging to JAR because the AWS logs said that a JAR was being launched by the Webapp. But even with JAR packaging everything worked fine locally and not in AWS.
Below is my WebMvc Config file I'm using to direct my '/' requests to the index.html file in src/main/webapp
public class WebMvcConfig implements WebMvcConfigurer {
private final long MAX_AGE_SECS = 3600;
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("HEAD", "OPTIONS", "GET", "POST", "PUT", "PATCH", "DELETE")
.maxAge(MAX_AGE_SECS);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("/");
}
}`
Spring Boot by default allows the web files to be stored in /public or /static or /resources and not in /webapp. And these locations need not be added via config, I just needed to add an empty controller class.
I removed the addResourceHandler function, created an empty controller class
#Controller
public class MyClass{}
and moved my web files to /resources/public folder. And Spring Boot took care of the configuration.
Why it worked fine locally and did not work in AWS is still a mystery to me.
Read this quote along with the solution to my problem. Thought it was worth a share.
Quote: "The only way to have fewer bugs in your code is not to write code whenever possible. Use what is already provided, even if that takes some research, the return is worth it."

Run Spring's .class instead of .jar file

I have a Java Spring application which I built with maven, and a .jar file together with .class files were generated.
Instead of running the .jar file, is there a way for me to run the .class files instead?
I tried executing java -cp . hello.Application in the same directory as the Application.class (source code of Application.java below), but was given Error: Could not find or load main class hello.Application. Removing the hello. did not work either.
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I am doing the Spring boot application.I think you can also use maven to create a jar file and then use linux commend to run it.
you can run a class by executing follow command :
java Application
for only simple console application. to run Spring Boot application you need maven to build jar file and executing jar file to call main method to load spring boot context. Spring Boot need several requirements and dependencies to run. Spring load context and create a special structure to load. for more you can see following links:
https://spring.io/guides/gs/spring-boot/
http://www.logicbig.com/tutorials/spring-framework/spring-boot/boot-exploded-structure/

What is the difference between spring cloud config server exec.jar and .jar suffix

We are currently using spring cloud config server spring-cloud-config-server-1.1.0.M2-exec.jar and would like to upgrade to the latest version. However, i've noticed that beyond 1.1.0.M2 version there's only standard jars and no exec.jar in Maven repo http://maven.springframework.org/milestone/org/springframework/cloud/spring-cloud-config-server/
Could someone please explain what the difference is? Will I be able to just substitute the exec one with the standard non exec one?
Thanks
The exec jar contains an executable version of the config server (as a Spring Boot application). The non-exec jar contains only the config server classes. So you can't just replace the exec jar with the other one. What you basically have to do is to create a basic Spring Boot application with the config server dependencies and the appropriate annotations (like in the example):
#SpringBootApplication
#EnableDiscoveryClient
#EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}

Could we implement resful webservice via Jersey without manven and web.xml on Tomcat 8

I am trying to implement a very simple restful webservice via Jersey and I keep getting a 404 error page without any other error on the console.
Here is the tutorial that I diligently followed.
http://www.doublecloud.org/2013/08/rest-api-service-made-easy-with-jersey-framework-in-java/
Since I am not using maven, I did not document any dependencies.
I am using Eclipse Java EE luna / Tomcat 8 / Java 8 / Servlet 3.0 ( I don't have any web.xml)
I loaded the Jersey 2.22.1 libraries
Is there something that I am missing to make it work? Should I convert it to a maven project?
Thanks a lof for your help in advance.
*********Response***************
1. Download the jersey library
2. Upload them in the application in the web-inf/lib folder and add them in the Java build path
3. Create an HelloApp.java class
`package testwebservice.rest.demo;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
#ApplicationPath("/rest")
public class HelloApp extends ResourceConfig {
public void AppConfig() {
packages("testwebservice.rest.demo");
}
}`
4. Create HelloWorldService.java class
`package testwebservice.rest.demo;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Response;
#Path("/hi")
public class HelloWorldService
{
#GET
#Path("/{name}")
public Response getMessage(#PathParam("name") String name)
{
String outMsg = "Hello " + name + "!";
return Response.status(200).entity(outMsg).build();
}
}`
Project / Clean in eClips
Start the server
Test the link "localhost:8080/testwebservice/rest/hi/Test"
result= Hello Test!
If you have all the jars from the Jersey JAX-RS 2.0 RI bundle, you don't need a web.xml. Just just need an javax.ws.rs.core.Application sublcass, annotated with #ApplicationPath. So this is the most minimal required configuration
#ApplicationPath("/api")
public class MyApplication extends Application {}
Just having this empty class will trigger class-path scanning, which will scan for classes annotated with #Path and #Provider classes.
As mentioned here class-path scanning is not recommended though. Better to use Jersey's package scanning capabilities. First instead of extending Application, you should extend ResourceConfig (which is an Application subclass). Then just call packages("..") to list the package to scan for your resources
#ApplicationPath("/api")
public class AppConfig extends ResourceConfig {
public AppConfig() {
packages("your.packages.to.scan");
}
}
And that's it. You should be up and running, as long as your resource class is structured properly. And make sure all your jars are actually in your WEB-INF/lib when deployed to Tomcat.
See Also:
Servlet Based Deployment for other deployment options (information)
Im pretty sure the tomcat servlet requires a web.xml at the very least.
Maven/gradle makes dependency management and building/deploying applications extremely easy, i would recommend this.
On another note: If you just need a simple small web service, take a look at spring-boot. It has an embedded tomcat server. No setup needed what so ever, other than a simple maven / gradle setup.
Take a look here: https://spring.io/guides/gs/rest-service/

Categories

Resources