Calling RequestMapping "twice" - java

I couldn't figure out what to put to the title, but I have the following code:
#Controller
public class WorkdayAddController {
#Autowired
private WorkdayRepository workdayRepository;
#Autowired
private VehicleRepository vehicleRepository;
#RequestMapping(value = "addworkday")
public String addWorkday(Model model){
model.addAttribute("workdayaddform", new WorkdayAddForm());
model.addAttribute("vehicles", vehicleRepository.findAll());
return "addworkday";
}
#RequestMapping(value = "saveworkday", method = RequestMethod.POST)
public String save(#Valid #ModelAttribute("workdayaddform") WorkdayAddForm workdayaddform, BindingResult bindingResult) {
if (!bindingResult.hasErrors()) { // validation errors
Date workdayBegin = workdayaddform.getBeginDate();
Date workdayEnd = workdayaddform.getEndDate();
if (!UtilityClass.dateIsAfterDate(workdayBegin, workdayEnd)) {
bindingResult.rejectValue("beginDate", "err.beginDate", "Aloitusaika ei voi olla lopetusajan jälkeen.");
return "addworkday";
}
Workday workday = new Workday();
Vehicle vehicle = new Vehicle();
workdayRepository.save(workday);
}
else {
return "addworkday";
}
return "redirect:/workdaylist";
}
}
After the 'dateIsAfterDate' check, it should direct one to 'addworkday' again, which it does, but it doesn't add the 'vehicles' model. Is there a way around this? I thought it would somehow just direct it to the above #RequestMapping(value= "addworkday") but this seems to not be the case.
Update:
#RequestMapping(value = "addworkday")
public String addWorkday(Model model, RedirectAttributes redirectAttributes){
System.out.println(redirectAttributes); // {}
System.out.println(model); // output in comment
model.addAttribute("workdayaddform", new WorkdayAddForm()); //I guess I need to add the old workdayform here?
model.addAttribute("vehicles", vehicleRepository.findAll());
return "addworkday";
}
#RequestMapping(value = "saveworkday", method = RequestMethod.POST)
public String save(#Valid #ModelAttribute("workdayaddform") WorkdayAddForm workdayaddform,
BindingResult bindingResult,
final RedirectAttributes redirectAttributes) {
if (!bindingResult.hasErrors()) { // validation errors
Date workdayBegin = workdayaddform.getBeginDate();
Date workdayEnd = workdayaddform.getEndDate();
if (!UtilityClass.dateIsAfterDate(workdayBegin, workdayEnd)) {
// Add the vehicle you want to send to the other method.
redirectAttributes.addFlashAttribute("workdayaddform", workdayaddform);
redirectAttributes.addFlashAttribute("vehicle", vehicleRepository.findAll());
redirectAttributes.addFlashAttribute("binding", bindingResult);
return "redirect:/addworkday";
}

You need to use the #RedirectedAttributes annotation in order to send attributes to another method in a controller. Also, you will need to add "redirect:/" to your returned url.
#RequestMapping(value = "saveworkday", method = RequestMethod.POST)
public String save(#Valid #ModelAttribute("workdayaddform") WorkdayAddForm workdayaddform,
BindingResult bindingResult,
final RedirectAttributes redirectAttributes) {
if (!bindingResult.hasErrors()) { // validation errors
Date workdayBegin = workdayaddform.getBeginDate();
Date workdayEnd = workdayaddform.getEndDate();
if (!UtilityClass.dateIsAfterDate(workdayBegin, workdayEnd)) {
// Add the vehicle you want to send to the other method.
redirectAttributes.addFlashAttribute("vehicle", vehicle);
redirectAttributes.addFlashAttribute("binding", bindingResult);
return "redirect:/addworkday";
}
// More code.
else {
redirectAttributes.addFlashAttribute("vehicle", new Vehicle());
return "redirect:/addworkday";
}
}
I wasn't sure if you meant, after the in the else or inside the if, so I add them in both places, just to make sure.

Related

How to schedule a JSP Page?

I have a JSP page as task.jsp. So I want to display this page only once in a year i.e. in the month of March every year.
I dont have any idea how to schedule it. Please help me. Following is my sample controller code:
#RequestMapping(
value = "task.htm",
method = RequestMethod.GET
)
public ModelAndView taskPost(#ModelAttribute("task") Task task, HttpServletRequest request) {
ModelAndView model = new ModelAndView("task");
//do something
return model;
}
You can throw a ResponseStatusException:
#RequestMapping(value = "task.htm", method = RequestMethod.GET)
public ModelAndView taskPost(#ModelAttribute("task") Task task,HttpServletRequest request {
if(LocalDate.now().getMonth() != Month.MARCH) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Unable to find resource");
}
ModelAndView model = new ModelAndView("task");
//do something
return model;
}
See more:
ResponseStatusException (javadoc)
https://www.baeldung.com/spring-response-status-exception

Conditional statements in Spring Controller questions

So a have a blueprint code of a web app which allows different accounts with logins to upload simple files. However, there are security flaws that allow non-admin accounts to enter database configurations and direct object referencing (download files of other accounts by URL tampering). I was recommended a solution whereby I check if the owner of the uploaded file is the same one trying to download it. But doing that in a spring #controller posed a few problems. If you look at my get statement to get a specific file, you see that I got the file object and the account object. Then I just check if the name is the same of file owner. But how do I "return" something in a controller while in an "if" statement?
#Controller
public class FileController {
#Autowired
private FileRepository fileRepository;
#Autowired
private AccountRepository accountRepository;
#RequestMapping(value = "/files", method = RequestMethod.GET)
public String list(Authentication authentication, Model model) {
model.addAttribute("files", accountRepository.findByUsername(authentication.getName()).getFileObjects());
return "files";
}
#RequestMapping(value = "/files/{id}", method = RequestMethod.GET)
public ResponseEntity<byte[]> viewFile(#PathVariable Long id) {
//1. get object or name account name
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
//2. check if the file account is of the same name
FileObject fo = fileRepository.findOne(id);
if((fo.getAccount().getUsername()).equals(currentPrincipalName)) {
System.out.println("WHAT AM I SUPPOSED TO DO!?");
}
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(fo.getContentType()));
headers.add("Content-Disposition", "attachment; filename=" + fo.getName());
headers.setContentLength(fo.getContentLength());
return new ResponseEntity<>(fo.getContent(), headers, HttpStatus.CREATED);
}
#RequestMapping(value = "/files", method = RequestMethod.POST)
public String addFile(Authentication authentication, #RequestParam("file") MultipartFile file) throws IOException {
Account account = accountRepository.findByUsername(authentication.getName());
FileObject fileObject = new FileObject();
fileObject.setContentType(file.getContentType());
fileObject.setContent(file.getBytes());
fileObject.setName(file.getOriginalFilename());
fileObject.setContentLength(file.getSize());
fileObject.setAccount(account);
fileRepository.save(fileObject);
return "redirect:/files";
}
#RequestMapping(value = "/files/{id}", method = RequestMethod.DELETE)
public String delete(#PathVariable Long id) {
fileRepository.delete(id);
return "redirect:/files";
}
}

