Cant validate form using BindingResult and tiles in Spring MVC - spring-mvc

Hi I am very new to Spring MVC. I am trying to create 1 login page with annotation based validation. Since I have kept #NonEmpty for user ID and password, I am expecting when user enters nothing and submit then validation should fail. But my if block(result.hasErrors()) in login controller is not getting executed when user do not enters anything.I have tried different approach but still no good result for me.
LoginController.java
public ModelAndView doLogin(HttpServletRequest request, #Valid #ModelAttribute("user") User user, BindingResult result, Model model) {
if(result.hasErrors()) {
return new ModelAndView("loginForm");
}
}
User.java
public class User {
#NonEmpty
private String userID;
#NonEmpty
private String password;
.
.
.
}
loginForm.jsp
<body>
<form:form modelAtrribute="user" method="POST" commandName="user">
User ID:
<input type="text" name="userID"/>
<form:errors path="userID"/>
Password:
<form:password path="password"/>
<form:errors path="password"/>
<input type="submit" value="Login"/>
</form>
</body>
spring-servlet.xml
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" id="viewResolver">
<property name="viewClass">
<value>
org.springframework.web.servlet.view.tiles2.TilesView
</value>
</property
</bean>
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</peroperty>
</bean>
tiles.xml
<tiles-definitions>
<definition name="plain.definition" template="/WEB-INF/plain/plain.jsp">
<put-attribute name="body" value=""></put-attribute>
</definition>
<definition extends="plain.definition" name="loginForm">
<put-attribute name="title" value="Login"></put-attribute>
<put-attribute name="body" value="/WEB-INF/jsp/loginForm.jsp"></put-attribute>
</definition>
</tiles-definitions>

Found solution for this problem. In my spring-servlet.xml I had <context:annotation-config> but not <mvc:annotation-driven />.
<context:annotation-config> supported some annotations but for #Valid I needed <mvc:annotation-driven />. After adding this my validations are running fine.
Though I have not figured out completely differences between these 2 tags.

Related

Next state is not getting called in spring web flow

I have Spring 3 application having Tiles2 as view resolver. Whenever I am clicking on "submit" button next jsp page should be displayed but it stays on same page.
I have a file WebFlow.xml file inside /WEB-INF/flow directory and JSPs are also in same folder.
My configuration as follows:
-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:flow="http://www.springframework.org/schema/webflow-config"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-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/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">
<mvc:annotation-driven/>
<context:component-scan base-package="com.controller.*"/>
<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.tiles2.TilesViewResolver"/>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles.xml</value>
</list>
</property>
</bean>
<flow:flow-executor id="flowExecutor" flow-registry="flowRegistry"/>
<flow:flow-registry id="flowRegistry">
<flow:flow-location path="/WEB-INF/flow/WebFlow.xml" id="flow"/>
</flow:flow-registry>
<bean id="flowHandlerMapping" class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
<property name="flowRegistry" ref="flowRegistry"/>
</bean>
<bean id="flowHandlerAdapter" class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
<property name="flowExecutor" ref="flowExecutor"/>
</bean>
</beans>
WebFlow.xml
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">
<var name="studentRegForm" class="com.formbean.flows.StudRegForm"/>
<view-state id="login" view="login">
<transition on="studentReg" to="studentReg"/>
</view-state>
<view-state id="studentReg" view="studentReg" model="studentRegForm">
<transition on="submitStudInfo" to="studConfirmPage"/>
</view-state>
<view-state id="studConfirmPage">
<transition on="submit" to="showStoredPage"/>
<transition on="Cancel" to="studentReg"/>
</view-state>
<end-state id="showStoredPage"/>
</flow>
login.jsp
<sf:form id="loginFrm" modelAttribute="loginForm" method="GET" action="${flowExecutionUrl}">
<input type="text" name="_flowExecutionKey" value="${flowExecutionKey}"/>
<input type="submit" value="Student Registration" name="_eventId_studentReg"/>
</sf:form>
StudentReg.jsp
<sf:form id="studRegFrm" modelAttribute="studentRegForm" method="GET" action="${flowExecutionUrl}">
<input type="text" name="_flowExecutionKey" value="${flowExecutionKey}"/>
<table>
<tr>
<td><sf:label path="name">Please Enter Name:</sf:label></td>
<td><sf:input path="name"/></td>
</tr>
<tr>
<td><sf:label path="address">Please Enter Address:</sf:label></td>
<td><sf:input path="address"/></td>
</tr>
<tr>
<td></td>
<td><input type="submit" name="_eventId_submitStudInfo" value="Submit"/></td>
</tr>
</table>
</sf:form>
tiles.xml
<tiles-definitions>
<definition name="mainLayout" template="/WEB-INF/jsp/layout/mainLayout.jsp">
<put-attribute name="Title" value=""/>
<put-attribute name="Header" value="/WEB-INF/jsp/layout/Header.jsp"/>
<put-attribute name="Body" value=""/>
<put-attribute name="Footer" value="/WEB-INF/jsp/layout/Footer.jsp"/>
</definition>
<definition name="login" extends="mainLayout">
<put-attribute name="Title" value="Start Page"></put-attribute>
<put-attribute name="Body" value="/WEB-INF/flow/login.jsp"/>
</definition>
<definition name="studentReg" extends="mainLayout">
<put-attribute name="Title" value="Registration Page"></put-attribute>
<put-attribute name="Body" value="/WEB-INF/flow/StudentReg.jsp"/>
</definition>
</tiles-definitions>
But whenever I am clicking on submit button of login.jsp, it gives ${flowExecutionUrl} & ${flowExecutionKey} as blank and next screen is not displaying. Am I missing some configuration or what's going wrong? Please help.
#Aasif your configuration 'looks' fine. SWF is notoriously un-intuitive to trouble shoot. Try inserting a logger into your flows like this:
Printing log from flow.xml
and determine where the the 'flow' execution is being interrupted. Once you isolate the location. Try to step into the flow code... I suspect an exception is being swallowed.
Possible Answer:
If I had to guess (even though your config looks correct). I would suspect SWF/tiles is NOT resolving the view name 'studentReg'. Try isolate this case by creating a separate flow and see if you can navigate to the view studentReg. You can also step into the Tiles resolver logic to make sure it is being located.
Also:
In my opinion, it is bad practice to give the same name to your viewStateId, transition, and viewName (i.e 'studentReg'). I think it makes trouble shooting more difficult when issues like this arise. Better to append a suffix to them. (i.e studentRegVsId, studentRegViewName, etc...) to create a distinction.

