Reset spring url. URL gets appended after submitting form twice - java

<form:form action="register/student.htm" method="post" modelAttribute="registerForm">
.....
</form:form>
When I initially submit this form the url is
"loclhost:8080/SpringSchool/register/student.htm"
If the submit fails and I submt it again, the new url gets appended and becomes:
"loclhost:8080/SpringSchool/register/register/student.htm"
As a result I get 404 error. How can I reset the url so that the url is not appended or just basically make this work?
#Controller
#RequestMapping("/register")
public class RegisterController {
#RequestMapping(method=RequestMethod.GET)
public ModelAndView registerPage(){
return new ModelAndView("registerStudent", "registerForm", new Student());
}
#RequestMapping(value="/student", method = RequestMethod.POST)
public ModelAndView registerStudent(#ModelAttribute("registerForm") final Student student, RedirectAttributes redirectAttr){
....
return new ModelAndView("registerStudent", "registerForm", student);
}
view resolver
<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>

If you start URL from '/' then it indicate the root of the context but if you start URL from word -- it means 'from the current path'. Your problem should be resolved if you add '/' to the URL:
<form:form action="/${pageContext.request.contextPath}/register/student.htm" method="post" modelAttribute="registerForm">
.....
</form:form>

This is because your form action is using a relative path. To fix your problem, you should organize your jsp in a folder and your controller should return views with the corresponding paths.
Move your jsp to:
/WEB-INF/jsp/register/registerStudent.jsp
Your controller should return the view name:
register/registerStudent
In your form, change action to:
<form:form action="student.htm" method="post" modelAttribute="registerForm">
.....
</form:form>

Related

SPRING MVC form:checboxes binding error

I am working on Spring MVC project. I am getting an error while binding the checkbox value to the back end file. Can any one please suggest whats the mistake or missing step please?
I have searched for similar threads but the answers did'nt solve my issue. Appreciate any help here.
Code:
JSP:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%#taglib uri = "http://www.springframework.org/tags/form" prefix = "form"%>
<%# page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<body>
<form:form modelAttribute="listOfShapes" action="/calculateArea">
<form:checkboxes items="${listOfShapes}" path="selectedShapes" />
</form:form>
</body>
</html>
MOdelAttribute:
#ModelAttribute("listOfShapes")
public List<String> getListOfShapes() {
List<String> shapesOfList = new ArrayList<String>();
shapesOfList.add("Circle");
shapesOfList.add("Rectangle");
shapesOfList.add("Square");
return shapesOfList;
}
POJO:
package model.pojo.org;
import java.util.List;
public class ListOfShapes {
private List<String> selectedShapes;
/**
* #return the selectedShapes
*/
public List<String> getSelectedShapes() {
return selectedShapes;
}
/**
* #param selectedShapes the selectedShapes to set
*/
public void setSelectedShapes(List<String> selectedShapes) {
this.selectedShapes = selectedShapes;
}
}
XML:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
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">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="calculate.area.org" />
</beans:beans>
I am getting the below Error. Can anyone please suggest?
org.springframework.beans.NotReadablePropertyException: Invalid property 'selectedShapes' of bean class [java.util.ArrayList]: Bean property 'selectedShapes' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
The Form Model should not be listOfShapes. The Form Model is what actually receives the input. So I believe this is wrong:
<form:form modelAttribute="listOfShapes" action="/calculateArea">
It's OK to use it as a Checkbox Display Constants getter in your <form:checkboxes items="${listOfShapes}" path="selectedShapes" /> but it's not OK to use it as an actual Form Model that gathers input. That would be your POJO instance, not a list of constants.
For example, see here:
http://www.baeldung.com/spring-mvc-form-tutorial
I assume you have a Controller that exposes the ModelAndView with the form model object, right? Something like
public String processForm(#ModelAttribute("employee")Employee employee,
BindingResult result, ModelMap model) {
}
in that case the Form Model would be
<form:form method="POST" action="/spring-mvc-xml/addEmployee" modelAttribute="employee">
as in that website example.

Can't load page in Spring MVC

I want to add a page in my spring MVC. I can call the index file but I can't click on the link in index.jsp to show page product.jsp. Its error message is "The requested resource is not available".
Below is my controller code:
#RequestMapping({"/", "/index"})
public String index(ModelMap model, HttpSession session, Principal principal) throws Exception {
return "index";
}
#RequestMapping({"/product"})
public String product(ModelMap model, HttpSession session, Principal principal) throws Exception {
return "product";
}
this index.jsp
<div class="row">
<div class="col-sm-4 menu-img-pad">
<ul class="multi-column-dropdown">
<li>Joggers</li>
<li>Foot Ball</li>
<li>Cricket</li>
</ul>
</div>
</div>
You need to define a ViewResolver in order to let spring how to find your views.
Have a look here. In your case an InternalResourceViewResolver would work.
An then -- in order to call your handler -- your link should look point to /product as you defined the path in your #RequestMapping method
Add below configuration to dispatcher-servlet.xml
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
In above configuration,views is folder name where container will look for your product.jsp file

Handling form validation with Thymeleaf 3.x - Stylizing errors

I'm testing for the first time Thymeleaf 3.x with a simples web app, and I'm having some issues doing form validation. I'm not able to change the graphical style of my form fields with the Thymeleaf attribute th:errorclass, and I don't know why.
Here is my controller:
#RequestMapping(value = {"/" , "" , "/home" , "/index" , "/login"} , method = RequestMethod.GET)
public String getLogin(final Model m)
{
if(m.containsAttribute("login") == false)
{
System.out.println("Creating login form...");
m.addAttribute("login", new For_Login());
}
return Util_Paginas.PAG_LOGIN.toString();
}
#RequestMapping(value = "/login" , method = RequestMethod.POST)
public String authenticate(
#Valid #ModelAttribute("login") final For_Login form ,
final BindingResult br ,
final Model m)
{
System.out.printf("Authentication received!%n");
System.out.printf("LOGIN: %s%n" , form.getLogin());
System.out.printf("PASS: %s%n" , form.getSenha());
if(br.hasErrors())
{
System.out.printf("Found %d fields!%n" , br.getErrorCount());
}
return Util_Paginas.PAG_LOGIN.toString();
}
My HTML file with Thymeleaf 3.x nature:
<!DOCTYPE html>
<html>
<head>
<title>Login page</title>
<link rel="stylesheet" type="text/css" media="all" th:href="#{/css/estilos.css}" />
</head>
<body>
<p>Welcome. Please login.</p>
<form action="#" th:action="#{/login}" th:object="${login}" method="post">
<fieldset>
<p>
Login:
<input
type="text"
th:field="*{login}"
th:class="campo"
th:errorclass="campo-invalido">
</p>
<p>
Password:
<input
type="password"
th:field="*{senha}"
th:class="campo"
th:errorclass="campo-invalido">
</p>
<p>
<input type="submit" value="Submit"/>
</p>
</fieldset>
</form>
</body>
</html>
My CSS file:
#CHARSET "ISO-8859-1";
.campo
{
background-color: gray;
border: 2px solid red;
}
.campo-invalido
{
background-color : #ff0000;
border: 1px solid #800000;
width: 230px;
color: white;
}
p
{
color: blue;
font-size: 22pt;
}
What is happening is that the style is not being applied. Errors are found on the server side, but when the page is returned, it is as if the th: errorclass attribute was not present. I do not know what I'm doing wrong.
I know that my css file is being read because the P tags are getting stylized.
I'm using:
Eclipse Mars.2 Release (4.5.2)
thymeleaf 3.0.3 RELEASE
thymeleaf-spring4 3.0.3 RELEASE
spring-webmvc 4.1.1 RELEASE
spring-context 4.1.1 RELEASE
validation-api 1.1.0 FINAL
hibernate-validator 5.3.4 FINAL
If in case someone wants to see some more code of my project, I'll be happy to present it here.
Thank you for your time and patience.
EDIT
I almost forgot something important too, my Spring MVC Application Context file:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
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.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">
<!-- ################################################################################### -->
<!-- MAPEAMENTO DE RECURSOS -->
<!-- ################################################################################### -->
<!-- Mapeamento de recursos (arquivos css, fontes, imagens, dentre outros). -->
<mvc:resources mapping="/css/**" location="/WEB-INF/recursos/css/" />
<mvc:resources mapping="/imagens/**" location="/WEB-INF/recursos/imagens/" />
<mvc:resources mapping="/fontes/**" location="/WEB-INF/recursos/fontes/" />
<!-- ################################################################################### -->
<!-- ANOTAÇÕES E RECURSOS SPRING -->
<!-- ################################################################################### -->
<!-- Possibilita o uso de anotações Spring Mvc. -->
<mvc:annotation-driven />
<!-- Define local para procura de componentes Spring (beans configurados
por anotações em classes). -->
<context:component-scan base-package="com.regra7.st.controle" />
<!-- ################################################################################### -->
<!-- INTERNACIONALIZAÇÃO -->
<!-- ################################################################################### -->
<!-- ################################################################################### -->
<!-- CONFIGURAÇÕES DO THYMELEAF -->
<!-- ################################################################################### -->
<!-- Template Resolver para Template Engine. -->
<!-- <bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" /> <property name="suffix"
value=".html" /> <property name="templateMode" value="HTML5" /> </bean> -->
<!-- SpringResourceTemplateResolver automatically integrates with Spring's
own -->
<!-- resource resolution infrastructure, which is highly recommended. -->
<bean id="templateResolver"
class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".html" />
<!-- HTML is the default value, added here for the sake of clarity. -->
<property name="templateMode" value="HTML" />
<!-- Template cache is true by default. Set to false if you want -->
<!-- templates to be automatically updated when modified. -->
<property name="cacheable" value="true" />
</bean>
<!-- SpringTemplateEngine automatically applies SpringStandardDialect and -->
<!-- enables Spring's own MessageSource message resolution mechanisms. -->
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<!-- Enabling the SpringEL compiler with Spring 4.2.4 or newer can speed
up -->
<!-- execution in most scenarios, but might be incompatible with specific -->
<!-- cases when expressions in one template are reused across different
data -->
<!-- ypes, so this flag is "false" by default for safer backwards -->
<!-- compatibility. -->
<property name="enableSpringELCompiler" value="true" />
</bean>
<!-- ################################################################################### -->
<!-- CONFIGURAÇÕES DO SPRING MVC -->
<!-- ################################################################################### -->
<!-- View resolver do Thymeleaf. -->
<bean class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
</bean>
<!-- Definição de HandlerMapping. -->
<!-- Cuida de classes controladoras. -->
<!-- <bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
</bean> -->
<!-- ################################################################################### -->
<!-- INTERCEPTADORES -->
<!-- ################################################################################### -->
<!-- INTERCEPTADORES -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/usuario/*" />
<bean class="com.regra7.st.interceptadores.Login" />
</mvc:interceptor>
</mvc:interceptors>
</beans>
EDIT 2
After messing around a bit with the validation code, I changed the approach used and suddenly, things started to work.
Previously, I was using bean validation with my own annotations for data validation. I decided to change to the validation done with Spring, using org.springframework.validation.Validator, And magically everything went well.
However, I would not like to use the data validation approach with Spring, but rather with bean validation annotations. I've figured out where I'm wrong, but I do not understand why.
I'll put my login validation code:
// My bean validation annotation.
#Documented
#Constraint(validatedBy = Val_Login.class)
#Target({ElementType.METHOD , ElementType.FIELD , ElementType.ANNOTATION_TYPE})
#Retention(RetentionPolicy.RUNTIME)
public #interface Login
{
String message() default "{com.regra7.st.login}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
int min() default 10;
int max() default 20;
}
// Validator implementation.
public class Val_Login implements ConstraintValidator<Login , String>
{
private int min;
// private int max;
#Override
public void initialize(Login login)
{
this.min = login.min();
// this.max = login.max();
}
#Override
public boolean isValid(String value, ConstraintValidatorContext context)
{
return Util_Validador.isLoginValido(value , this.min);
}
}
// The form input object.
public class For_Login
{
#Login(min = 8)
private String login;
// Many things ommited
}
The Util_Validador class is able to return a true or false value, this has already been tested. If I do this:
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import com.regra7.st.formularios.For_Login;
import com.regra7.st.util.Util_Texto;
public class ValidadorFormulario implements Validator
{
#Override
public boolean supports(Class<?> clazz)
{
return For_Login.class.isAssignableFrom(clazz);
}
#Override
public void validate(Object objeto, Errors erros)
{
For_Login log = (For_Login) objeto;
if(Util_Texto.isVazia(log.getLogin()) ||
log.getLogin().length() < 8)
{
erros.rejectValue("login", "Login errado!");
}
if(Util_Texto.isVazia(log.getSenha()) ||
log.getSenha().length() < 14)
{
erros.rejectValue("senha", "Senha errada!");
}
}
}
Everything works out. Can you guys help me a bit, please? I think this can help many people who get on the same place as me.
As always, thank you.
I did two things wrong:
I forgot to import some libraries needed by Hibernate Validator.
I was using prefixes for form fields (For_Login). The data binding
was not happening properly. Actually, it was, but Thymeleaf was not
recognizing it properly. It's no use having a field named _myField
(for instance), and setting setMyField and getMyField methods. Either
you write the field with the name myField, or the methods with the
names get_myField and set_myField.

Ajax post to Spring MVC controller results in "Requested resource is unavailable" error

I have been trying to get this code to work. I've just started with Spring MVC (and I'm relatively new to web dev - my background is GUI dev/science) but I think the error may be triggered because there is a problem linking the jquery code in my jsp to the Spring controller. I've literally been trying to get this to work for days without success and I've tried all the suggestions made by posters on this forum with a similar problem - to no avail. I'd therefore very much appreciate your input. The project is being developed using Netbeans, Tomcat 8, Maven, Spring MVC, and Jquery.
projectDashboard.jsp (in WEB-INF/views):
<div class="col-lg-8 col-md-8 col-sm-8">
<div id="projectForm">
<div class="form-group">
<input id="name" name="name" type="text" class="form-control" placeholder="Project name (50 characters or less)"/>
<textarea id="description" name="description" class="form-control" placeholder="Project Description (200 characters or less)"></textarea>
</div>
<div class="form-group">
<input class="btn btn-primary pull-right" id="createProjectButton" value="Create" type="button"/>
</div>
</div>
</div>
JQuery:
<script>
$(document).ready(function(){
$("#createProjectButton").on("click", function(){
var projectJson = {
"name":$("#name").val(),
"description":$("#description").val()
};
$.ajax({
type: "POST",
url: "/ProgressManagerOnline/projectDashboard",
data: JSON.stringify(projectJson),
contentType: "application/json; charset=utf-8",
dataType: "json"
});
});
});
</script>
ProjectDashboard.java (Spring MVC controller class in src/main/java):
#RequestMapping(value = "/projectDashboard", method = RequestMethod.POST)
public String saveProject(#RequestBody Project project) throws Exception {
return "OK";
}
Relevant code in appconfig-mvc.xml:
<mvc:annotation-driven/>
<mvc:view-controller path="/" view-name="login"/> //home web page - login.jsp
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Maven pom.xml includes:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.5</version>
</dependency>
Tomcat context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/ProgressManagerOnline"/>
Error in Firefox web console:
The requested resource is not available. (404 error)
My Project.java:
#Entity
#Table(name = "projects")
public class Project implements Serializable {
private Long id;
private String name;
private String description;
private java.util.Date dateCreated;
public Project(){};
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id){
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Column(name = "dateCreated", columnDefinition="DATETIME")
#Temporal(TemporalType.TIMESTAMP)
public Date getDateCreated() {
return dateCreated;
}
public void setDateCreated(Date dateCreated) {
this.dateCreated = dateCreated;
}
}
I've been at this for days now and have tried every suggestion posted on this forum and others.
Many thanks in advance to anyone who can help out.
You are missing couple of configurations I guess in your application.
You require auto conversion of json to java object ,
#RequestBody Project project
Hence you need to add json converter so please look documentation : http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/converter/json/MappingJackson2HttpMessageConverter.html
Add following in your configuration context xml along with required dependencies added in your pom.xml,
<!-- Configure bean to convert JSON to POJO and vice versa -->
<beans:bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<!-- Configure to plugin JSON as request and response in method handler -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonMessageConverter"/>
</list>
</property>
</bean>
(Posted on behalf of the OP).
The solution suggested by TechBreak worked - I was missing the Spring context dependency in my pom.xml and the extra config in my xml:
<!-- Configure bean to convert JSON to POJO and vice versa -->
<bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" />
<!-- Configure to plugin JSON as request and response in method handler -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jsonMessageConverter"/>
</list>
</property>
</bean>
After a restart of the server and
mvn clean install
Cheers.

Handle 404 errors in Spring?

Here is the code I have for redirecting unmapped requests to 404 page
#RequestMapping("/**")
public ModelAndView redirect() {
ModelAndView mv = new ModelAndView();
mv.setViewName("errorPage");
return mv;
}
The above code works fine but the problem is with the web resources like css and js files
also go inside this redirect method and it is not loading any of the files. But i already have this code in my dispatcher servlet,but spring controller is not recognizing this resources mapping.
<mvc:resources mapping="/resources/**" location="/WEB-INF/web-resources/" />
so i tried some regex expression in the request mapping to negate the resources url something like this
#RequestMapping("/{^(?!.*resources/**)}**")
public ModelAndView redirect() {
ModelAndView mv = new ModelAndView();
mv.setViewName("errorPage");
return mv;
}
But this is not working as expected ..So if anyone could help it would be great :)
I found the solution to handle 404 (Unmapped links), I used a SimpleUrlHandlerMapping to do this.
I added the below code to my dispatcher servlet .xml
<!-- Here all your resources like css,js will be mapped first -->
<mvc:resources mapping="/resources/**" location="/WEB-INF/web-resources/" />
<context:annotation-config />
<!-- Next is your request mappings from controllers -->
<context:component-scan base-package="com.xyz" />
<mvc:annotation-driven />
<!-- Atlast your error mapping -->
<bean id="errorUrlBean" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/**">errorController</prop>
</props>
</property>
</bean>
<bean id="errorController" class="com.xyz.controller.ErrorController">
</bean>
com.xyz.controller.ErrorController class
public class ErrorController extends AbstractController {
#Override
protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
// TODO Auto-generated method stub
ModelAndView mv = new ModelAndView();
mv.setViewName("errorPage");
return mv;
}
}
I found the below reasons
#RequestMapping("/**") uses RequestHandlerMapping and
<mvc:resources mapping="/resources/**" location="/WEB-INF/web-resources/" />
uses SimpleUrlHandlerMapping
RequestHandlerMapping takes presedence over SimpleUrlHandlerMapping, so that was the reason all resources request went inside the redirect method in my case.
So i just changed the #RequestMapping("/**") request to SimpleUrlHandlerMapping by configuring that as a bean as given above in my dipatcher servlet and mapped it at the last and it solved the problem.
Also add the below code to your web.xml
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/error.jsp</location>
</error-page>
Now this simple solution can be used to redirect all unmapped requests i.e) 404 errors to an error page :)

Categories