I have a simple Spring boot application. There URL that would be used here is going to be like:
sub.domain.com/variable1/variable2
and variable1 and variable2 can be anything for example:
sub.domain.com/kfc/foo
sub.domain.com/subway/boo
and I capture those in my controller as below:
#Controller
public class IndexController {
#RequestMapping(value="/{var1}/{var2}", method = RequestMethod.GET)
public String Index(#PathVariable(value="var1") String variable1, #PathVariable(value="var2") String variable2) {
return "/index.html";
}
}
which will redirect to my html page which is located at src/main/webapp/index.html
so the index page is loaded under the dynamic url but then none of the scrips or stylesheets are found because it's trying to find them under variable1 path.
for example if I have
sub.domain.com/kfc/foo
and my link to css in the index.html is
<link rel="stylesheet" href="styles/index.css" />
it will try to find the index.css under
sub.domain.com/kfc/styles/index.css
how can I tell the app to look into the right place for the styles or js files?
index.html is trying to load styles from a relative path.
In order for index.html to load styles under sub.domain.com/styles/index.css, add a / in link tag **/**styles/index.css <link rel="stylesheet" href="/styles/index.css" />
Related
I am very new to Spring Boot framework and want to clarify why I am facing with this issue.
Issue: .jsp file is not shown at the correct endpoint.
this is my controller class
#Controller
public class HomeController {
#RequestMapping("home")
public String home() {
System.out.println("Hello World");
return "home.jsp";
}
}
This is my application.properties class
spring.mvc.view.prefix = /webapp/
spring.mvc.view.suffix = .jsp
this is what I have inside home.jsp file
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Change Titlte</title>
</head>
<body>
Hello
</body>
</html>
and lastly, the project directory
When I start spring boot app the site looks like this
Why do you think I can't see the content of home.jsp file?
Any help is appreciated.
Best,
PS: I already added Tomcat Jasper libraries in the pom.xml file
Check this simple examle. It seems you should not use .jsp extension in controller's return statement. Don't forget to specify method of your endpoint. Use #GetMapping instead of #RequestMapping
Also you'd better switch to Spring MVC thymeleaf that works good with html files. jsp - is used mostly for Java EE projects.
There are several things to notice here.
Change mapping to /home instead.
View resolver is configured already, return "home" instead of "home.jsp".
Take Model object as an argument it will be useful.
home(ModelMap model)
I have created a Spring Boot application with Intellij. It creates a sample web application with a controller and an empty html page.
But problem is this sample application returns "Whitelabel Error Page" when I go to "http://localhost:8080/info/aa". I think It cannot find info.html file. Is there any way to fix this?
Here is sample controller;
#Controller
#RequestMapping("/info")
public class InfoController {
#RequestMapping("/aa")
public String getServerInfo(Map<String, Object> model){
model.put("message", "server info");
return "info";
}
}
My project directory;
EDIT: My html file info.html;
<!DOCTYPE html>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html lang="en">
<head>
</head>
<body>
</body>
</html>
EDIT 2: I update my html directory to templates/info.html
DemoApplication class;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
And application.properties file is empty.
If your info.html is actually a template file then it obviously shouldn't be in a static content, it should be in a templates folder, as its not static.
Here is an example: https://spring.io/guides/gs/serving-web-content/
Under static folder you have all static content, which wouldn't change when you serve it, for example, images, css, js scripts and so on.
Under templates folder you store templates from which spring + its template ending(for example thymeleaf) will generate actual html, using your model, which will be served to a client.
Also if you have a subfolder in templates like templates/info/info.html then you should return info/info as a template name from your controller, not just info.
However if you are using jsp then its something different, and you shouldn't use template folder, you should create webapp/WEB-INF/jsp/ folders and put it there and you should name your template info.jsp then, instead of info.html
Example here:
https://www.mkyong.com/spring-boot/spring-boot-hello-world-example-jsp/
You don't have to put your info.html into static/info folder inside your resources, instead put it into templates.
The #RequestMapping on top of your InfoController class does not tell where to find the requested html files, it is just a mapping for your request.
If you want to have separates folder for different html pages you can have the info folder inside of your templates folder, but you still have to refer is in your controller as info/info:
#RequestMapping("/aa")
public String getServerInfo(Map<String, Object> model){
model.put("message", "server info");
return "info/info";
}
If you want to use JSP (like I see you want) first of all move the html files to the folder:
/src/java/webapp/
and change the extension to .jsp. Then you will have your view file in:
/src/java/webapp/info/info.jsp
Secondly you have to add configuration for view resolving:
#Configuration
#EnableWebMvc
public class WebConfiguration {
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/templates/");
resolver.setSuffix(".jsp");
return resolver;
}
}
And in the controller rember to return path of the file - you have configured head to .../templates and you have to return info/info:
#RequestMapping("/info")
public String info() {
return "info/info";
}
After having configured Thymeleaf 3 in Spring Boot 4 using the Gradle configuration
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
compile('org.thymeleaf:thymeleaf:3.0.3.RELEASE')
and
ext['thymeleaf.version'] = '3.0.3.RELEASE'
ext['thymeleaf-layout-dialect.version'] = '2.1.2'
URL resolvers do not properly resolve the URLs in Thymeleaf views:
<link rel="stylesheet" href="/css/login.css" data-th-href="#{~/css/login.css}">
simply becomes
<link rel="stylesheet" href="/css/login.css">
I have done some debugging and first of all, during a request I noticed that SaveToSessionResponseWrapper (sub of SaveContextOnUpdateOrErrorWrapper) gets initialized like this:
public SaveContextOnUpdateOrErrorResponseWrapper(HttpServletResponse response,
boolean disableUrlRewriting) {
super(response);
this.disableUrlRewriting = disableUrlRewriting;
}
The arguments passed are a FireWalledResponse and false. The latter results in the following method completely disabling the forwarding of URLs:
#Override
public final String encodeURL(String url) {
if (this.disableUrlRewriting) {
return url;
}
return super.encodeURL(url);
}
Now, if I put a breakpoint in the constructor and force disableUrlRewriting to be true, it eventually executes HttpServletResponseImpl.isEncodeable which then fails here:
} else if(hreq.isRequestedSessionIdFromCookie()) {
return false;
At this point I'm not sure what is wrong. I'm unable to find anyone with this error and it works with neither starter-tomcat nor starter-undertow but I haven't done as thorough debugging in Tomcat yet.
#{~/css/login.css} is a server-relative URL in Thymeleaf.
If you want a context-relative URL, omit the tilde (~) character:
<link rel="stylesheet" href="/css/login.css" data-th-href="#{/css/login.css}">
See Standard URL Syntax article for details.
You should use
<link rel="stylesheet" href="/css/login.css" th:href="#{/css/login.css}">
Without data-th-href
I'm going through this Spring tutorial online form springsource.org.
http://static.springsource.org/docs/Spring-MVC-step-by-step/part2.html
In Chapter 2, at the end, it has you add a bean to prefix and suffix /WEB-INF/jsp/ and .jsp to responses.
The code so far should basically load index.jsp when you go to localhost:8080/springapp/ which will redirect to localhost:8080/springapp/hello.htm which creates an instance of the HelloController which should in theory send you over to /WEB-INF/jsp/hello.jsp. When I added the prefix/suffix bean and changed all my references to just "hello" instead of the fully pathed jsp file, I started getting the following error:
message Handler processing failed; nested exception is
java.lang.NoClassDefFoundError: javax/servlet/jsp/jstl/fmt/LocalizationContext
I've tried going back through the samples several times and checking for typo's and I still can't find the problem. Any tips or pointers?
index.jsp (in the root of the webapp:
<%# include file="/WEB-INF/jsp/include.jsp" %>
<%-- Redirected because we can't set the welcome page to a virtual URL. --%>
<c:redirect url="/hello.htm" />
HelloController.java (minus the imports and package:
public class HelloController implements Controller {
protected final Log logger = LogFactory.getLog(getClass());
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String now = (new Date()).toString();
logger.info("Returning hello view with " + now);
return new ModelAndView("hello", "now", now);
}
}
My hello.jsp file:
<%# include file="/WEB-INF/jsp/include.jsp" %>
<!DOCTYPE html>
<html>
<head>
<title>Hello :: Spring Application</title>
</head>
<body>
<h1>Hello - Spring Application</h1>
<p>Greetings, it is now <c:out value="${now}" /></p>
</body>
</html>
It seems like you are missing the JSTL jar here. Try downloading it and place it in your classpath to see if it works: Where can I download JSTL jar
It seems certain required jar(s) are missing from classpath.
Make sure you have servlet-api-2.x.jar jsp-api-2.x.jar and jstl-1.x.jar on classpath
Please make sure the jstl.jar file is located in your WEB-INF/lib folder.
As a matter of fact, here is what is stated in the tutorial that you linked. I guess you missed this step:
We will be using the JSP Standard Tag Library (JSTL), so let's start
by copying the JSTL files we need to our 'WEB-INF/lib' directory. Copy
jstl.jar from the 'spring-framework-2.5/lib/j2ee' directory and
standard.jar from the 'spring-framework-2.5/lib/jakarta-taglibs'
directory to the 'springapp/war/WEB-INF/lib' directory.
I'm using Spring MVC 3.0 to construct a rest-style url.
Here is part of my code:
#RequestMapping(value = {"/", "/posts"}, method = RequestMethod.GET)
public String getNewestPosts(Model model, HttpServletRequest request)
throws DataAccessException {
return getPostsByPage(1, model, request);
}
#RequestMapping(value = "/posts/page/{page}", method = RequestMethod.GET)
public String getPostsByPage(#PathVariable long page, Model model,
HttpServletRequest request) throws DataAccessException {
// ... get the posts by page number
}
I wrote two methods. One handles the request from url "/posts" which means retrieving the first page of the posts , and the other one handles the request from url "/posts/page/{page}" which means retrieving the posts according to the path variable {page}.
And the problem is that all the two methods above point to the same view which is a jsp file, but they're in different paths("/posts, "/posts/page/xxx"). The css path (../style.css) can not adapt both of them.
I try to solve it by using absolute css path(/style.css), which means the web application works only if the application is deployed on a root path("/").
I would appreciate it if you could help me.
Use the <c:url> tag, which prepends the context path to an absolute URL.
<link rel="stylesheet" type="text/css" href="<c:url value="/style.css" />" />
or
<c:url var="cssUrl" value="/style.css" />
<link rel="stylesheet" type="text/css" href="${cssUrl}" />