processFormSubmission not being called - spring

I am new to spring. I am creating a simple login page. But the processFormSubmission() is not being called. But the showForm() is working.
public class LoginController extends SimpleFormController
{
private LoginService loginService;
private String loginView;
public LoginService getLoginService() {
return loginService;
}
public void setLoginService(LoginService loginService) {
this.loginService = loginService;
}
public String getLoginView() {
return loginView;
}
public void setLoginView(String loginView) {
this.loginView = loginView;
}
public LoginController() {
setBindOnNewForm(true);
}
#Override
protected ModelAndView processFormSubmission(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors)
throws Exception
{
TraceUser tr = (TraceUser) command;
System.out.println(tr);
//loginService.
return super.processFormSubmission(request, response, command, errors);
}
#Override
protected ModelAndView showForm(HttpServletRequest request,
HttpServletResponse response, BindException errors)
throws Exception {
ModelAndView mav = new ModelAndView();
mav.addObject("traceUser", new TraceUser());
mav.setViewName(getLoginView());
return mav;
}
}
And please help me out with how should the ModelAndView object should be processed further.

First of all, the use of the Controller API has been left aside in favor of the new annotation-based controllers (see the #RequestMapping annotation) and classes like SimpleFormController have been deprecated since quite a while now.
However, to answer your question, I assume your form does not declare method="post" and by default, the SFC will consider only POST requests as form submissions (see the isFormSubmission() method in AbstractFormController). Is this the case ?

Related

Spring: how to pass objects from filters to controllers

I'm trying to add a Filter that creates an object that is then to be used inside a controller in a Spring Boot application.
The idea is to use the Filter as a "centralized" generator of this object - that is request-specific and useful only in a controller.
I've tried to use the HttpServletRequest request.getSession().setAttribute method: I can access my object in the controller, but then it will be (clearly) added to the session.
Are the Filters the right way to do so? If yes, where can I keep the temporary object generated by the filter to be used by the controllers?
Why Don't you use a Bean with the #Scope('request')
#Component
#Scope(value="request", proxyMode= ScopedProxyMode.TARGET_CLASS)
class UserInfo {
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
private String password;
}
and then you can Autowireed this bean in both filter and controller to do setting and getting of data.
lifecycle of this UserInfo bean is only exisits within the request so once the http request is done then it terminates the instance as well
you can use ServletRequest.setAttribute(String name, Object o);
for example
#RestController
#EnableAutoConfiguration
public class App {
#RequestMapping("/")
public String index(HttpServletRequest httpServletRequest) {
return (String) httpServletRequest.getAttribute(MyFilter.passKey);
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
#Component
public static class MyFilter implements Filter {
public static String passKey = "passKey";
private static String passValue = "hello world";
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
request.setAttribute(passKey, passValue);
chain.doFilter(request, response);
}
#Override
public void destroy() {
}
}
}
An addition to wcong's answer.
Since Spring 4.3 after setting the attribute by using request.setAttribute(passKey, passValue);, you can access the attribute in your controller by simply annotating it with #RequestAttribute.
ex.
#RequestMapping("/")
public String index(#RequestAttribute passKey) {
return (String) passKey;
}
I dont know actually what is the scenario but If you really want to create an object in a filter and then use it somewhere in the code then you may use ThreadLocal class to do so.
To get know how this work see the most voted answer from that question Purpose of ThreadLocal?
In general using ThreadLocal you will be able to create a class that can store objects available ONLY for the current thread.
Sometimes for optimization reasons the same thread can be used to serve subsequent request as well so it will be nice to clean the threadLocal value after the request is processed.
class MyObjectStorage {
static private ThreadLocal threadLocal = new ThreadLocal<MyObject>();
static ThreadLocal<MyObject> getThreadLocal() {
return threadLocal;
}
}
in the filter
MyObjectStorage.getThreadLocal().set(myObject);
and in the Controller
MyObjectStorage.getThreadLocal().get();
Instead of filter you can use also #ControllerAdvice and pass objects to specified Controllers by using model.
#ControllerAdvice(assignableTypes={MyController.class})
class AddMyObjectAdvice {
// if you need request parameters
private #Inject HttpServletRequest request;
#ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("myObject", myObject);
}
}
#Controller
public class MyController{
#RequestMapping(value = "/anyMethod", method = RequestMethod.POST)
public String anyMethod(Model model) {
MyObjecte myObject = model.getAttribute("myObject");
return "result";
}
}

Create own class that transforms HTTP request to object in Spring?

