Controller Testing For SPRING-MVC - spring

I am getting error in my controller Saying Null Pointer Exception while When I don't perform the testing. Everything works fine.
Controller :
#RequestMapping(value = "/studentinsection/{sectionId}", method = RequestMethod.GET)
public ModelAndView studentInSectionForm(#ModelAttribute("studentInSectionFormData") StudentInSectionForm studentInSectionFormData,
#PathVariable Integer sectionId,
ModelMap model) {
ArrayList<StudentInSections> studentInSectionList = (ArrayList<StudentInSections>)
studentInSectionsService.retrieveAllStudentInSections(sectionId, 1);
StudentSection studentSection = studentSectionService.retrieveStudentSection(sectionId);
logger.info("section Name is:" + studentSection.getSectionName());
ArrayList<User> userList = new ArrayList<User>();
for (StudentInSections studentInSections : studentInSectionList) {
String studentName =
(userService.retrieveUserName(studentInSections.getStudentId(), 1));
User users = userService.retrieveUser(studentName);
userList.add(users);
}
logger.info("sectionId is " + sectionId);
ArrayList<User> allStudents = (ArrayList<User>)
userService.retrieveAllStudents();
studentInSectionFormData.setStudentInSectionList(studentInSectionList);
model.addAttribute("studentList", allStudents);
model.addAttribute("userList", userList);
model.addAttribute("studentSectionName", studentSection.getSectionName());
model.addAttribute("studentSectionId", studentSection.getSectionId());
return new ModelAndView("studentinsection", "studentInSectionFormData", studentInSectionFormData);
}
Testing is as follow:
#Test
public void testStudentInSectionForm() throws Exception {
mockMvc.perform(get("/studentinsection/1"))
.andExpect(status().isFound())
.andExpect(redirectedUrl("studentinsection"));
}
this is passing everything into the controller fine even sectionId is getting printed 1 in logger than also studentin sectionList returns nullMointerException. help me to resolve my problem.. Thanx

It slooks like the context is not being loaded correctly. What is the exception stacktrace.
You can also view the request if you do :
mockMvc.perform(get("/studentinsection/1"))
.andExpect(status().isFound())
.andDo(print())

Related

how to access GetMapping notation from postman with HttpServletRequest

I have a spring boot controller but I don't know how to access the GetMapping notation through postman application. This is my controller:
#GetMapping
public ResponseEntity<dataTableDTO> getProject(HttpServletRequest request, int draw) throws Exception {
//... do what needs to be done
List<ProjectEntity> objProj = (List<ProjectEntity>) projectRepository.findAll();
List<String> slist = new ArrayList<String>();
for(ProjectEntity d : (List<ProjectEntity>)objProj){
slist.add(String.valueOf(d.getCustomerId()));
}
String listCustId = StringUtils.collectionToCommaDelimitedString(slist);
List<CustomerDTO> objCust = (new CustomerDAO()).getCustomer(listCustId, request.getHeader("Authorization"));
List<ProjectDTO> objProjDTO = new ArrayList<ProjectDTO>();
for(ProjectEntity d : (List<ProjectEntity>)objProj){
String name = "";
for(CustomerDTO c : objCust){
if(c.getId() == d.getCustomerId()){
name = c.getFirstName() + " " + c.getLastName();
}
}
objProjDTO.add(new ProjectDTO(d.getId(), d.getCustomerId(), name, d.getName(), d.getType()));
}
dataTableDTO data = new dataTableDTO(draw, objProjDTO.size(), objProjDTO.size(), objProjDTO, null);
return new ResponseEntity<dataTableDTO>(data, HttpStatus.OK);
}
I just want to know how to access the GetMapping notation through postman. I already try but i got error
error image
Put a #RequestParam annotation on your draw variable?
#GetMapping
public ResponseEntity<dataTableDTO> getProject(HttpServletRequest request, #RequestParam(name="draw") int draw) throws Exception {...}

Adding #ModelAttribute results in 400 (Bad Request) in Delete Request

I can submit a delete request fine with the following:
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteTest(#PathVariable String id) {
return new ResponseEntity<>(Result.Success("Hi " + id + "!!!", null), HttpStatus.OK);
}
However, when I add an #ModelAttribute variable, I get 400 (Bad Request) as the http response code:
#RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteTest(#PathVariable String id, #ModelAttribute("authUser") User authUser) {
return new ResponseEntity<>(Result.Success("Hi " + id + "!!!", null), HttpStatus.OK);
}
This #ModelAttribute is working fine with a put request handler I have in my #RestController but not in this delete request.
Here's the #ModelAttribute code:
#ModelAttribute("authUser")
public User authUser(#AuthenticationPrincipal SpringAuthUser springAuthUser) throws Exception {
User user = ConstantsHome.userprofileMgr.getUserByUserId(springAuthUser.getUsername(), true, true);
user.updateRights(null);
request.getSession().setAttribute(ConstantsHome.USEROBJECT_KEY, user);
return user;
}
Why would adding #ModelAttribute cause a delete request to return a 400 (Bad Request) http response?
I'm using spring-web-4.1.4 & spring-security-4.0.3
I digged a little and found that specifying a #PathVariable of "id" somehow attaches it to the #ModelAttribute variable (as a Long(!) instead of a String as I specified). I then came across this post that lead me to different ways to resolve the issue :
Values of #PathVariable and #ModelAttribute overlapping.
Ended up with this as a method declaration (replaced "id" with "userId"):
#RequestMapping(value = "/{userId}", method = RequestMethod.DELETE)
public ResponseEntity<Result> deleteUser(#PathVariable String userId,
#ModelAttribute("authUser") User authUser) {
...
}
Hopefully this will help someone else quickly that might run into this issue instead of spending a day trying to figure it out...

