Using SPRING_SECURITY_LAST_USERNAME in a Thymeleaf template - spring-mvc

I've got a login form rendered by ThymeLeaf and powered by Spring Security. If an authentication error occurs, I'd like the username field to be pre-populated with the value the user entered on their previous attempt. Spring Security provides SPRING_SECURITY_LAST_USERNAME for that purpose, but my searches of the documentation and online don't turn up how to expose that via ThymeLeaf. Below are simplified versions of the relevant files:
My security XML file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<sec:http auto-config="true">
<sec:intercept-url pattern="/login/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<sec:form-login login-page="/login" authentication-failure-url="/login/fail" default-target-url="/"/>
<sec:logout />
</sec:http>
<sec:global-method-security secured-annotations="enabled"/>
</beans>
login.html:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head th:include="template::head"></head>
<body class="login">
<nav th:include="template::nav"></nav>
<div>
<h2>Log in</h2>
<div>
<div th:if="${loginFail}" class="error">
Username/password incorrect.
</div>
<form id="login" th:action="#{/j_spring_security_check}" method="POST">
<dl>
<dt>Username</dt>
<dd><input type="text" id="j_username" name="j_username" />#mshare.net</dd>
<dt>Password</dt>
<dd><input type="password" id="j_password" name="j_password" /></dd>
</dl>
<input type="submit" value="Log in" />
</form>
</div>
</div>
</body>
</html>
Controller error handler:
#RequestMapping(value = "/login/fail")
public String loginError(Model model) {
model.addAttribute("loginFail", Boolean.TRUE);
return "login";
}

Related

Validation not happening for custom login page in Spring security

