How to redirect page after ajax complete? - spring

My ajax is performing successfully because it deletes the row from database :
#Controller
...
#ResponseBody
#RequestMapping(value = "/ajaxDeleteUser", method = RequestMethod.POST)
public ModelAndView ajaxDelUser(HttpServletRequest request) {
int userId = Integer.parseInt(request.getParameter("id"));
userDao.delete(userId);
return new ModelAndView("redirect:/");
}
...
At the view :
<c:url value="/" var="home" scope="request" />
$.ajax({
data: {"id":data},
type: "POST",
url: "${home}"+"ajaxDeleteUser",
async: false
});
The problem is that after the ajax is complete then I saw the row on the list ! So how to redirect to the list actual page after ajax complete ?
UPDATE :
Here is servlet-context.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="com.ambre.hib" />
</beans:beans>
And here is 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">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

Consider using "success" event: http://api.jquery.com/Ajax_Events/
$.ajax({
data: {"id":data},
type: "POST",
url: "${home}"+"ajaxDeleteUser",
async: false,
success: function(result) {
location.href = "your_location"
}
});

You've got two options here. First, you can redirect on the front end after the ajax completes using the ajax success function like below:
success: function(result) {
location.href = "your_location"
}
Or preferably you can do it on the backend using spring mvc do the job. For this purpose remove the #Responsebody cuz you don't need it (you are not returning anything) and also change the return type to a String like below.
#RequestMapping(value = "/ajaxDeleteUser", method = RequestMethod.POST)
public String ajaxDelUser(HttpServletRequest request) {
//your stuff goes here
....
//important line
return "redirect:/index.html";
}
Here I am using index.html but change the name to your preferred page. As long as you've configured the Spring view resolver properly then it should work by itself. If you've put a suffix in the view resolver (for example .jsp) then you should return just the name of the page without the suffix and spring will figure out the page automatically like below
return "redirect:/index"; //equals index.jsp