Spring mvc: Controller Result resent to RequestMappingHandlerMapping

I have an abstract Spring Controller class extended by various controllers.
Example method:
#Override
#RequestMapping(value = { "/", "" }, method = RequestMethod.GET)
public String getAllAsView(#RequestParam(required = false) boolean ajax,
Model m) {
String mapping = elementClass.getSimpleName();
m.addAttribute(mapping + "List", getAll());
return mapping + "All" + (ajax ? "Ajax" : "");
}
These are the relevant definitions in my view.xml:
<definition name="maintemplate" template="/WEB-INF/views/main_template.jsp">
<put-attribute name="top" value="/WEB-INF/views/header.jsp" />
<put-attribute name="side" value="/WEB-INF/views/menu.jsp" />
</definition>
<definition name="ajaxtemplate" template="/WEB-INF/views/ajax_template.jsp">
<put-attribute name="top" value="/WEB-INF/views/header.jsp" />
</definition>
<definition name="PersonAll" extends="maintemplate">
<put-attribute name="content" value="/WEB-INF/views/personlist.jsp" />
</definition>
<definition name="PersonAllAjax" template="ajaxtemplate">
<put-attribute name="content" value="/WEB-INF/views/personlist.jsp" />
</definition>
With the ajax parameter only the body content is to return.
Everything works fine without the ajax parameter.
But with the Ajax parameter the return string is used for a new Controller request.
This is the Log:
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /person/6
TRACE: org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod - Invoking [PersonController.getAsView] method with arguments [6, true, {}]
WARN : de.kreth.clubhelperbackend.aspects.DaoLoggerAspect - de.kreth.clubhelperbackend.dao.PersonDao.getById(6) ==> 6: M Kreth
TRACE: org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod - Method [getAsView] returned [PersonGetAjax]
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Looking up handler method for path /person/ajaxtemplate
This is the servlet-context.xml:
<?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:context="http://www.springframework.org/schema/context"
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">
<context:component-scan base-package="de.kreth.clubhelperbackend" />
<mvc:annotation-driven>
<mvc:message-converters>
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean
class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean">
<property name="dateFormat">
<bean class="java.text.SimpleDateFormat">
<constructor-arg type="java.lang.String"
value="dd/MM/yyyy HH:mm:ss.SSS Z"></constructor-arg>
</bean>
</property>
</bean>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" />
<bean class="org.springframework.web.servlet.view.tiles2.TilesViewResolver">
<property name="order" value="1" />
</bean>
<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/views/**/views.xml</value>
</list>
</property>
</bean>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
I am stuck finding out what is happening here. I changed the template name and the new name was used for the request.
The problem came up, after I changed nearly all xml files in project. I inserted Doctype tag and changed schema definitions and stuff. Because that caused heavy problems I stepped back to a working version. Before that, the ajax parameter worked.
Ah - and I updated to java-version 1.6.
Any ideas why spring uses the templatename "ajaxtemplate" as a new request and sends it back to the controller?
Best regards
Markus
Stupid mistake: never programm past midnight:
<definition name="PersonAllAjax" template="ajaxtemplate">
<put-attribute name="content" value="/WEB-INF/views/personlist.jsp" />
</definition>
must be
<definition name="PersonAllAjax" extends="ajaxtemplate">
<put-attribute name="content" value="/WEB-INF/views/personlist.jsp" />
</definition>