Mock BindingResult in unit test case when user does not exist

I'm very new to Mockito and Junit. I'm working on creating test case for forgot password workflow. Below is the code for controller and test. Could anyone tell me how should I test on bindingresult?
#RequestMapping(value = "/user/public/forgotPassword", method = RequestMethod.POST)
public ModelAndView sendforgetPasswordLink(#ModelAttribute ForgetPasswordBean forgetPasswordBean,BindingResult result, HttpSession session) {
BreadCrumbBuilder.addLinktoBreadCrumb(session, new Link(Constants.FORGET_PASSWORD_TITLE, "/user/public/forgotPassword", Constants.GROUP_USER, 0));
Map<String, String> breadCrumbs = HomePageController.setupInitialBreadCrumbs(session);
breadCrumbs.put(Constants.FORGET_PASSWORD_TITLE, "/user/public/forgotPassword");
session.setAttribute(SessionAttributes.BREAD_CRUMBS,breadCrumbs);
ModelAndView mav = new ModelAndView();
mav.addObject("displayTitle", Constants.FORGET_PASSWORD_TITLE);
PublicUser user = publicUserService.findPublicUserByEmail(forgetPasswordBean.getEmail().toLowerCase());
if(user == null) {
result.reject("email", "An account does not exist for this email.");
mav.setViewName("publicuser/forgetPassword.jsp");
return mav;
}
String randomId = java.util.UUID.randomUUID().toString();
user.setTempId(randomId);
mailService.sendForgetPasswordLink(user);
publicUserService.savePublicUser(user);
String msg = "Password reset instructions have been sent to your email.";
mav.addObject("msg", msg);
mav.setViewName("message.jsp");
return mav;
}
This is test I created so far
#Test
public void TestForgetPasswordForNoUserFound() throws Exception {
final String input_email = "abc#test.com";
ForgetPasswordBean forgetPasswordBean = new ForgetPasswordBean();
forgetPasswordBean.setEmail(input_email);
PublicUser daoUser = new PublicUser();
daoUser.setEmail(input_email);
when(mockPublicUserService.findPublicUserByEmail(input_email)).thenReturn(null);
when(mockBindingResult.hasErrors()).thenReturn(true);
final ModelAndView modelAndView = controller.sendforgetPasswordLink(forgetPasswordBean, mockBindingResult, mockHttpSession);
ModelMap modelMap = modelAndView.getModelMap();
assertEquals("An account does not exist for this email.", modelMap.get(mockBindingResult));
assertEquals("publicuser/forgetPassword.jsp", modelAndView.getViewName());
assertModelAttributeValue(modelAndView, "displayTitle", Constants.FORGET_PASSWORD_TITLE);
}
What you can do is verify behavior of your BindingResult by checking that the reject method was called.
Basically instead of
assertEquals("An account does not exist for this email.", modelMap.get(mockBindingResult));
You can do the following
Mockito.verify(mockBindingResult).reject("email", "An account does not exist for this email.");
And that way you can verify that the method was called.