You can Use this.This will redirect after response has arrived.
$.ajax({
data:{"id":data},
type: "POST",
url: "${home}"+"ajaxDeleteUser",
async: false,
success: function(result) {
var link = "http://www.sample.com";
$(location).attr('href',link);
});

Related

Spring security j_spring_security_check call gives 404 not found error [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I am trying to create a login authentication with spring security. I am receiving a 404 not found error for my login url /knowledgeBase/j_spring_security_check. I have correctly defined my custom filter and my url in the security xml. Also I added a security filter in the web xml file. I am calling this url via an ajax request by serializing the form data. I had this code working in another project seuccessfully but now I am getting this error. What might be the cause?
This is security.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Disabled Security for Static Resources -->
<global-method-security pre-post-annotations="enabled" secured-annotations="enabled"/>
<http pattern="/static/**" security="none"/>
<beans:bean id="shaPasswordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
<beans:constructor-arg value="256"/>
</beans:bean>
<beans:bean id="userService" class="com.gsu.knowledgebase.service.UserService"/>
<!-- Ajax Aware Handler -->
<beans:bean id="authEntryPoint"
class="com.gsu.knowledgebase.spring.AjaxAwareLoginUrlAuthenticationEntryPoint"
scope="singleton">
<beans:constructor-arg name="loginFormUrl" value="/knowledge-base"/>
</beans:bean>
<http authentication-manager-ref="authenticationManager" entry-point-ref="authEntryPoint"
pattern="/knowledge-base/**"
use-expressions="true" disable-url-rewriting="true">
<custom-filter position="BASIC_AUTH_FILTER" ref="loginFilter"/>
<logout logout-success-url="/knowledge-base" invalidate-session="true" delete-cookies="JSESSIONID"
logout-url="/knowledgeBase/j_spring_security_logout"/>
<intercept-url pattern="/knowledge-base/" access="permitAll"/>
<intercept-url pattern="/knowledge-base/memory"
access="hasRole('ADMIN') || hasRole('MODERATOR') || hasRole('USER')"/>
<access-denied-handler error-page="/knowledge-base/error/403"/>
<session-management session-authentication-error-url="/knowledge-base/error/sessionExpired"/>
</http>
<!-- ************************** -->
<authentication-manager id="authenticationManager">
<authentication-provider user-service-ref="userService">
<password-encoder ref="shaPasswordEncoder"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="loginFilter"
class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="filterProcessesUrl" value="/knowledgeBase/j_spring_security_check"/>
<beans:property name="authenticationSuccessHandler">
<beans:bean class="com.gsu.knowledgebase.spring.AuthenticationSuccessHandler"/>
</beans:property>
<beans:property name="authenticationFailureHandler">
<beans:bean class="com.gsu.knowledgebase.spring.AuthenticationFailureHandler"/>
</beans:property>
</beans:bean>
<!-- ************************** -->
</beans:beans>
This is web.xml file :
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Spring Web MVC Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/applicationContext.xml,
/WEB-INF/spring/security.xml
</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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>
<servlet>
<servlet-name>main</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>knowledge-base</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlets/knowledge-base-dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/visual/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>knowledge-base</servlet-name>
<url-pattern>/knowledge-base/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
This is my login form :
<form id="login-form">
<div class="form-group">
<label>Username</label>
<input type="text" class="form-control" name="j_username" ng-model="username"
placeholder="Your username">
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="j_password" class="form-control" ng-model="password"
placeholder="Password">
</div>
<div class="form-check">
<!--<input type="checkbox" class="form-check-input" id="exampleCheck1">-->
<!--<label class="form-check-label">Check me out</label>-->
</div>
<span class="validation-message" style="display:none;">{{validationMessage}}</span>
<span class="success-message" style="display:none;">{{successMessage}}</span>
<input type="button" class="btn btn-default blue" value="Log in"
ng-click="login()">
</form>
And this is how I call the j_spring_security_check url via ajax :
$.ajax({
type: "POST",
url: 'knowledgeBase/j_spring_security_check',
data: jQuery("#login-form").serialize(), // serializes the form's elements.
success: function (data) {
window.location = "/knowledge-base/memory";
},
error: function (data, textStatus, jqXHR) {
if (data.status == 410) {
} else if (data.status == 409) {
} else if (data.status == 406) {
} else {
}
$scope.$digest();
printError(textStatus);
}
});
But I receive a 404 not found error.
UPDATE :
After solving this, I had trouble with my UserService. It does not recognize the autowired dependencies that are defined within it. I tried both using Autowired annotation directly on the variable and on the constructor separately. knowledgbaseDao is null in the loadUserByUsername. On startup, constructors of this class is called 3 times. Each creates different objects. First one is created using the default empty constructor. Other two is created using the autowired constructor and assigns knowledgebaseDao the correct class. When userservice is called from login page it uses the first UserService class and a null pointer exception is thrown. Here is my code :
#Component("userService")
public class UserService implements UserDetailsService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
private KnowledgeBaseDao knowledgeBaseDao;
public UserService(){
System.out.println();
}
#Autowired
public UserService(KnowledgeBaseDao knowledgeBaseDao) {
this.knowledgeBaseDao = knowledgeBaseDao;
}
public UserDetails loadUserByUsername(String login) throws AuthenticationException {
logger.info("UserDetails Database Service : " + login);
// check user exists in database
User user = knowledgeBaseDao.findUserByEmail(login);
if (user == null) {
logger.warn("User({}) does not exist in system", login);
throw new UsernameNotFoundException("There is no user with this username.");
}
boolean containsLoginRole = checkLoginRole(user);
if (!containsLoginRole) {
throw new UsernameNotFoundException("Access denied.");
}
if ((user.getStatus() == null || user.getStatus() == 0)) {
throw new UsernameNotFoundException("User is not confirmed");
}
//boolean enabled = user.getStatus() == AccountStatus.ACTIVE;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
if (user.getLoginTryCount() != null && user.getLoginTryCount() >= 3) {
accountNonLocked = false;
}
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), true, accountNonExpired,
credentialsNonExpired, accountNonLocked, this.getAuthorities(user.getRoleId()));
}
public Collection<? extends GrantedAuthority> getAuthorities(Collection<Role> roleList) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (Role role : roleList) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
return authorities;
}
public Collection<? extends GrantedAuthority> getAuthorities(Long roleId) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority(Constants.ROLE_NAME(roleId.intValue())));
return authorities;
}
private boolean checkLoginRole(User user) {
if (user.getRoleId() == 0) {
return false;
}
if (user.getRoleId() == Constants.ROLE_ADMIN
|| user.getRoleId() == Constants.ROLE_MODERATOR
|| user.getRoleId() == Constants.ROLE_USER) {
return true;
} else {
return false;
}
}
}
Are you sure /knowledgeBase is the root servlet context url? I think it is knowledge-base .. so in this case the correct url the make login request should be /knowledge-base/knowledgeBase/j_spring_security_check try doing a post via postman