I am trying execute sample example for spring security using custom login page.The application is not throwing any error.From home.jsp, it is navigating into custom login page but even after entering correct user id and password it is going back to home.jsp instead of hello.jsp without showing any error.Requesting your help in identifying the error.
hello.jsp
<%# taglib prefix="c" uri="/WEB-INF/tld/c.tld" %>
<html>
<body>
<h3>message : ${message}</h3>
<h3>User name : ${username}</h3>
LogOut
</body>
</html>
home.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h3>Welcome to spring security</h3>
<b>Click here to logon</b>
</body>
</html>
login.jsp
<%# taglib prefix="c" uri="/WEB-INF/tld/c.tld"%>
<html>
<head>
<title>Login Page</title>
<style>
.errorblock {
color: #ff0000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
</head>
<body onload='document.f.j_username.focus();'>
<h3>Login with Username and Password (Custom Page)</h3>
<c:if test="${SPRING_SECURITY_LAST_EXCEPTION !=null}"><!-- ${not empty error} -->
<div class="errorblock">
Your login attempt was not successful, try again.<br /> Caused :
${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
</div>
</c:if>
<form name='f' action="<c:url value='j_spring_security_check' />"
method='GET'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='j_username' value=''>
</td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='j_password' />
</td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit"
value="submit" />
</td>
</tr>
<tr>
<td colspan='2'><input name="reset" type="reset" />
</td>
</tr>
</table>
</form>
</body>
</html>
web.xml
<?xml version="1.0"?>
<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4" id="WebApp_ID">
<display-name>Spring MVC</display-name>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml,/WEB-INF/spring-security.xml
</param-value>
</context-param>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
mvc-dispatcher-servlet.xml
<?xml version="1.0"?>
<beans xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns="http://www.springframework.org/schema/beans">
<context:component-scan base-package="test"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>mymessages</value>
</list>
</property>
</bean>
</beans>
LoginController.java
package test;
import java.security.Principal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
public class LoginController {
#RequestMapping(value = "/welcome", method = RequestMethod.GET)
public String printWelcome(ModelMap model,Principal principal) {
System.out.println("*****Hello controller called***");
String name = principal.getName();
model.addAttribute("username", name);
model.addAttribute("message","spring security custom form example");
return "hello";
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(ModelMap model) {
return "login";
}
#RequestMapping(value = "/loginfailed", method = RequestMethod.GET)
public String loginerror(ModelMap model) {
model.addAttribute("error","true");
return "login";
}
#RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout(ModelMap model) {
return "login";
}
#RequestMapping(value = "/*", method = RequestMethod.GET)
public String home(ModelMap model) {
return "home";
}
}
spring-security.xml
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-4.2.xsd">
<!-- <http auto-config="true">
<intercept-url pattern="/welcome*" access="hasRole('ROLE_USER')" />
<http-basic />
</http> -->
<!-- <http>
<intercept-url pattern="/welcome*" access="hasRole('ROLE_USER')"/>
<form-login/>
<logout logout-success-url="/home"/>
</http> -->
<http>
<intercept-url pattern="/welcome*" access="hasRole('ROLE_USER')"/>
<form-login login-page="/login" default-target-url="/welcome" authentication-failure-url ="/loginfailed" />
<logout logout-success-url="/logout"/>
<csrf disabled="true"/>
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="rahul" password="123" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
Try to add those parameters to your spring security form login to make sure your named requests parameters are correct.
<form-login login-page="/login" username-parameter="j_username"
password-parameter="j_password" default-target-url="/welcome"
authentication-failure-url ="/loginfailed" />
Also make sure to change your form:
<form name='loginForm'
action="<c:url value='j_spring_security_check' />" method='POST'>
Also your logout should be a POST, a GET is not supported for logout. Actually you don't need it. Just do something like:
<c:url value="/j_spring_security_logout" var="logoutUrl" />
<form action="${logoutUrl}" method="post" id="logoutForm">
</form>

responses with characteristics not acceptable according to the request "accept" headers

I am using Spring MVC. trying to send list of POJO objects to the jsp page, but I m getting the following line error at web browser:
Please help me.
Error Message
HTTP Status 406 -
The resource identified by this request is only capable of generating
responses with characteristics not acceptable according to the request
"accept" headers.
Code Snap Shot :
1. Controller
#RequestMapping(value="displayUsers", method=RequestMethod.GET)
public #ResponseBody ModelAndView showUsers(HttpServletRequest request){
ModelAndView objModel=new ModelAndView();
UserDAO objUserDAO=DAOFactory.getInstanceOfUser();
// fetching list of all the users
List<User> listOfUser=objUserDAO.listOfUser();
objModel.addObject("listOfUser", listOfUser );
objModel.setViewName("showuser");
return objModel;
}
2. User DAO:
public List<User> listOfUser(){
SessionFactory factory=HibernateUtils.getInstance();
Session session=factory.openSession();
String hqlQuery="From User u";
Query query=session.createQuery(hqlQuery);
List<User> list=query.list();
return list;
}
3. Link to call showUser.jsp from register.jsp
Show Users
4. showuser.jsp :
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
<%# include file="genericinclude.jsp"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
</head>
<body>
<h2 align="center"><u>User List</u></h2>
<form name="showUserPage" method="post">
<table align="center" border="0">
<c:forEach var="userList" items="${listOfUser}">
<tr>
<td>${userList.userId }</td>
<td>${userList.firstName }</td>
<td>${userList.lastName}</td>
<td>${userList.userGender }</td>
<td>${userList.roll }</td>
<td>${userList.userMobile1 }</td>
<td>${userList.userMobile2 }</td>
<td>${userList.userEmail }</td>
<td> Edit /
<font color="red">Delete</font>
</td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
5. dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<context:component-scan base-package="com.marse.*"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" id="jspViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
Just remove the annotation '#ResponseBody' from the Controller method
#RequestMapping(value="displayUsers", method=RequestMethod.GET)
public ModelAndView showUsers(HttpServletRequest request){
// code...
}

Spring Security redirects to forbidden page(403)

I am using spring-security on top of spring-mvc application. Few points about the application I am working on.
Home page is login page i.e /users(). Login menu served as HTML dropdown menu.
Implementing userDetailsService() and UserDetails() instead of AuthenticationManager/provider
Required is person to view the home page without any roles.
Current situation :
Redirects it to 403 page mentioned in the entrypoint-ref.
No idea how to redirect it to user.jsp or /users
All examples I can find on net somehow show same stuff which is implementing `AuthenticationManager. Some code :
security-context.xml
<import resource="servlet-context.xml" />
<!-- Global Security settings -->
<security:global-method-security pre-post-annotations="enabled" />
<!-- Spring Security framework settings -->
<security:http pattern="/users" use-expressions="true" auto-config="true" disable-url-rewriting="true" entry-point-ref="formAuthenticationEntryPoint">
<security:session-management>
<security:concurrency-control max-sessions="5" error-if-maximum-exceeded="false"/>
</security:session-management>
<security:intercept-url pattern="/*" requires-channel="any" access="permitAll" />
<security:intercept-url pattern="/**" requires-channel="any" access="permitAll" />
</security:http>
<!-- queries to be run on data -->
<beans:bean id="formAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>
<bean id="LoginServiceImplementation" class="com.WirTauschen.service.LoginServiceImpl"></bean>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="userDetailsService" />
</security:authentication-manager>
</beans>
LoginServiceImpl :
#Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{
#Autowired private UserDao userDao;
#Autowired private Assembler assembler;
#Override
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails userDetails = null;
User user = userDao.findByName(username);
if(user == null) { throw new UsernameNotFoundException("Wrong username or password");} //Never specify which one was it exactly
return assembler.buildUserFromUserEntity(user);
}
}
Login-form(part of hompage HTML code enveloped in user.jsp)
<nav class="col-lg-5 col-md-5 col-sm-5">
<ul class="pull-right">
<li class="purple"><i class="icons icon-user-3"></i> Login
<ul id="login-dropdown" class="box-dropdown">
<li>
<form id="form" action="<c:url value='/login'/>" method="POST">
<div class="box-wrapper">
<h4>LOGIN</h4>
<div class="iconic-input">
<input type="text" placeholder="Username" name="username" id="username" value="">
<i class="icons icon-user-3"></i>
</div>
<div class="iconic-input">
<input type="password" placeholder="Password" name="password" id="password" value="">
<i class="icons icon-lock"></i>
</div>
<input type="checkbox" id="loginremember"> <label for="loginremember">Remember me</label>
<br>
<br>
<div class="pull-left">
<input name="submit" type="submit" class="orange" value="Login">
</div>
<div class="pull-right">
Forgot your password?
<br>
Forgot your username?
<br>
</div>
<br class="clearfix">
</div>
<div class="footer">
<h4 class="pull-left">NEW CUSTOMER?</h4>
<a class="button pull-right" href="create_an_account.html">Create an account</a>
</div>
</form>
</li>
</ul>
</li>
<li><i class="icons icon-lock"></i> Create an Account</li>
</ul>
</nav>
Form-login from security-applicationContext.xml
<security:form-login login-page="/users" default-target-url="/users"/>
Any help would be nice. Never knew spring-security will be nothing but torture.
UPDATE
You have to understand how Spring works: the client tries to get to a protected resource (users page, for example); if he did not login yet, he is being redirected (Spring redirects him) to the login page.
In your Spring beans.xml you declare what is your login page. If you put there "/login.html", you have to make sure that you have this kind of page, with the login form. After the user logs in, Spring will redirect him back to the /users.
Makes sense?
UPDATE II
You can make (like Amazon...) a landing page (e.g. index.html) which is public, meaning users can see it without logging in. Then, there are links there to 'protected resources', and if a user try to click on it and get the protected resource, Spring will redirect him to the login page. If you wanna do that, you put you 'protected resources' under a specific directory (e.g. /secured) and you place there all protected resources HTML/JSP/etc. You configure this in the beans.xml: (note here that 'welcome' page is non-secured, everybody will be able to see it without login)
<sec:http pattern="/welcome" security="none" />
<sec:http authentication-manager-ref="authenticationManager">
<sec:intercept-url pattern="/secure/**" access="ROLE_USER" />

HTTP Status 404 Servlet-The requested resource is not available [duplicate]

This question already has answers here:
Servlet returns "HTTP Status 404 The requested resource (/servlet) is not available"
(19 answers)
Closed 6 years ago.
I am making one simple program to take few fields as input and then after clicking on confirm button confirm.jsp will appear.
I have created Controller.java servlet to identify the button clicked and then open the jsp.
Controller.java is stored in directory WEB-INF/classes/ch2/servletController and submit.jsp,register.jsp,confirm.jsp are stored in /ch2/servletController directory.
Whenever i click on confirm button, i get below error. WebApplication is the name of my project. I am using netBeans IDE.
HTTP Status 404 - /WebApplication/ch2/servletController/Controller
type Status report
message /WebApplication/ch2/servletController/Controller
description The requested resource is not available.
Please find below web.xml,servlet and all the jsp files..
register.jsp
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>Register</title>
</head>
<body>
<form method="get" action="Controller">
<p><b>E-store</b></p>
<br>
<br>
<p>Enter First Name: <input type="text" name="FirstName" value="${param.FirstName}"></p>
<p>Enter Last Name: <input type="text" name="LastName" value="${param.LastName}"></p>
<p>Enter Mail-id: <input type="text" name="MailId" value="${param.MailId}"></p>
<p>Enter PhoneNo: <input type="text" name="PhoneNo" value="${param.PhoneNo}"></p>
<p><input type="submit" name="confirmButton" value="confirm"></p>
</form>
</body>
</html>
confirm.jsp
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>Confirm Details</title>
</head>
<body>
<form method="get" action="Controller" >
<p><b>E-store</b></p>
<br>
<br>
<p>First Name: ${param.FirstName}<input type="hidden" name="FirstName" value="${param.FirstName}"></input></p>
<p>Last Name: ${param.LastName}<input type="hidden" name="LastName" value="${param.LastName}"></input></p>
<p>Mail-id: ${param.MailId}<input type="hidden" name="MailId" value="${param.MailId}"></input></p>
<p>PhoneNo: ${param.PhoneNo}<input type="hidden" name="PhoneNo" value="${param.PhoneNo}"></input></p>
<input type="submit" name="EditButton" value="Edit">
<input type="submit" name="Submitbutton" value="Submit">
</form>
</body>
</html>
submit.jsp
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>Confirm Details</title>
</head>
<body>
<form>
<p><b>E-store</b></p>
<br>
<br>
<p>Thank You for the registration. Your details have been submitted as follows-</p>
<p>First Name: ${param.FirstName}<input type="hidden" name="FirstName" value="${param.FirstName}"></input></p>
<p>Last Name: ${param.LastName}<input type="hidden" name="LastName" value="${param.LastName}"></input></p>
<p>Mail-id: ${param.MailId}<input type="hidden" name="MailId" value="${param.MailId}"></input></p>
<p>PhoneNo: ${param.PhoneNo}<input type="hidden" name="PhoneNo" value="${param.PhoneNo}"></input></p>
</form>
</body>
</html>
Controller.java
package ch2.servletController;
import java.io.IOException;
import javax.servlet.http.*;
import javax.servlet.http.HttpServlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
public class Controller extends HttpServlet
{
#Override
protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException
{
String address=null;
if(request.getParameter("confirmButton")!= null)
{
address="confirm.jsp";
}
else if(request.getParameter("EditButton")!= null)
{
address="register.jsp";
}
else if(request.getParameter("Submitbutton")!=null)
{
address="submit.jsp";
}
RequestDispatcher Dispatcher=request.getRequestDispatcher(address);
Dispatcher.forward(request, response);
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>FirstController</servlet-name>
<servlet-class>ch2.servletController.Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FirstController</servlet-name>
<url-pattern>/Controller</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
index.jsp
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>First JSP</title>
</head>
<body>
<form>
<p><b>Welcome to E-store</b></p>
<br>
<br>
<p>Click to Register</p>
</form>
</body>
</html>
I'd be grateful if anyone can help me to solve this problem.
Many Thanks in Advance.
I had to change the location of register.jsp to web directory where index.jsp is located and it worked for me.

Question about spring #ModelAttribute taking any arbitrary string

While taking lessons in spring3 I coded a sample from a tutorial. I created a controller as below
package my.spring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import my.spring.form.Contact;
#Controller
public class ContactController {
#RequestMapping(value ="/addContact",method =RequestMethod.POST)
public String addContact(#ModelAttribute("contact") Contact ct){
System.out.println("First Name:" + contact.getFirstname() + "Last Name:" + contact.getLastname());
return "redirect:contacts.htm";
}
#RequestMapping("/contacts")
public ModelAndView showContacts() {
System.out.println("showing contacts");
return new ModelAndView("contact", "userEntries", new Contact());
}
}
Then I decided to play around with it and modified the #ModelAttribute in method parameter from
public String addContact(#ModelAttribute("contact") Contact ct)
to
public String addContact(#ModelAttribute("somevalue") Contact ct)
Still I couldn't find any change in behaviour of the application. This was a bit of surprise for me. As I understood, the data from form is collected in a Contact object and using #ModelAttribute that object is bound to the parameter ct. This parameter is then used to process inside the method.
Is it that the actual string used inside #ModelAttribute( ) doesn't matter?
Here is the WEB-INF/jsp/contact.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Contact Manager</title>
</head>
<body>
<h2>Contact Manager</h2>
<form:form action="addContact.htm" commandName="userEntries">
<table>
<tr>
<td>
<form:label path="firstname">First Name</form:label>
</td>
<td>
<form:input path="firstname"/>
</td>
</tr>
<tr>
<td>
<form:label path="lastname">Last Name</form:label>
</td>
<td>
<form:input path="lastname"/>
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Add Contact"/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
and the spring servlet configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="my.spring.controller" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Finally, the index.jsp forwards to contacts
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>my index</title>
</head>
<body>
<jsp:forward page="contacts.htm"></jsp:forward>
</body>
</html>
It will be used for mapping the model attribute to the form:
<form:form modelAttribute="myObject">
</form>
You will have to use
public String controllerMethod(#ModelAttribute("myObject") Object obj){
....
}
If you don't use the same value in both model attribute values you won't be able to see the error messages of the validation (when doing in the controller result.rejectValue and in the jsp <form:errors/> tag).
There are no differences to populate the values from the form in the object because you can use html tags instead of spring tags, and in the html tags you only have the name attribute to map the value.
In case you use #ModelAttribute in a method like below, you will insert in the model an attribute named "myObject" with value the object returned. This is another feauture of this annotation and it will be invoked before any method of the controller.
#ModelAttribute("myObject") Object obj
public Object method(){
...
return obj;
}

Resources