I was trying to make a spring boot jsp application. So, I had gone to http://start.spring.io/ and selected web module and application is download into local folder.
After importing project into eclipse, I made an entry into application.properties as
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
Then I created one controller as
#Controller
public class HelloController {
#RequestMapping("/hello")
public String hellopage() {
return "ankit";
}
}
Lastly, I added one jsp under WEB-INF/jsp folder as ankit.jsp
After starting the application, I hit the url http://localhost:8080/hello and I get response as Whitelabel Error Page
While I spend many hours to return jsp from spring-boot mvc with no success,
I tried to return the response from controller as REST SERVICE. So, I had made only few changes
1) Replace #Controller with #RestController
2) remove entry from appliation.properties
Then, I run main class and got the successful response on hitting the url http://localhost:8080/hello
So, my question is why there is so much pain in configuring spring boot to return response into jsp page.
EDIT:
Initially, my application is started with following class:
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
But after few people suggestions, i changed it to following
#SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer{
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(DemoApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
However, result is same. After referring to this link, I had rename WEB-INF folder to view. On hitting the /hello url, my jsp is download into my local machine.
So, rendering the jsp from controller is again a mystery.
I need to either:
made a rest application instead of web application
switch to thymeleaf template engine instead of jsp
put more research into it jsp rendering
Thanks for your answers
Things you should check when using Spring boot with JSP :
Make sure you have a subclass of SpringBootServletInitializer in you project. It should look like this :
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
Make sure to use a "war" packaging
Make sure to declare the following provided dependency in your pom.xml : spring-boot-starter-tomcat
If it still doesn't work, try it with an external server instead of the embedded tomcat.
That said, Thymeleaf or Freemarker templates will be a lot easier to deal with. Thymeleaf is used by the Spring documentation so you might want to check that.
According to your description, your application.properties is ok with
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
Your Controller class is ok with
#Controller
public class HelloController {
#RequestMapping("/hello")
public String hellopage() {
return "ankit";
}
}
Your main application is ok with
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Make sure that you have created folder webapp inside main. WEB-INF inside webapp. and jsp folder inside WEB-INF. And ankit.jsp inside jsp folder.
One more thing add these dependency in your pom.xml
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
Related
In our application, we have to serve static files from a folder outside of the application folder. The location of the static file folder is /var/tmp/myapp/attachments additionally to the default locations. The application is implemented to create a deployable war (extending SpringBootServletInitializer.class). Using Spring Boot 2.2 and Tomcat 9
Here is the setup of my application:
1. application.yml file
main:
web-application-type: none
# tried adding static resource location here but did not work
#resources:
#static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:///var/tmp/myapp/attachments/
2. Application.class
#SpringBootApplication(
// We are including Spring, but don't want it to stomp on the legacy servlet container, so disable various configurations.
exclude = {
DispatcherServletAutoConfiguration.class,
ErrorMvcAutoConfiguration.class,
WebMvcAutoConfiguration.class,
MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class},
scanBasePackages = {"com.app", "com.appmodule"})
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
3. pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Tried Solutions:
1. Tried to add spring-resources-static-locations to application.yml
2. Tried to write:
#Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/myapp/**")
.addResourceLocations("classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:///var/tmp/myapp/attachments/");
}
}
The link created to access static locations:
1. http://my.development.com:8080/myapp/attachments/6b8f6b78-e0e3-4163-89df-2861ac58bc65/common/images/COVER_PANE_FOOTER_COMPANY_LOGO/11/CompanyLogo.jpg
2. also tried: http://my.development.com:8080/attachments/6b8f6b78-e0e3-4163-89df-2861ac58bc65/common/images/COVER_PANE_FOOTER_COMPANY_LOGO/11/CompanyLogo.jpg
Could you please help me figure out based on current application configuration what is the best way to achieve it?
Thank you!
The Problem
My spring-boot application recently changed routing from host/endpoint to host/middle/endpoint. Since the change, I am running into an issue where the resources are not being found relative to the new url structure. Before, I could reference resources like css stylesheets like link(rel='stylesheet', href='css/style.css'), but now the logger shows an error saying it can't find the resource at /middleman/css/style.css.
From my research, I have found that what I need to do is use a resource handler registry. I have created one (as shown below) but it doesn't seem to be working. I think the problem is that even though I now have the resource registry, I am not referencing resources in the registry. What is the proper way to solve this problem and have all resources point load from the same place regardless of the endpoint? I very well may be missing some obvious piece of SOP
Note: This is all a dumbed down representation of my project in order to give the idea of what is going on without giving unnecessary information.
Project Structure
src
main
java
com.mystuff.cool
configurations
ResourceConfiguration.java
controllers
RoutingController.java
application
Application.java
resources
static
css
footer.css
style.css
images
place1.png
location1.png
spot1.png
favicon.ico
javascripts
layout.js
templates
home.jade
Application Class
#ComponentScan(basePackages = {"my.packages"})
#EnableAutoConfiguration
#EnableSAMLSSO
#Configuration
public class Application
{
public static void main(String[] args)
{
SpringApplication.run(new Object[]{ Application.class, ServiceConfig.class, ResourceConfiguration.class}, args);
}
}
Resource Configuration
#EnableWebMvc
#Configuration
public class ResourceConfiguration extends WebMvcConfigurerAdapter
{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(31556926);
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(31556926);
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer)
{
configurer.enable();
}
}
Controller
#Controller
public class RoutingController
{
#RequestMapping("/house/home")
public String home(Model model)
{
model.addAttribute("title", "Home is where the heart is");
commonModelTribs(model);
return "home";
}
}
Home Page
doctype html
html
title Place-spedia #{title}
link(rel='icon', href='images/favicon.ico')
link(rel='stylesheet', href='css/style.css')
script(src='javascripts/layout.js')
link(rel='stylesheet', href='css/footer.css')
body
div#footer-icons
a(href='place1')
img#place1(src="images/place1.png")
a(href='location1')
img#location1(src="images/location1.png")
a(href='spot1')
img#spot1(src='images/spot1.png')
If you are using spring boot, you don't need to worry about the resource configuration since you are already configuring the resource directory through the auto configuration. The default behavior for the autoconfiguration is to look within resources/static.
Your issue is with your href values, try inserting a leading forward slash:
link(rel='icon', href='/images/favicon.ico')
link(rel='stylesheet', href='/css/style.css')
script(src='javascripts/layout.js')
link(rel='stylesheet', href='/css/footer.css')
Spring is routing your application to a new relative path, so by putting the leading / in your href attributes, you are telling the router to look absolutely within the static directory instead of relatively from the middle directory.
Playing around with Spring Boot + MVC with static HTML pages, while noticed this thing:
Firstly, what I have:
Index controller:
#Controller
public class IndexController {
#RequestMapping("/")
public String index() {
return "index.html";
}
#RequestMapping("/{path:[^\\.]+}/**")
public String forward() {
return "forward:/";
}
}
The Html file is:...\src\main\resources\static\index.html
So when my main application class is:
#SpringBootApplication
public class MyApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Everything works well and in default path: localhost:8080\ I get index.html page content
But if I annotate Application class with #EnableWebMvc
#SpringBootApplication
#EnableWebMvc
public class MyApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
I get exception: javax.servlet.ServletException: Could not resolve view with name 'index.html' in servlet with name 'dispatcherServlet'
But according to this spring doc it is a valid configuration.
Maybe someone can explain me why? Do I understand something wrong?
According to spring-boot's docs
The auto-configuration adds the following features on top of Spring’s defaults:
Static index.html support.
...
If you want to keep Spring Boot MVC features, and you just want to add
additional MVC configuration (interceptors, formatters, view
controllers etc.) you can add your own #Configuration class of type
WebMvcConfigurerAdapter, but without #EnableWebMvc. If you wish to
provide custom instances of RequestMappingHandlerMapping,
RequestMappingHandlerAdapter or ExceptionHandlerExceptionResolver you
can declare a WebMvcRegistrationsAdapter instance providing such
components.
So by adding #EnableWebMvc you just disable what spring-boot autoconfiguring for you. Namely static index.html support.
Actually I think when you choose to use spring boot you should use the default config of spring Boot. It means you just have to edit the file application.properties. Now if you use spring mvc, you have to provide your own servlet. So I think mixing up the to is not a good idea. Either you use spring Boot wiht no much config to do or you use spring mvc and you make all the necessary config.
According to Spring Boot MVC structure, you should locate your html file in the templates folder. Then will be visible for Spring Boot
src\main\resources\templates\index.html
I've created an external JAR which contains a simple Spring REST controller, which contains the following piece of code:
#RestController
#RequestMapping("/hello")
public class HelloController {
#RequestMapping(value = "/world")
public Hello hello() {
System.out.println("HELLO WORLD");
return new Hello(1L, "Hello World");
}
}
I then compile this small project into a jar called hello.jar which i then add to the class path of my Spring Boot application and start the application.
I've also added the package to ComponentScan like so:
#SpringBootApplication
#Configuration
// #Controller
// #org.springframework.context.annotation.Configuration
#ComponentScan(basePackages = {"main.java.foo.hello" })
#EnableEntityLinks
#EnableAutoConfiguration
public class Main {
public static void main(final String[] args) throws Exception {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)classLoader).getURLs();
for (URL url : urls) {
if (url.getPath().contains("hello")) {
System.out.println(url.getPath());
}
}
SpringApplication.run(Main.class);
}
}
Because of the print out I can see that the jar is loaded into the application and by adding logging to the Spring Boot Application I can see that the Controller is scanned and is picked up (or at least it seems to be).
However went I browse (via chrome) or make a REST call (via Advance REST client) to "localhost:8765/hello/world" (I start my server on port 8765), I get 404 error.
Other Rest Controllers (from within the application, not the external JAR) seem to be working fine as all REST calls return the appropriate results.
Does anyone think they know why 404 is returned?
I am working on a web application using SpringBoot.
The problem I am facing is as follows. The application is running fine from Eclipse, but when I deploy the project as a war in tomcat 7, it's giving me "HTTP Status 404". No exception found in tomcat logs.
Below is my controller:
#RestController
public class TinyUrlController{
#Autowired TinyUrlService tinyUrlService;
#RequestMapping("/create")
public String createUrl(#RequestParam("url") String url,HttpServletRequest request){
TinyUrl tinyUrl = tinyUrlService.createUrl(url);
return tinyUrl.toString();
}
}
Seems your application have no entry point that's why you got nothing. Just create entry point into your application.
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(applicationClass, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<Application> applicationClass = Application.class;
}
See also Spring Boot deploying guide
I suggest that you try to build your application layout by using
http://start.spring.io/
It will make a SpringBoot application
It will make java packages right too
Just remember to place your controllers under java package "demo".. otherwise they cannot be "auto wired" without more configuration...
I suggest you make a simple controller that just returns "hello" as a starter...