Sending an Ajax request from a jsp page to a spring Controller

I am trying to make an ajax call from a jsp page using the spring MVC framework to fetch some data from the server but I am getting the following error.
10-Dec-2015 11:53:05.349 WARNING [http-nio-8084-exec-14] org.springframework.web.servlet.PageNotFound.noHandlerFound No mapping found for HTTP request with URI [/EIMEnterprise/[object%20Object]] in DispatcherServlet with name 'spring-dispatcher'
No matter what I have as my URL parameter for my $.get call, it seems to attach an [object%20Object]] value at the end. Here is my Ajax Controller Class
#Controller
public class AjaxController {
#RequestMapping(value="/viewhiers.html", method=RequestMethod.GET)
public #ResponseBody ArrayList<HierarchyBean> getHiersViaAjax(#RequestParam("versionID") int versionID) {
//return an arraylist of HierarchyBean
}
}
Below is my web.xml file
<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">
<display-name>EIMEnterprise</display-name>
<servlet>
<servlet-name>spring-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>spring-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
And below is my jsp page with the following code
<script type="text/javascript">
$(document).ready(function() {
$('#versiontab tr td').click(function() {
//alert("Hello");
//highlight the current row and disable highlight on the other rows
$(this).closest("tr").addClass('highlightblue').siblings().removeClass('highlightblue');
//make an ajax call to populate the hierarchies
$.get({
url: '/EIMEnterprise/viewhiers.html?versionID=1',
type: 'GET',
success: function(data) {
alert("success");
/*
$.each(data, function (index, value) {
alert(index + " " + value);
});*/
}
});
});
});
</script>
And here is my spring-dispatcher-servlet.xml file
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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/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">
<!--Scan this package for any controller annotations-->
<context:component-scan base-package="com.eimenterprise.controllers" />
<!--Used for using pathvariable with map-->
<mvc:annotation-driven />
<mvc:resources location="/resources/" mapping="/resources/**" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Please let me know what I am doing wrong as it seems to append an object value at the end of the urL instead of sending it to the correct controller and thus cannot find the mapping.
I was passing the parameters wrong in $.get. This is resolved.
Should use $.get in the following way.
$.get( "ajax/test.html", function( data ) {
$( ".result" ).html( data );
alert( "Load was performed." );
});

How can I return text only from Spring servlet?

