JSP not Evaluating with Spring MVC - java

I am trying to render JSP in a Spring 3.2 using annotation driven configuration, but the JSP renders as a string and is not evaluated.
I am using the maven jetty plugin to run the webapp in development. So it seems as if everything should "just work".
The dependencies I am including to use JSP are
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
The bean to configure JSP is
#Configuration
public class WebAppConfiguration {
#Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
The controller is pretty straight forward
#Controller
public class RootController {
#RequestMapping(value = "/login")
public String login() {
return "login";
}
and the JSP is also pretty easy
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head></head>
<body>
<%= "Hello World" %>
${ "Hello World" }
<form name="auth" action="<c:url value='j_spring_security_check' />" method="POST">
<label>Username: <input type="text" name="j_username"></label>
<label>Password: <input type="password" name="j_password"></label>
<input type="submit" value="Submit"/>
</form>
</body>
</html>
As you can see from the image the JSP is not being evaluated. Is there anything I need to do to tell JSP to be evaluated when rendered.
Edit 1
So just for a little extra information I used the Resthub archetype resthub-mongodb-backbonejs-archetype to bootstrap this project, which uses a WebAppInitializer rather than the older web.xml, and it uses new annotation driven beans rather than the xml beans.
EDIT 2
I have been smashing my head on this for all to long so I put the project on github https://github.com/austinbv/calendar/. Since I do not know what is important and what is not.
Thanks for the help

#austinbv Please use the SPRING LINK to check the setup. (As #Rohit has pointed you above - the missing piece)

I had the same problem when using spring boot. Adding these dependencies to the project pom.xml resolved the issue:
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-compiler</artifactId>
<version>5.5.23</version>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-runtime</artifactId>
<version>5.5.23</version>
</dependency>
<dependency>
<groupId>tomcat</groupId>
<artifactId>jasper-compiler-jdt</artifactId>
<version>5.5.23</version>
</dependency>

The above given issue fixed for me after making following change in the "web.xml"
The spring servlet needs to be the default servlet. ie mapped to / and not /*.
Ref link: https://code-examples.net/en/q/b49ce1

You need to specify the appropriate view class
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
resolver.setPrefix("/views/");
resolver.setSuffix(".jsp");
return resolver;
}

I do not know how much actual will be my answer, but I had exactly the same issue (Spring + boot + maven + tomcat).
I solved it by removing the scope-provided from tomcat.embed dependence. So, my dependence now looks like this:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>

Because JSP does not obey MVC pattern :P

Related

FileUpload, Struts2, no file in FileUploaderInterceptor

Have a working Struts2 portlet environment where I cannot make Struts fileUpload work, in portlet mode.
I can see that
A file is uploaded to the server, created in temp space.
A multipart request is present on the original request, with the filename
and file contents, where it enters Struts classes.
I can trigger the maximum size response, the default value set in Struts.
The FileUploadInterceptor is triggered but in the Jakarta
MultipartRequest there is no file. Somewhere between the original
request and the Jakarta wrapper the file is lost.
I have tried the same approach in a stripped down Spring boot 2 application, the same problem occurs as in the main project.
Followed the code at
https://struts.apache.org/core-developers/file-upload.html
for the JSP and action classes. The portlet is created, the flow works, but no file in the action.
Standard Sping Boot 2 with extra in pom:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.5.20</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
Struts.xml
<package name="uploadtest" extends="struts-portlet-default" namespace="/uploadtest">
<action name="uploadtestPrepare" class="bouvet.no.fileuploadtest.action.FileUploadSubmitAction">
<result name="success">/WEB-INF/struts2/test/fileUpload.jsp</result>
</action>
<action name="uploadTestSubmit" class="bouvet.no.fileuploadtest.action.FileUploadSubmitAction">
<result name="success">/WEB-INF/struts2/test/fileUpload.jsp</result>
</action>
</package>
and the form
<s:form action="uploadTestSubmit" method="post" enctype="multipart/form-data">
FileName: <s:property value="%{filename}"/>
<s:file name="upload" label="File" />
<s:submit/>
</s:form>
a setter
public void setUploadFileName(String filename) {
this.filename = filename;
}
Is this a bug in portlet mode or am I missing a key dependency, a component, version? Alternative method?
In the image, a breakpoint in the JSR168 dispatcher, the file is present. First code to run after the server.
breakpoint in JSR168 dispatcher
The solution in this case was to step back a step and look at what was present in the request.
The CMS the portlet is running in is in fact taking care of the upload before the upload reach the portlet environment. The jakarta wrapper I found was created by the CMS but it is outside of the portlet scope.
Solution:
public String intercept(ActionInvocation invocation) throws Exception {
final ActionContext context = invocation.getInvocationContext();
Object action = invocation.getAction();
try {
if (action instanceof FileUploadAware) {
HttpServletRequest request = (HttpServletRequest) context.get(HTTP_REQUEST);
// if (request instanceof MultipartRequestWrapper) {
File file = (File) request.getAttribute("upload");
((FileUploadAware) action).setFile(file);
// }
}
}catch (Exception e){
LOG.error("Exception? {}", e);
}finally {
return invocation.invoke();
}
Not a final solution but the concept, an interceptor that finds an upload attribute on the request and puts it on a FileUploadAware action. The attribute is a local temp file the CMS has intercepted and created.
This works for me, a special solution for this CMS or a general for portlets? Do not know.

Spring boot webjars: unable to load javascript library through webjar

I have a spring boot (I use Thymeleaf for templating) project where I want to use some jQuery libraries.
Unfortunately, the webjars aren't loading at all. I have tried many configuration but all of them failed.
Here is the code snippet of my HTML page:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head lang="en">
<title>JAC</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<script src="http://cdn.jsdelivr.net/webjars/jquery/2.1.4/jquery.js"
th:src="#{/webjars/jquery/2.1.4/jquery.min.js}" type="text/javascript"></script>
<script src="http://cdn.jsdelivr.net/webjars/jquery-file-upload/9.10.1/jquery.fileupload.js" type="text/javascript"
th:src="#{/webjars/jquery-file-upload/9.10.1/jquery.fileupload.min.js}"></script>
<link href="http://cdn.jsdelivr.net/webjars/bootstrap/3.3.5/css/bootstrap.min.css"
th:href="#{/webjars/bootstrap/3.3.5/css/bootstrap.min.css}"
rel="stylesheet" media="screen" />
<link href="http://cdn.jsdelivr.net/webjars/jquery-file-upload/9.10.1/jquery.fileupload.css"
rel="stylesheet" media="screen" />
</head>
I have added them in the pom file:
<dependency>
<groupId>org.webjars.npm</groupId>
<artifactId>jquery</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.5</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery-file-upload</artifactId>
<version>9.10.1</version>
</dependency>
But when calling the page I got a 404 on jquery.min.js and jquery.fileupload.min.js.
GET http://localhost:8888/webjars/jquery-file-upload/9.10.1/jquery.fileupload.min.js
2015-09-21 02:02:04.059 home:9
GET http://localhost:8888/webjars/jquery/2.1.4/jquery.min.js 404 (Not Found)
You are referencing jquery library correctly. Maybe you are missing resource handler configuration.
<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>
Or if you use JavaConfig
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
Webjars documentation
If this will not work, please check if you have webjars on classpath (open your application JAR in 7Zip and check if webjars resources are inside it.)
After inspecting the webjar for jquery, I got this working by adding a "dist" subpath.
<script src="webjars/jquery/2.1.4/dist/jquery.min.js" type="text/javascript"></script>
Additional answer found on one blog:
When using Spring Framework version 4.2 or higher, it will
automatically detect the webjars-locator library on the classpath and
use it to automatically resolve the version of any WebJars assets.
In order to enable this feature, we’ll add the webjars-locator library
as a dependency of the application:
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
<version>0.30</version>
</dependency>
In this case, we can reference the WebJars assets without using the
version; (...)
if you use servlet 3.x just add :
1- using java config :
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/webjars/**").addResourceLocations("/webjars/").resourceChain(false);
registry.setOrder(1);
}
}
2- or xml config :
<mvc:resources mapping="/webjars/**" location="/webjars/">
<mvc:resource-chain resource-cache="false" />
</mvc:resources>
The webjars dependencies should be available on the spring boot classpath, so you should try referencing the webjars using the src attribute like so:
<script src="webjars/jquery/2.1.4/jquery.min.js" type="text/javascript"></script>
<script src="webjars/jquery-file-upload/9.10.1/jquery.fileupload.min.js"></script>
<link href="webjars/bootstrap/3.3.5/css/bootstrap.min.css"
rel="stylesheet" media="screen" />
<link href="webjars/jquery-file-upload/9.10.1/jquery.fileupload.css"
rel="stylesheet" media="screen" />
I ended up doing a mvn clean install (from cmd prompt) to get the target cleaned and all the lib/jars populated correctly. I am using Spring boot with Intelij.
After inspecting the webjars for jquery, I got this working by adding a "THE VERSION OF JQUERY LIBRARY USED IN POM.XML FILE"
<script src = "/webjars/jquery/3.1.0/jquery.min.js"></script>
(in my case I used 3.1.0 version, used that version only that you are using).
Make sure if you have updated the version of bootstrap or jquery when you are adding the dependencies, you should update the URL's in the jsp's or html's with the correct version of bootstrap and jquery.

Spring boot ModelAndView value is not displayed

I can't get the values added to the model in jsp dispalyed. I have tried with everything and and checked all answers on stackoverflow, but nothing helps.
To save your time, I paste a part of code:
My pom.xml :
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
<relativePath/>
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
and my java config code is :
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
and
#EnableWebMvc
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public InternalResourceViewResolver getViewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
my controller is :
#Controller
#RequestMapping(value = "workorder")
public class WorkOrderController {
#RequestMapping(value = "/toProviewPage", method = RequestMethod.GET)
public ModelAndView toPreview(){
WorkOrderVo workOrderVo = new WorkOrderVo();
workOrderVo.setId(1);
workOrderVo.setName("xxx");
workOrderVo.setPriority(1);
workOrderVo.setDetail("xxxx");
return new ModelAndView("workOrderPreview", "workOrderVo", workOrderVo);
}
}
my jsp file is :
<%# page language="java" contentType="text/html; charset=UTF-8" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html lang="en">
<div class="form-group">
<label for="detail" class="col-sm-2 control-label">Detail</label>
<div class="col-sm-10">
<textarea class="form-control" rows="5" id="detail" name="detail" value="${workOrderVo.dreadonly="true"></textarea>
</div>
</div>
but spring boot doesn't resloved is as a jsp file, and display all the html code is the Browser.
Where I write errors?
You can't run the main() method directly for the application when you are using "embedded Tomcat". If you look at your POM it is indicating that the Jasper dependency is provided meaning that it expects your artifact to be put inside a Tomcat container. Running the main() method in your application does not actually load up Jasper which is why you are not seeing the pages processed as JSP. For IntelliJ you need to set up a Maven run configuration (not an application) and use spring-boot:run which apparently sets up Tomcat for you. Here is a picture of how to set it up.
I did it with your application and it appears that the JSPs are being processed. I don't see the exact code you are referencing above in GitHub but I noticed that the preview page had a JSP tag that was processed. There was no value in it but the tag was replaced. Its not clear to me that this is documented so I got a hint from this question. If anyone finds official Spring Boot documentation that makes it clear let me know and I will update this.
I'll summarize the current two feasible solutions:
first :
modify pom dependency, change:
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
to
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
The second:
use spring-boot:run command to start application.

How to upload file using spring mvc3? [duplicate]

This question already has answers here:
File Upload to Server Directory Using Spring MVC
(2 answers)
Closed 8 years ago.
I want to upload file and do process by using Spring MVC3. i tried with
#RequestMapping(value = "uploadAction.do")
public ModelAndView upload(
#RequestParam("file") CommonsMultiPartFile file
)
{
System.out.println(file);
ModelAndView view = new ModelAndView();
return view;
}
but it is not working and i have confused with #RequestParam and #ModelAttribute so please help me
The upload functionality depends on several factors factors. As by the docs, following are the things you must ensure
Make a POST request. File upload should be a POST request
#RequestMapping(value = "uploadAction.do", method=RequestMethod.POST)
Enable Spring multipart handling by adding a multipart resolver to the web application’s context
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
Ensure commons-fileupload.jar is on your classpath, if you're using maven the following should cover you
<!-- File Upload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.0.1</version>
</dependency>
with all this in place, your mapping should work well, providing that your form is OK, here is an example
<form id="fileuploadForm" action="/uploadAction.do" method="POST" enctype="multipart/form-data" class="cleanform">
<input id="file" type="file" name="file" />
<p><button type="submit">Upload</button></p>
</form>
note also that its always better to program against an interface, by changing the argument type to
public ModelAndView upload(#RequestParam("file") MultipartFile file) {
you'll delegate injecting the implementation to the framework. The benefit is that you can write file upload test using spring mvc test framework, in which case the framework will insert the mocked implementation for the MultipartFile interface
Something like this:
#RequestMapping(value="/upload", method=RequestMethod.POST)
public String upload( #RequestParam("upload")
MultipartFile multipartFile
...
){
....
}
and in the form enctype is required:
<form id="command" name="command" method="POST" action="/upload" enctype="multipart/form-data">
....
<input id="upload" type="file" name="photo">
....
</form>

Can't use JSTL on a simple example

Here's my current situation:
I've created a Maven project from my shell, using this command:
mvn archetype:generate -DgroupId=it.my.current.package.example -DartifactId=Example -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=false
mvn package
Then I opened Eclipse, imported the project as a Maven one. I added those dependencies to my
pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
<scope>provided</scope>
</dependency>
Then I created a JSP and a Servlet.
My servlet just sets some variables and my JSP use them with some JSTL.
I've added on my JSP this tag:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
and the code on my JSP is really simple:
<c:forEach items="${requestScope.empList}" var="emp">
<tr>
<td><c:out value="${emp.id}"></c:out></td>
<td><c:out value="${emp.name}"></c:out></td>
<td><c:out value="${emp.role}"></c:out></td>
</tr>
</c:forEach>
My Servlet it's doing this:
List<Employee> empList = new ArrayList<Employee>();
Employee emp1 = new Employee();
emp1.setId(1); emp1.setName("Sam");emp1.setRole("Developer");
Employee emp2 = new Employee();
emp2.setId(2); emp2.setName("John");emp2.setRole("Manager");
empList.add(emp1);empList.add(emp2);
request.setAttribute("empList", empList);
RequestDispatcher rd = getServletContext().getRequestDispatcher("/home.jsp");
rd.forward(request, response);
Employee is a simple Bean.
When I try to run this application, from my Servlet, it actually shows me this, on my JSP:
${emp.id} ${emp.name} ${emp.role}
And it's not showing the value that I set on my Servlet.
I'm totally new to JSTL, so I googled first for my issue. I tried adding jstl-1.2.jar on my $TOMCAT_HOME/lib directory, but it didn't work.
What's the problem then?
EDIT: what are the configuration I need to do on my container and project to run JSTL? Isn't enough what I've made?
I think that it is not a problem with JSTL. This notation: ${emp.role} is EL (Expression Language) and it is not working.
Don't you have isELIgnored="true" set somewere in the JSP file? Like this:
<%# page isELIgnored="true" %>
Or maybe in web.xml:
<el-ignored>true</el-ignored>
It should be false by default, but if you use servlet version older than 2.4 then the default is true, so in that case you would need to set it to false in web.xml:
<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <el-ignored>true</el-ignored>
    </jsp-property-group>
</jsp-config>
You have version 3.1 in dependencies, but in web.xml file 2.3 version is used. To use Servlet 3.1 try to change your web.xml into:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
rest of the TAGs
</web-app>
Also remove:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
(it's for 2.3 version)

Categories