I would like to create own class that will transform HTTP request and initializes object from this HTTP request in my Spring MVC application. I can create object by defining parameters in method but I need to do mapping in my own way and do it manually.
How can I do it with my own implementation that will pass to Spring and it will use it seamlessly?
Update1
Solution that kindly provided Bohuslav Burghardt doesn't work:
HTTP Status 500 - Request processing failed; nested exception is
java.lang.IllegalStateException: An Errors/BindingResult argument is
expected to be declared immediately after the model attribute, the
#RequestBody or the #RequestPart arguments to which they apply: public
java.lang.String
cz.deriva.derivis.api.oauth2.provider.controllers.OAuthController.authorize(api.oauth2.provider.domain.AuthorizationRequest,org.springframework.ui.Model,org.springframework.validation.BindingResult,javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
Maybe I should mention that I use own validator:
public class RequestValidator {
public boolean supports(Class clazz) {
return AuthorizationRequest.class.equals(clazz);
}
public void validate(Object obj, Errors e) {
AuthorizationRequest request = (AuthorizationRequest) obj;
if ("foobar".equals(request.getClientId())) {
e.reject("clientId", "nomatch");
}
}
}
and declaration of my method in controller (please not there is needed a validation - #Valid):
#RequestMapping(value = "/authorize", method = {RequestMethod.GET, RequestMethod.POST})
public String authorize(
#Valid AuthorizationRequest authorizationRequest,
BindingResult result
) {
}
I have two configurations classes in my application.
#Configuration
#EnableAutoConfiguration
#EnableWebMvc
#PropertySource("classpath:/jdbc.properties")
public class ApplicationConfig {
}
and
#Configuration
#EnableWebMvc
public class WebappConfig extends WebMvcConfigurerAdapter {
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new AuthorizationRequestArgumentResolver());
}
}
What is wrong?
Update 2
The problem is with param BindingResult result, when I remove it it works. But I need the result to process it when some errors occur.
If I understand your requirements correctly, you could implement custom HandlerMethodArgumentResolver for that purpose. See example below for implementation details:
Model object
public class AuthorizationRequestHolder {
#Valid
private AuthorizationRequest authorizationRequest;
private BindingResult bindingResult;
// Constructors, accessors omitted
}
Resolver
public class AuthorizationRequestMethodArgumentResolver implements HandlerMethodArgumentResolver {
#Override
public boolean supportsParameter(MethodParameter parameter) {
return AuthorizationRequestHolder.class.isAssignableFrom(parameter.getParameterType());
}
#Override
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
// Map the authorization request
AuthorizationRequest authRequest = mapFromServletRequest(request);
AuthorizationRequestHolder authRequestHolder = new AuthorizationRequestHolder(authRequest);
// Validate the request
if (parameter.hasParameterAnnotation(Valid.class)) {
WebDataBinder binder = binderFactory.createBinder(webRequest, authRequestHolder, parameter.getParameterName());
binder.validate();
authRequestHolder.setBindingResult(binder.getBindingResult());
}
return authRequestHolder;
}
}
Configuration
#Configuration
#EnableWebMvc
public class WebappConfig extends WebMvcConfigurerAdapter {
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(new AuthorizationRequestMethodArgumentResolver());
}
}
Usage
#RequestMapping("/auth")
public void doSomething(#Valid AuthRequestHolder authRequestHolder) {
if (authRequestHolder.getBindingResult().hasErrors()) {
// Process errors
}
AuthorizationRequest authRequest = authRequestHolder.getAuthRequest();
// Do something with the authorization request
}
Edit: Updated answer with workaround to non-supported usage of #Valid with HandlerMethodArgumentResolver parameters.

Spring-MVC Exception handler returns OK when writing into response