How set RedirectAttributes in Controller Test

I need test my controller method
#RequestMapping(path="/add", method = RequestMethod.POST)
public RedirectView addToCart(#ModelAttribute(value="productId") long productId, #ModelAttribute(value="quantity") int quantity, RedirectAttributes redirectAttributes) throws ProductNotFoundException {
RedirectView redirect = new RedirectView("/product/");
redirect.setExposeModelAttributes(false);
try {
redirectAttributes.addFlashAttribute("flash", shoppingCartService.addQuantity(sCart, productId, quantity));
} catch (ExceedsProductQuantityException e) {
e.printStackTrace();
redirectAttributes.addFlashAttribute("flash", new FlashMessage(e.getMessage(), FlashMessage.Status.FAILURE));
}
return redirect;
}
My test code looks like:
#Test(expected = ExceedsProductQuantityException.class)
public void addTooManyToCartTest1() throws Exception {
Product product = productBuilder();
product.setQuantity(15);
Purchase purchase = purchaseBuilder(product); // First purchase
when(productService.findById(1L)).thenReturn(product);
when(sCart.getPurchase()).thenReturn(purchase);
mockMvc.perform(MockMvcRequestBuilders.post("/cart/add")
.param("quantity", String.valueOf(product.getQuantity() + 1))
.param("productId", "1"))
.andExpect(MockMvcResultMatchers.model().attribute("flash", "rdValue"))
.andExpect(MockMvcResultMatchers.flash().attribute("flash", FlashMessage.class));
}
But I get NestedServledException error message, I think its because in my controller method I try to work with RedirectedAttributes, but it's null. So, where and how I have to init and set RedirectedAttributes in my test?
Problem wasnt in RedirectAttributes, there was sCart Mock uninitialized.
I believe you dont need give RedirectAttributes with request as other params.