How to execute a spring batch job by clicking on a button in a jsp page?

I'm a newbie in spring batch and spring Mvc, and I want that a batch job (which extracts data from a database and writes it in another database) is executed from a jsp page by clicking on a button (or a link if it's possible) I'm using spring Mvc. This is my job configuration:
<bean id="jobRepository"
class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseType" value="oracle" />
</bean>
<bean id="itemReader"
class="org.springframework.batch.item.database.JdbcCursorItemReader"
scope="step">
<property name="dataSource" ref="dataSource" />
<property name="sql"
value="select id,name,qual from users" />
<property name="rowMapper">
<bean class="tn.com.spring.UserRowMapper" />
</property>
</bean>
<bean id="oracleitemWriter"
class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource" />
<property name="sql">
<value>
<![CDATA[
insert into users2(id,name,qual)
values (:id,:name,:qual)
]]>
</value>
</property>
<property name="itemSqlParameterSourceProvider">
<bean
class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider" />
</property>
</bean>
<batch:job id="Job" job-repository="jobRepository">
<batch:step id="step1">
<batch:tasklet transaction-manager="transactionManager">
<batch:chunk reader="itemReader" writer="oracleitemWriter"
commit-interval=" 10">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<jdbc:initialize-database data-source="dataSource">
<jdbc:script
location="org/springframework/batch/core/schema-drop-oracle10g.sql" />
<jdbc:script location="org/springframework/batch/core/schema-oracle10g.sql" />
</jdbc:initialize-database>
and this is my job controller (I found it in the net but still not working!)
#Component
#Controller()
public class JobController {
#Autowired
#Qualifier("JobLauncher")
private JobLauncher jobLauncher;
#Autowired
#Qualifier("Job")
private Job job;
#RequestMapping(value = "/job")
public void job() {
try {
JobExecution execution = jobLauncher.run(job, new JobParameters());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
and here is the button
<form action=" <%=application.getContextPath()%>/job" method="get">
<input type="submit" value="execute My job" />
</form>
Could you please help me ? Whats's missing in my configuration?
I'm confused !
Thanks in advance.
As a solution for this problem, I have made this javascript code which will invoke the execution of the job :
$(function() {
$('#JobBtn').click(function() {
$.get('${batchJobUrl}');
});
});
and in the jsp page you need to specify the Id of the button writen in the javascript code:
<input type="button" value="execute job " id='JobBtn' class="btn" />
I Hope it will help someOne..

Rss feeds and apache tiles with Spring MVC

I;m trying to create RSS feeds for my web site. I follow the tutorial from mkyong (http://www.mkyong.com/spring-mvc/spring-3-mvc-and-rss-feed-example/) which was quite useful. According to this tutorial i create a model class and the following class
public class CustomRssViewer extends AbstractRssFeedView{
#Override
protected void buildFeedMetadata(){
//some code
}
#Override
protected List<Item> buildFeedItems(){
//some code
}
}
And finally the controller class
#Controller
public class RssController {
#RequestMapping(value="/rssfeed", method = RequestMethod.GET)
public ModelAndView getFeedInRss() {
//set the RSS content
ModelAndView mav = new ModelAndView();
mav.setViewName("rssViewer");
mav.addObject("feedContent", items);
return mav;
}
}
According to the tutorial the View rssViewer belongs the class CustomRssViewer , so i need to write it at the dispatcher servlet the following lines of code:
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
<bean id="rssViewer" class="com.mkyong.common.rss.CustomRssViewer" />
My problem is that i'm using apache tiles. So the rssViewer can not be recognised as i didn't enhanced it to the tiles definition. And i really don't know how can i do this. For example i need to write something as the following:
<definition name="rssViewer" template="?">
<put-attribute name="title" value=""/>
<put-attribute name="content" value=""/>
</definition>
At the template i don't know what to declare as well as at the put-attribute.Because until now at the template i use to declare the direction that a specific jsp exists. Something like this:
template="/WEB-INF/pages/mypage.jsp"
And also at the view-properties i don't know what should i declare.
Thanks in advance for any comment or response.
You should use a ContentNegotiatingViewResolver in conjuction with that example's BeanNameViewResolver. Just declare the order property of your already existing BeanNameViewResolver to be 1, and set the order property of the new ContentNegotiatingViewResolver to 0.
You should then configure the ContentNegotiatingViewResolver to use the appropriate View for RSS, and set the media type for RSS.
Here is an example from the Spring Docs:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="atom" value="application/atom+xml"/>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>
Note, they are using atom, not RSS, but the idea is the same. Also they do not set the order (which you should do).

Spring MVC, Tiles, Multiple Controllers

I'm experimenting with Spring MVC for an upcoming project. I'll need some web pages in the application to render multiple reusable "components" and figured that Tiles should help me accomplish this? Each component would have it's own controller.
The example I've put together is only partially working. It's a page with 3 tiles. The 3rd tile has a controller that's trying to return an ArrayList (via #ModelAttribute annotation) to the client but the ArrayList is empty when the view is included as a tile.
Here's the tiles setup in *-servlet.xml:
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
<property name="order" value="0"/>
</bean>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tiles-config/tiles.xml</value>
</list>
</property>
</bean>
<bean id="viewResolver2" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="1" />
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
Here's my tiles config (tiles.xml):
<tiles-definitions>
<definition name="parent" template="/WEB-INF/jsp/tiles/parent_layout.jsp">
<put-attribute name="header" value="/WEB-INF/jsp/tiles/header.jsp"/>
<put-attribute name="body" value=""/>
<put-attribute name="recordsSection" value=""/>
<put-attribute name="widgetsSection" value=""/>
</definition>
<definition name="_n/list.htm" extends="parent">
<put-attribute name="recordsSection" value="/WEB-INF/jsp/_n/list.jsp"/>
<put-attribute name="widgetsSection" value="/WEB-INF/jsp/_n/widgets.jsp"/>
</definition>
</tiles-definitions>
Here's the JSP code behind the tile in question. The "widgetsList" expression is what is bound to the controller method but coming back empty when this view is included as a tile.
<%#page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" isELIgnored="false"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%#taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%#taglib prefix="display" uri="http://displaytag.sf.net" %>
<h3>Widgets</h3>
<p>widgetsList=${widgetsList}</p>
<div id="displaylist">
<display:table id="items" name="${widgetsList}" cellspacing="0" export="true">
<display:column title="Widget ID" property="widgetId"/>
<display:column title="Widget Name" property="widgetName"/>
<display:column title="Widget State" property="widgetState"/>
</display:table>
</div>
Here's the controller:
#Controller
public class WidgetController {
#Autowired
private WidgetDaoImpl widgetDao = new WidgetDaoImpl();
#RequestMapping("_n/widgets.htm")
public String widgets() {
return "_n/widgets.htm";
}
#ModelAttribute("widgetsList")
public ArrayList<Widget> getWidgets() {
System.out.println("executing getWidgets()");
ArrayList<Widget> records = widgetDao.listWidgets();
return records;
}
}
When I access the the view "widgets.jsp" directly, the "widgetsList" attribute gets populated, it's only when it's added as a tile that it returns nothing.
Tiles only gives you a composite view and with Spring MVC a controller can only return one view, in this case a whole tiles-defined page will be returned by a single controller.
I don't have much experience with tiles configuration, but what you're trying to achieve is only possible if you can have controller-mapped URLs (and not JSPs) as tiles elements, so that the tiles processor will invoke the spring controllers for each of the "components".
But since you're talking about components and you seem to need them here, why not start with a component oriented framework (Wicket for instance can easily be integrated with Spring out-of-the box).
A pattern i found great while doing this is using jQuery, ajax and json with tiles. On the pages you want your widgets include a marker div like
<div id="displayWidgets"></>
With jQuery check for this div on page load and if it exists do a json call to the controller for this content.
This approach is great because when you include the javascript below, the controller for each page doesn't need to know about any model information except its own. I use this for populating common information like headers and footers that are dynamic.
$.ready(){
if($('div#displayWidgets')){
$.getJSON('/widgetsList', function(data) {
//loop over json and create your html, url below has great examples
}
}
}
http://api.jquery.com/jQuery.getJSON/
Json tutorial from spring controller using jackson
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/

Resources