Here's the story, I have a single page application, where I want to call a servlet from an ajax object, and have the text returned from the servlet be displayed on my webpage.
Here's an example of how I could do it:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Insert title here</title>
<script src="jquery.js" type="text/javascript" ></script>
<script type="text/javascript">
function submittext() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "submit", true);
xmlhttp.send();
document.getElementById("myTextField").innerHTML = xmlhttp.responseText;
}
</script>
</head>
<body>
<input type="text" name="mytext" />
<br>
<button onClick="submittext()">Submit</button>
<br>
<div id="myTextField"></div>
</body>
</html>
web.xml
<servlet>
<servlet-name>testdogservlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>testdogservlet</servlet-name>
<url-pattern>/submit</url-pattern>
</servlet-mapping>
testdogservlet-servlet
<?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: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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="world.hello.mytest" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
MyServlet.java
package world.hello.mytest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class MyServlet {
private String savedText;
#RequestMapping("/submit")
public ModelAndView submitText()
{
return new ModelAndView("text", "barModelName", "submission successful ModelObject");
}
}
text.jsp
${barModelName};
This solution works fine. You click the submit button, and it changes the div contents to text contained in text.jsp.
The question is, it seems redundant to have an entire page dedicated as just the container for holding this text. Is there a tidier solution for doing this?
A spring controller can pass in the HttpServletRequest and HttpServletReponse into the mapped methods.
Modify your method to accept these two arguments, and then you can directly modify the HttpServletResponse.
#RequestMapping("/submit")
private void submit(HttpServletRequest request, HttpServletResponse response) throws IOException
{
OutputStream os = response.getOutputStream();
os.write("submission successful ModelObject".getBytes());
os.close();
os.flush();
}
Just replace the return object to something like this:
private String savedText;
#RequestMapping("/submit")
public String submitText()
{
return "submission successful ModelObject";
}
My advice is convert it to JSON object using either #RestController or Jackson JSON converter.
#RequestMapping("/submit")
#ResponseBody
public String submitText()
{
return "submission successful ModelObject";
}

Mapping more than one url to same controller but different methods