I'm using spring-webmvc : 3.2.3.RELEASE (and its related dependencies).
I have this controller:
#Controller
#RequestMapping("/home")
public class HomeController {
#Autowired
MappingJacksonHttpMessageConverter messageConverter;
#RequestMapping(method = RequestMethod.GET)
public String get() {
throw new RuntimeException("XXXXXX");
}
#ExceptionHandler(value = java.lang.RuntimeException.class)
#ResponseStatus(HttpStatus.CONFLICT)
public ModelAndView runtimeExceptionAndView(ServletWebRequest webRequest) throws Exception {
ModelAndView retVal = handleResponseBody("AASASAS", webRequest);
return retVal;
}
#SuppressWarnings({ "resource", "rawtypes", "unchecked" })
private ModelAndView handleResponseBody(Object body, ServletWebRequest webRequest) throws ServletException, IOException {
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(webRequest.getResponse());
messageConverter.write(body, MediaType.APPLICATION_JSON, outputMessage);
return new ModelAndView();
}
}
since the "/home" method throws RuntimeException that is being handled with the #ExceptionHandler, when the get() method is invoked, I'm expectin to get HttpStatus.CONFLICT, but instead, I'm getting HttpStatus.OK.
Can someone please tell me what should I do in order to get the response status from
the annotated exception handler?
The reason is because you are explicitly writing to the output stream, instead of letting the framework handle it. The header has to go before the body content is written, if you are explicitly handling writing to the output stream, you will have to write the header also yourself.
To let the framework handle the entire flow, you can instead do this:
#ExceptionHandler(value = java.lang.RuntimeException.class)
#ResponseStatus(HttpStatus.CONFLICT)
#ResponseBody
public TypeToBeMarshalled runtimeExceptionAndView(ServletWebRequest webRequest) throws Exception {
return typeToBeMarshalled;
}
Modify ExceptionHandler method like this
#ExceptionHandler(value = java.lang.RuntimeException.class)
public ModelAndView runtimeExceptionAndView(ServletWebRequest webRequest, HttpServletResponse response) throws Exception {
response.setStatus(HttpStatus.CONFLICT.value());
ModelAndView retVal = handleResponseBody("AASASAS", webRequest);
return retVal;
}
If you want to handle exception by json result, I suggest to use #ResponseBody with Automatic Json return.
#ExceptionHandler(value = java.lang.RuntimeException.class)
#ResponseBody
public Object runtimeExceptionAndView(ServletWebRequest webRequest, HttpServletResponse response) throws Exception {
response.setStatus(HttpStatus.CONFLICT.value());
return new JsonResult();
}

GWT - RemoteService interface and Spring - how to get HttpSession?

I am using GWT (2.5) with RPC, Spring and Postgresql for my project. My issue is about HttpSession handling .
All queries to server are dispatched by Spring (DispatchServlet) to my GwtController (extends RemoteServiceServlet) .
The particular RemoteService is injected in the GwtController . It is easy to get the HttpSession inside the GwtContorller.
In example by getThreadLocalRequest().getSession() or just from request.getSession().
My question is how to get HttpSession object inside the RemoteService ?
public class GwtRpcController extends RemoteServiceServlet {
……………
private RemoteService remoteService;
private Class remoteServiceClass;
………………
public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
…………
}
public String processCall(String payload) throws SerializationException {
…………
}
public void setRemoteService(RemoteService remoteService) {
…………….
}
}
My Interface - DataService which implements RemoteService
public class DataServiceImpl implements DataService {
public Data getData(){
!!!!! Here I want to get HttpSession !!!!!
…………………………
}
}
You can maintain a ThreadLocal in your Servlet and store there your current Request, then expose your Request with a static method.
public class GwtRpcController extends RemoteServiceServlet {
static ThreadLocal<HttpServletRequest> perThreadRequest =
new ThreadLocal<HttpServletRequest>();
#Override
public String processCall(String payload) throws SerializationException {
try {
perThreadRequest.set(getThreadLocalRequest());
return super.processCall(payload);
} finally {
perThreadRequest.set(null);
}
}
public static HttpServletRequest getRequest() {
return perThreadRequest.get();
}
}
public class DataServiceImpl implements DataService {
public Data getData(){
HttpServletRequest request = GwtRpcController.getRequest();
HttpSession session = request.getSession();
}
}

#ExceptionHandler not being invoked

After some time researching and trying different things I still cannot get my #ExceptionHandler to be invoked in my jUnit integration test. Please, help me understand why?
#RequestMapping(value = "/someURL", method = RequestMethod.POST)
public ModelAndView batchUpload(#RequestBody final String xml, #RequestParam boolean replaceAll)
throws IOException, URISyntaxException, SAXException, ParserConfigurationException, InvocationTargetException, IllegalAccessException, UnmarshallingFailureException
{
StreamSource source = new StreamSource(new StringReader(xml));
DomainClass xmlDomainClass;
try
{
xmlDomainClass = (DomainClass) castorMarshaller.unmarshal(source);
}
catch (UnmarshallingFailureException me)
{
// some logging. this gets executed
throw me;
}
.
#ExceptionHandler(Throwable.class)
public ModelAndView handleUnmarshallingExceptions(Throwable th)
{
// never executes anything in here
return new ModelAndView( /*some parameters */ );
}
Spring: RESTful controllers and error handling helped me, my problem was the lack of this:
#Component
public class AnnotatedExceptionResolver extends AnnotationMethodHandlerExceptionResolver{
public AnnotatedExceptionResolver() {
setOrder(HIGHEST_PRECEDENCE);
}
}

Resources