Migrating to Spring MVC 4

We are migrating our mvc code to Spring 4. Previously we had a a method formBackingObject which we converted to get method initForm.
But trouble is - in previous controller which was extending SimpleFormController, formBackingObject was getting called even before submit method. We have now removed SimpleFormController. But initForm is getting called only only once on page load. It doesn't get called before submit. And there is some custom logic of creating user object and adding to UserProfileForm object.
Have you faced similar issue.
Old code
protected Object formBackingObject(HttpServletRequest request) throws Exception {
final UserProfileForm userProfileForm = new UserProfileForm();
final String id = request.getParameter("id");
if (id != null && !id.trim().equals("")) {
final User user = authenticationServices.findUser(ServletRequestUtils.getLongParameter(request, "id"));
userProfileForm.setUser(user);
} else {
final User user = new User();
userProfileForm.setUser(user);
}
return userProfileForm;
}
new code
#RequestMapping(method = RequestMethod.GET)
public String initForm(HttpServletRequest request, ModelMap model) throws Exception{
final UserProfileForm userProfileForm = new UserProfileForm();
final String id = request.getParameter("id");
if (id != null && !id.trim().equals("")) {
final User user = authenticationServices.findUser(ServletRequestUtils.getLongParameter(request, "id"));
userProfileForm.setUser(user);
} else {
final User user = new User();
userProfileForm.setUser(user);
}
addToModel(request, model);
model.addAttribute("userProfileForm", userProfileForm);
return "user-management/user-profile";
}
Create a method annotated with #ModelAttribute to fill your model.
#ModelAttribute("userProfileForm");
public UserProfileForm formBackingObject(#RequestParam(value="id", required=false) Long id) throws Exception{
final UserProfileForm userProfileForm = new UserProfileForm();
if (id != null) {
final User user = authenticationServices.findUser(id);
userProfileForm.setUser(user);
} else {
final User user = new User();
userProfileForm.setUser(user);
}
return userProfileForm;
}
#RequestMapping(method = RequestMethod.GET)
public String initForm() {
return "user-management/user-profile";
}
This way you can also use the #RequestParam annotation instead of pulling out parameters yourself.
See the reference guide for more information on the subject.
Certain inter-module dependencies are now optional at the Maven POM level where they were once required. For example, spring-tx and its dependence on spring-context. This may result in ClassNotFoundErrors or other similar problems for users that have been relying on transitive dependency management to pull in affected downstream spring-* . To resolve this problem, simply add the appropriate missing jars to your build configuration.

Spring MVC handle Exceptions and how to show in same view