I have this code:
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">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
The servlet-context:
<?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
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd"">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<mvc: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>
<beans:bean class="com.goatsoft.helpin.Controllers.LoginController"></beans:bean>
<context:component-scan base-package="com.goatsoft.helpin" />
The root-context(empty):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="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.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->
And I got two buttons in the home.jsp, one this way:
<form action="/usuario/getbyid" method="post">
<!--some texts and stuff -->
<input type="submit" value="Login">
</form>
And anoher one this way:
<form action="/usuario/adduser" method="post">
<input type="submit" value="adduser">
</form>
This is the LoginController:
#Controller
public class LoginController{
String name;
String pass;
//#Autowired
//UsuarioService usuarioService;
#RequestMapping("usuario/adduser")
public String addUsuario(){
System.out.println("url adduser");
return name;
}
#RequestMapping("usuario/getbyid")
public String getById(){
System.out.println("url getbyid");
return name;
}
}
With this, I am getting this stacktrace:
ERROR: org.springframework.web.servlet.DispatcherServlet - Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Initialization of bean failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'loginController' bean method
public java.lang.String com.goatsoft.helpin.Controllers.LoginController.addUsuario()
to {[/usuario/adduser],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'com.goatsoft.helpin.Controllers.LoginController#0' bean method
public java.lang.String com.goatsoft.helpin.Controllers.LoginController.addUsuario() mapped.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:631)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:588)
at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:645)
at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:508)
at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:449)
at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:133)
at javax.servlet.GenericServlet.init(GenericServlet.java:160)
at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1280)
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1193)
at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:865)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:136)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'loginController' bean method
public java.lang.String com.goatsoft.helpin.Controllers.LoginController.addUsuario()
to {[/usuario/adduser],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'com.goatsoft.helpin.Controllers.LoginController#0' bean method
public java.lang.String com.goatsoft.helpin.Controllers.LoginController.addUsuario() mapped.
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:183)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.detectHandlerMethods(AbstractHandlerMethodMapping.java:147)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initHandlerMethods(AbstractHandlerMethodMapping.java:109)
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.initApplicationContext(AbstractHandlerMethodMapping.java:89)
at org.springframework.context.support.ApplicationObjectSupport.initApplicationContext(ApplicationObjectSupport.java:119)
at org.springframework.web.context.support.WebApplicationObjectSupport.initApplicationContext(WebApplicationObjectSupport.java:72)
at org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)
at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:117)
at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:92)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:394)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1448)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
... 32 more
I have tried to remove the bean from the servlet-context.xml, since I have it scans it and get two instances. This way, the home.jsp is displayed but if I press any of the buttons none of the sysouts in the controller shows up (methods are not invoked). If I remove the , I dont get any error but the home.jsp isnt displayed. Removing both results in no errors, but the home.jsp isn't displayed.
I have no clue of how to map two URLs to the same Controller. It should not be so difficult. Any help? Thank you.
try this.
#Controller
#RequestMapping("/usuario")
public class LoginController{
String name;
String pass;
#RequestMapping("/adduser")
public String addUsuario(){
System.out.println("url adduser");
return name;
}
#RequestMapping("/getbyid")
public String getById(){
System.out.println("url getbyid");
return name;
}
Or use your config just add "/"
#Controller
public class LoginController{
String name; <-- Take care with those instance variables.
String pass;
#RequestMapping(value = "/usuario/adduser", method = RequestMethod.POST )
public String addUsuario(){
System.out.println("url adduser");
return name;
}
#RequestMapping(value = "/usuario/getbyid", method = RequestMethod.POST )
public String getById(){
System.out.println("url getbyid");
return name;
}
}
Well, removing LoginController from the servlet-context.xml, adding a slash to the #RequestMapping url, and removing it from the home.jsp did the trick.

Spring 3 MVC extra #RequestMapping value getting appended to returned view

I have a view 'hi.jsp' with user name and password text fields. I need to submit 'hi.jsp' to 'LoginController.java'. If there is any error in the data submitted then 'LoginController.java' must redirect the request back to 'hi.jsp' (with text fields retaning the entered data) with respective error messages. After changing data and re-submitting 'hi.jsp' I get 404 error.
So the first submission is successful however problem occurs during second submission.
The source code of files is mentioned below:
hi.jsp
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="s" %>
<%# page session="false" %>
<html>
<body>
<s:form method="POST" modelAttribute="loginObj" action="login/validatelogin">
<label for="userName">UserName</label>
<s:input path="userName" id="userName" size="15"/><br>
<div style="{color:red}"> <s:errors path="userName"></s:errors></div>
<label for="password">Password</label>
<s:input path="password" id="password" size="15" /><br>
<s:errors path="password"></s:errors>
<input name="submit" type="submit" value="login"/>
</s:form>
</body>
</html>
LoginController.java
package rajeev.spring.spitter.mvc.controller;
import javax.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
#RequestMapping("/login")
public class LoginController {
#RequestMapping(value="/validatelogin", method=RequestMethod.POST)
public String validateLogin(#Valid #ModelAttribute("loginObj") LoginBean loginObj, BindingResult bindingResult)
{
System.out.println(bindingResult.hasErrors());
if(bindingResult.hasErrors())
{
return "hi";
}
return "home";
}
}
spitter-servlet.xml (spring 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:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-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/beans http://www.springframework.org/schema/beans/spring-beans.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="rajeev.spring.spitter.mvc.controller"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>Spring Hello World</display-name>
<welcome-file-list>
<welcome-file>/</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>springDispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spitter-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
During the second submission of 'hi.jsp' tomcat log also displays a warning:
WARNING: No mapping found for HTTP request with URI [/SpringMVC/login/login/validatelogin] in DispatcherServlet with name 'springDispatcher'
It seems that during second submission of 'hi.jsp' an extra '/login' is getting appended to the submission path of the form.
Kindly suggest if something is wrong with above code or do I need to modify it to make it working.
Thanks for your help.
This is because the relative form post URL changed when you map your handler method into a different URL
<s:form method="POST" modelAttribute="loginObj" action="login/validatelogin">
Common solution to this problem is to use absolute path, but instead of hardcoding, lookup your context-path using
<c:set var="root" value="${pageContext.request.contextPath}"/>
Then on your form
<s:form method="POST" modelAttribute="loginObj" action="${root}/login/validatelogin">
Other option you might consider is to use Post-Redirect pattern in your controller handler method to avoid switching the URL
public String validateLogin(#Valid #ModelAttribute("loginObj") LoginBean loginObj, BindingResult bindingResult) {
....
return "redirect:/login";
}
Try this:
<c:url var="myAction" value="/login/validatelogin"/>
<s:form method="POST" modelAttribute="loginObj" action="${myAction}">

Resources