I have a controller which has a few actions, which are triggered by hitting various buttons on the page. I would like to have a default action, but am unsure how to annotate the method. Here is an example:
#Controller
#RequestMapping("/view.jsp")
public class ExampleController {
#RequestMapping(method = RequestMethod.GET)
public ModelAndView displayResults() {
ModelAndView mav = new ModelAndView("view");
mav.addObject("queryResults", methodToQueryDBForListing());
return mav;
}
#RequestMapping(method = RequestMethod.POST, params="submit=Action 1")
public ModelAndView action1(#RequestParam("selectedItemKey") String key) {
ModelAndView mav = new ModelAndView("action1");
//Business logic
return mav;
}
#RequestMapping(method = RequestMethod.POST, params="submit=Action 2")
public ModelAndView action2(#RequestParam("selectedItemKey") String key) {
ModelAndView mav = new ModelAndView("action2");
//Business logic
return mav;
}
//A few more methods which basically do what action1 and action2 do
}
How can I annotate a method which will act on a POST with any submit button pressed with no key selected?
I have tried:
#RequestMethod(method = RequestMethod.POST, params="!selectedItemKey")
#RequestMethod(method = RequestMethod.POST)
I'd really hate it if I had to set required = false on each of the methods which take RequestParams and then conditionally check to see if one comes in or not... Is there a way to annotate this to work properly?
I would make this a path variable rather than a parameter, and would get rid of the .jsp:
#RequestMapping("/view")
...
#RequestMapping("/action1")
#RequestMapping("/action2")
#RequestMapping("/{action}")
It is more "restful".
The proper annotation is:
#RequestMapping(
method = RequestMethod.POST,
params = { "!selectedItemKey", "submit" }
)
It seems odd though, that it was not hitting this method until adding that second parameter.
I'm not so familiar with annotated spring-mvc but I can remember that when extending a MultiActionController you can specify a default entry point by defining the following spring config:
<bean name="myController"
class="foo.bar.MyController">
<property name="methodNameResolver">
<bean class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<property name="defaultMethodName" value="init" />
</bean>
</property>
package foo.bar
public class MyController extends MultiActionController {
/**
* Called when no parameter was passed.
*/
public ModelAndView init(HttpServletRequest request,
HttpServletResponse response) {
return new ModelAndView("myDefaultView");
}
/**
* action=method1
*/
public void method1(HttpServletRequest request,
HttpServletResponse response) {
return new ModelAndView("method1");
}
/**
* action=method2
*/
public void method2(HttpServletRequest request,
HttpServletResponse response) {
return new ModelAndView("method2");
}
}
So maybe in this instance you could solve this by configuring your controller over spring config instead of using annotations.
Related
My Spring RestController have the following method which returns the DTO:
#RequestMapping(
value = "/profile",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public UserProfileDto getUserProfile() {...}
I would like intercept the controller method call, get the resulted DTO and modify some fieds before serialization into JSON?
As far as I understand there are 2 ways:
Custom filter:
Doesn't work as I can get only byte stream of serialized response
Custom HandlerInterceptor:
But I'm not sure how can I do it as postHandle in HandlerInterceptor have null ModelAndView, and afterCompletion doesn't have ModelAndView at all
You may use OncePerRequestFilter, like this example below,
#Component
public class MyFilter extends OncePerRequestFilter {
private final ObjectMapper objectMapper;
#Autowired
public MyFilter(final ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
#Override
protected void doFilterInternal(
final HttpServletRequest request,
final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException {
// Add your code here ...
}
filterChain.doFilter(request, response);
}
}
You can do this to change the handle your response,
#RequestMapping(
value = "/profile",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UserProfileDto> getUserProfile() {
return ResponseEntity.ok().body(new UserProfileDto());
}
In Spring application, I need to hold user value until I don't remove or destroy.
According to it, I have used the HttpSession in the Controller as follows
#Controller
public class MyController {
#RequestMapping(value = { "/search" }, method = RequestMethod.POST) //this hander called once
public String search(SearchVo aSearchVo, BindingResult result,
ModelMap model,HttpSession httpsession) {
if (result.hasErrors()) {
model.addAttribute("searches", new SearchVo());
return "home";
}
httpSession.setAttribute("searchstring", aSearchVo.getSearchString());
return "caseResult";
}
#SuppressWarnings("unchecked")
#RequestMapping(value = { "/filtersearch" }, method = RequestMethod.POST) //This handler call again and again
public String filterSearch(#ModelAttribute("filter") FilterVo fvo,ModelMap model , HttpSession httpSession){
String searchKeyWorld=httpSession.getAttribute("searchstring");
System.out.println(searchKeyWorld);
searchKeyWorld+=fvo.getFilterWorld();
return "caseResult";
}
}
but in the session variable, the value gets changed automatically as in the last filter; as I haven't set any session variable in filtersearch Handler
You need to use #SessionAttributes for putting variable in http session.
This is a class level annoation.
#Controller
#SessionAttributes("searches")
public class MyController{
#RequestMapping(value = { "/search" }, method = RequestMethod.POST) //this hander called once
public String search(SearchVo aSearchVo, BindingResult result,
ModelMap model,WebRequest webRequest) {
if (result.hasErrors()) {
model.addAttribute("searches", new SearchVo());
return "home";
}
model.addAttribute("searches", new SearchVo());
//For removing anything from session
//webRequest.removeAttribute("searches", WebRequest.SCOPE_SESSION);
return "caseResult";
}
}
Is it possible in Spring MVC to have void handler for request?
Suppose I have a simple controller, which doesn't need to interact with any view.
#Controller
#RequestMapping("/cursor")
public class CursorController {
#RequestMapping(value = "/{id}", method = PUT)
public void setter(#PathVariable("id") int id) {
AnswerController.setCursor(id);
}
}
UPD
#Controller
#RequestMapping("/cursor")
public class CursorController {
#RequestMapping(value = "/{id}", method = PUT)
public ResponseEntity<String> update(#PathVariable("id") int id) {
AnswerController.setCursor(id);
return new ResponseEntity<String>(HttpStatus.NO_CONTENT);
}
}
you can return void, then you have to mark the method with
#ResponseStatus(value = HttpStatus.OK) you don't need #ResponseBody
#RequestMapping(value = "/updateSomeData" method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.OK)
public void defaultMethod(...) {
...
}
Only get methods return a 200 status code implicity, all others you have do one of three things:
Return void and mark the method with #ResponseStatus(value = HttpStatus.OK)
Return An object and mark it with #ResponseBody
Return an HttpEntity instance
Also refer this for interesting information.
I am new to spring mvc3 development and was facing a minor issue (which I was didn't face with ASP.Net MVC3). I want to know the process of defining a default (or landing) URL for a controller.
I have an accounts controller where I do all account management related stuff. So all my urls are mapped to this controller. I want to know that how can I map my "/accounts" url request to hit openAccountsDashboard method?
Code -
.... imports...
#Controller
#RequestMapping(value = "/accounts/*")
public class AccountController {
#RequestMapping( value = "/", method = RequestMethod.GET)
public ModelAndView openAccountsDashboard(HttpServletRequest request) {
.....
return new ModelAndView("accounts/landing");
}
#RequestMapping( value = "/change-password", method = RequestMethod.GET)
public ModelAndView openPasswordChangePage(HttpServletRequest request) {
.....
return new ModelAndView("accounts/passwordChange");
}
... other actions...
}
Any help would be great!
Thanks
Try something like this:
.... imports...
#Controller
#RequestMapping(value = "/accounts/")
public class AccountController {
#RequestMapping( value = "", method = RequestMethod.GET)
public ModelAndView openAccountsDashboard(HttpServletRequest request) {
.....
return new ModelAndView("accounts/landing");
}
#RequestMapping( value = "/change-password", method = RequestMethod.GET)
public ModelAndView openPasswordChangePage(HttpServletRequest request) {
.....
return new ModelAndView("accounts/passwordChange");
}
... other actions...
}
Then you can use url like this:
http://localhost:8080/yourwebapp/accounts/
to hit openAccountsDashboard method.
Regards,
Arek
Currently i am using paging on my page which uses MultiActionController which displays a jsp page perfectly , on the same page now i want to validate a simple textfield (input/form:input) also want to retrieve name and id from a dropdown(Select option) once a link is clicked. Simple !!
Two questions
Can i use a class implements Validator? and inject it same way as simpleformcontroller in config or some other way within the controller? How? example please?
Can i use java bean in jsp -> i always get error of binding, how to indicated controller to use this bean? i have have passed as argument to my method add and also tried overriding newCommandObject
Controller.java
public ModelAndView add(HttpServletRequest request, HttpServletResponse response, Person person) throws Exception {
return new ModelAndView("userpage");
}
#Override
protected Object newCommandObject(Class clazz)
throws Exception {
return new Person();
}
I will do something like below in Spring version > 2.5
#Controller
public class YourController
{
protected final Log logger = LogFactory.getLog(getClass());
private final String yourInputJsp = "yourInputJsp";
private final String yourInputJspSuccess = "yourInputJspSuccess";
private YourService yourService;
#Autowired
#Qualifier("yourFormValidator")
private YourFormValidator validator;
#RequestMapping(value = "/yourRequest.htm", method = RequestMethod.GET)
public String referenceData(ModelMap model, HttpServletRequest request) throws Exception
{
yourService = new YourServiceImpl(ContextHandler.getWebAppContext(request));
YourFormData yourFormData = new YourFormData();
model.addAttribute("yourFormData", yourFormData);
return yourInputJsp;
}
#InitBinder()
public void initBinder(WebDataBinder binder) throws Exception {
binder.registerCustomEditor(String.class, new StringMultipartFileEditor());
}
#RequestMapping(value="/yourRequest.htm", method = RequestMethod.POST)
public String process(#ModelAttribute("yourFormData") YourFormData yourFormData, BindingResult result, SessionStatus status, HttpServletRequest request)
{
String mav = yourInputJsp;
validator.validate(yourFormData, result);
if(!result.hasErrors())
{
//Some business logic
mav = "redirect:yourInputJspSuccess.htm";
status.setComplete();
}
return mav;
}
}