If I handle exceptions with #ControllerAdvice and #ExceptionHandler How can I show error message to user in the same View. For ex. suppose user in "customer/new" view. and invoke "save" action, then it will go to controller and I call methods service layer. but if internal exception occurred in service layer, I want to show error message on same "customer/new" View.
I have written a separate class to handle exceptions as follow.
#ControllerAdvice
public class DefaultControllerHandler {
#ExceptionHandler({MyProjectException.class, DataAccessException.class})
public ResponseEntity<String> handleInternalErrorException(Exception e) {
logger.error(e.getMessage(), e);
return new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Appreciate your ideas.
Thanks!
You can use flash redirect attributes.
#RequestMapping(value = "/administrator/users", method = RequestMethod.POST)
public String adminAddUser(#ModelAttribute("user") #Valid User user, BindingResult bindingResult, Model model, RedirectAttributes redirectAttrs) {
String redirectUrl = "/administrator/users";
try {
userService.save(user);
} catch (YourServiceException e) {
redirectAttrs.addFlashAttribute("errorMessage", "error occured: " + e.getMessage());
redirectAttrs.addFlashAttribute("userObject", user);
redirectUrl = "/administrator/users?form"; // If error - return to same view
}
return "redirect:" + redirectUrl;
}
#RequestMapping(value = "/administrator/users", params = "form", method = RequestMethod.GET, produces = "text/html")
public String adminUsersList(#ModelAttribute("errorMessage") final String errorMessage, #ModelAttribute("userObject") final User user Model model) {
if(user == null) {
user = new User();
}
model.addAttribute("user", user);
if(errorMessage != null) {
model.addAttribure("errorMessage", errorMessage);
}
return "administrator/users/create";
}
In that case you must have section on your users.jsp page to show errorMessaage. Something like this:
<c:if test="${not empty errorMessage}">${errorMessage}</c:if>
If you can fetch url path and redirectAttributes from controller method - you can do this through #ControllerAdvice
The only solution I can think about is make your call to the service layer AJAX and then redirect only if there are no errors, if not display the error message.
It might look something like this in your Javascript file
$("#someButton").click(function(){
//make your ajax call
if (noError){
window.location.href = contextPath+"/somePath";
}
else{
//display your error message
}
});

Spring MVC + GWT : Redirect Issue

I am using Spring annotated MVC framework in an app which I am developing.
Following is the issue I am facing:
I have Controller which does a redirect, after a POST:
#RequestMapping(value = "/emdm-viewer-redirect.do", method = RequestMethod.POST)
public ModelAndView getMetricKeysAndRedirect(#RequestParam Object jsonObject, Model model)
{
ModelAndView modelAndView = new ModelAndView("redirect:/mdm-viewer.do");
.....
.....
....//make some service calls and populate value1
...
modelAndView.addobject("param1", value1);
return modelAndView;
}
I have another controller which is mapped to URL mdm-viewer.do (The redirect URL mentioned above):
#RequestMapping(value = "/mdm-viewer.do", method = RequestMethod.GET)
public String getMDMViewer(Model model) {
return "mdmViewer"; //returns a mdmViewer.jsp
}
Please note that the mdmviewer.jsp is a GWT entrypoint which is in classpath.
I have my firebug window open which tells me that a GET request was made for mdm-viewer.do, but it gives me a blank response. In fact, it does not redirect to the new jsp and stays on the same page from where the POST request was made.
However, if I copy the firebug URL and open it in a new window of my browser, I see the expected results.
Any ideas what I am doing wrong here? Tried to google it a lot, but can't find a similar issue anywhere.
Eventually, I returned a ModelAndView back from the POST method using a
#ResponseBody
And in my GWT Module, I used the response.getText() output to do a
#Override
public void onResponseReceived(Request request, Response response) {
if (200 == response.getStatusCode()) {
JSONObject jsonObject = (JSONObject) JSONParser.parse(response.getText());
String viewName = jsonObject.get("viewName").isString().stringValue();
JSONObject jsonParams = jsonObject.get("model").isObject();
Set<String> chartKeys = jsonParams.keySet();
String redirectURL = viewName + "?";
for (String keyString : chartKeys) {
redirectURL = redirectURL + keyString + "=" + jsonParams.get(keyString).isString().stringValue() + "&";
}
Window.open(GWT.getHostPageBaseURL() + redirectURL, "_self", "");
}
}

Resources