Spring controller main methods

I'm new to Spring and Spring MVC. I'm trying to implement a basic web-application to test the functionalities of this framework and I'm finding some difficulties.
I discovered that from version 3, annotations brought many advantages so, controller classes do not have to implement abstract classes (i.e. SimpleFormController), but this means that there are not mandatory methods to implement.
So my question is: which are the common useful methods that one should implement in a controller class?
You only have to implement the methods you wish to correspond to the actions from your various webpages - e.g. to accept the input of a form.
What specific difficulties are you having?
The methods will have relevant annotations to denote that they should be invoked for a particular URL. For example in following code (taken from Official Doc.),
#Controller
public class HelloWorldController {
#RequestMapping("/helloWorld")
public String helloWorld(Model model) {
model.addAttribute("message", "Hello World!");
return "helloWorld";
}
}
helloWorld(Model model) is just any method in a any class. What makes it special is the annotation #RequestMapping which tell that this method should invoked when the requesting URL is /helloWorld
Similar to Santosh I recommend you look at the official doc and the Javadoc: http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/web/bind/annotation/RequestMapping.html
Basically instead of overriding methods your going to use annotations on methods and based on the parameter annotations and method arguments different things will happen. The Javadoc above states the equivalent annotations to be used instead overriding the simpleform methods.
Here is a complete example of CRUD controller that I generated with Roo:
#Controller
#RequestMapping("/timers")
public class MyTimer {
#RequestMapping(method = RequestMethod.POST, produces = "text/html")
public String create(#Valid Timer timer, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
populateEditForm(uiModel, timer);
return "timers/create";
}
uiModel.asMap().clear();
timer.persist();
return "redirect:/timers/" + encodeUrlPathSegment(timer.getId().toString(), httpServletRequest);
}
#RequestMapping(params = "form", produces = "text/html")
public String createForm(Model uiModel) {
populateEditForm(uiModel, new Timer());
return "timers/create";
}
#RequestMapping(value = "/{id}", produces = "text/html")
public String show(#PathVariable("id") Long id, Model uiModel) {
uiModel.addAttribute("timer", Timer.findTimer(id));
uiModel.addAttribute("itemId", id);
return "timers/show";
}
#RequestMapping(produces = "text/html")
public String list(#RequestParam(value = "page", required = false) Integer page, #RequestParam(value = "size", required = false) Integer size, Model uiModel) {
if (page != null || size != null) {
int sizeNo = size == null ? 10 : size.intValue();
final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
uiModel.addAttribute("timers", Timer.findTimerEntries(firstResult, sizeNo));
float nrOfPages = (float) Timer.countTimers() / sizeNo;
uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
} else {
uiModel.addAttribute("timers", Timer.findAllTimers());
}
return "timers/list";
}
#RequestMapping(method = RequestMethod.PUT, produces = "text/html")
public String update(#Valid Timer timer, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) {
if (bindingResult.hasErrors()) {
populateEditForm(uiModel, timer);
return "timers/update";
}
uiModel.asMap().clear();
timer.merge();
return "redirect:/timers/" + encodeUrlPathSegment(timer.getId().toString(), httpServletRequest);
}
#RequestMapping(value = "/{id}", params = "form", produces = "text/html")
public String updateForm(#PathVariable("id") Long id, Model uiModel) {
populateEditForm(uiModel, Timer.findTimer(id));
return "timers/update";
}
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = "text/html")
public String delete(#PathVariable("id") Long id, #RequestParam(value = "page", required = false) Integer page, #RequestParam(value = "size", required = false) Integer size, Model uiModel) {
Timer timer = Timer.findTimer(id);
timer.remove();
uiModel.asMap().clear();
uiModel.addAttribute("page", (page == null) ? "1" : page.toString());
uiModel.addAttribute("size", (size == null) ? "10" : size.toString());
return "redirect:/timers";
}
void populateEditForm(Model uiModel, Timer timer) {
uiModel.addAttribute("timer", timer);
}
}

Categories