Spring Controller Test - object in controller is null - java

I try to test a controller and have a problem with an object City c = cityService.findByID(city); It is always null when I run the test. If I run the program and not the test it works as it should.
City c shouldn't be null because it is an object which should be fetched from DB by city id of last selected city(option from dropdown list) and I pass the city id here: .param("city", String.valueOf(306)).
void selectCityTest() throws Exception { //post
Integer voivodeship = 10;
Integer city = 306;
List<City> cities = cityService.getAllCitiesByVoivodeship(voivodeship);
mockMvc.perform(MockMvcRequestBuilders.post("/select_city")
.contentType(MediaType.APPLICATION_JSON)
.param("city", String.valueOf(306))
.content(new Gson().toJson(cities)))
.andExpect(status().isOk());
}
Controller.java
#RequestMapping(value = "/select_city", method = RequestMethod.POST)
public String selectCity(Integer city, Model model) {
City c = cityService.findByID(city);
List<City> cities = cityService.getAllCitiesByVoivodeship(c.getVoivodeship().getId());
model.addAttribute("cities", cities);
model.addAttribute("city_selected", city);
return "taxoffice";
}

Related

Send value from controller to another controller in Spring Boot

I have two method in different controller class
#RequestMapping(value="/addHari")
public String menuAddHari(HttpServletRequest request,#RequestParam(value="addchkmerah",required = false)String status, Model model) throws ParseException {
Date hariKerja = new SimpleDateFormat("yyyy-MM-dd").parse(request.getParameter("addharikerja"));
java.sql.Date workDay = new java.sql.Date(hariKerja.getTime());
String keterangan = request.getParameter("addkolomket");
Time jamMasuk = hs.getTime(request.getParameter("addjammasuk"));
Time jamKeluar = hs.getTime(request.getParameter("addjampulang"));
month = request.getParameter("addBulan");
HariKerjaModel hm = new HariKerjaModel();
hm.setKeterangan(keterangan);
hm.setTanggal(workDay);
hm.setMerahBukan(status);
hm.setJamMasuk(jamMasuk);
hm.setJamKeluar(jamKeluar);
hs.saveDate(hm);
model.addAttribute("month", month);
return "redirect:/hariKerja";
}
and
#RequestMapping(value="/hariKerja")
public String menuHariKerja(Model model,HttpServletRequest request) {
List<HariKerjaModel> hk = new ArrayList<>();
String month = request.getParameter("bulansrc");
HariKerjaController h = new HariKerjaController();
String x=h.getMonth();
if(month==null) {
String month2 = (String) model.getAttribute("month");
}
hk = hs.readHariKerja(month);
model.addAttribute("ListHariKerjaModel", hk);
model.addAttribute("valueSelected",month);
return "hariKerja";
}
how to pass value variable "month" in method "menuAddHari" to variable "month2" in method "menuHariKerja" ?
You can achieve your requirement while redirect your request with path or query or body containing entity or fields which are url-form-encoded.
return StringBuffer("redirect:/your/other/controller/method/")
.append(param1).append("/").append(param2);
And you will be able to handle the request in your other controller with :
#GetMapping(value="/your/other/controller/method/{param1}/{param2}")
public String otherMethodInOtherController(#PathVariable("paramName1") String param1, #PathVariable("paramName2") String param2) {
// your 2sd controller code here...
return "your-view-name";
}
Of course, if you have many parameters to send, it will be better to set a ResponseEntity with BodyInserters inside the body of your request before to send it to your 2sd controller.
And don't forget not to use GET methods to forward sensitive user|system datas.

I get an empty list, have error when querying java spring

I have problems, when I do a query, the list is empty
#Override
public List<QcReport> listQc3(double year, String hole_id) {
Session session = this.sessionFactory.getCurrentSession();
List report = session.createQuery("SELECT hole_id,year FROM QcReport where year = " +year+" AND hole_id = :hole_id")
// .setParameter("year", year)
.setParameter("hole_id", hole_id)
.list();
System.out.println(report);
return report;
}
controller
#RequestMapping(value = "/qc_table")
public ModelAndView listReport(#ModelAttribute("report") QcReport assay,Model model) throws IOException {
ModelAndView mod = new ModelAndView("qc_table");
QcReport hole = new QcReport();
List<QcReport> list = qcServ.listQc3(hole.getYear(),hole.getHole_id());
model.addAttribute("listReporte", list);
// mod.addObject("listReporte", list);
return mod;
}
the output of my code is empty,
when I execute my code
Hibernate:
select
qcreport0_.hole_id as col_0_0_,
qcreport0_.year as col_1_0_
from
vw_dhqc_report qcreport0_
where
qcreport0_.year=0.0
and qcreport0_.hole_id=?
[]

Unit Tests Junit NullPointerException and NoSuchElement help! Rest endpoints

When I am accessing my class to test the methods, I am getting exceptions every time I try to define a new object and use the newly defined object.
Tests in error:
UserInformationControllerTest.deleteUser:83 » NullPointer
UserInformationControllerTest.getUserInfo:27 » NullPointer
UserInformationControllerTest.updateUserInfo:68 » NullPointer
UserOrderControllerTest.createUserOrder:60 » NoSuchElement
UserOrderControllerTest.getUserOrder:47 » NullPointer
UserOrderControllerTest.updateUserOrder:85 » NullPointer
My assignment is to make 4 happy cases and 4 unhappy cases for each class
I am thoroughly confused.
My test class for UserInformation
private HashMap<Integer,UserInformation> userInformationHashMap;
#Test
public void getUserInfo(){
UserInformationController userInformationController = new UserInformationController();
this.userInformationHashMap = new HashMap<>();
int user0 = 0;
int user1 = 1;
UserInformation userInformation0 = new UserInformation("Doug","Jones", "djones#gmail.com","17073");
UserInformation userInformation1 = new UserInformation("Natalie","Peirce", "nataliepeirce12#yahoo.com","dynamicrabbit");
this.userInformationHashMap.put(user0,userInformation0);
this.userInformationHashMap.put(user1,userInformation1);
userInformationController.getUserInfo(user0);
userInformationController.getUserInfo(user1);
Assert.assertEquals(userInformationController.getUserInfo(user0),userInformationController.getUserInfo(user1)); //False
Assert.assertNotEquals(user0,user1); //True
}
#Test
public void createUser(){
UserInformationController userInformationController = new UserInformationController();
this.userInformationHashMap = new HashMap<>();
UserInformation userInformation0 = new UserInformation("Troy","Green","tjg217#verizon.com","2012hummingbirds");
UserInformation userInformation1 = new UserInformation("Sierra", "West","themostimportantwest#msn.com","shadeyglasses77");
int user0 = userInformationController.createUser(userInformation0);//Can you tell me why this does not work
int user1 = userInformationController.createUser(userInformation1);//Can you tell me why this does not work
this.userInformationHashMap.put(user0, userInformation0);
this.userInformationHashMap.put(user1, userInformation1);
Assert.assertNotEquals(this.userInformationHashMap.get(user0),this.userInformationHashMap.get(user1)); //True
Assert.assertNotNull(this.userInformationHashMap.get(user0)); //False
}
#Test
public void updateUserInfo(){
UserInformationController userInformationController = new UserInformationController();
this.userInformationHashMap = new HashMap<>();
int userId = 0;
UserInformation userInformation = new UserInformation("Nicole", "Rigby", "sexygirl69#babellon.com","throwmethemoney");
UserInformation newUserInformation = new UserInformation("Kitty", "Morgan", "ilovecats#cats.com","cats");
this.userInformationHashMap.put(userId,userInformation);
Assert.assertEquals(this.userInformationHashMap.get(userId),userInformation); //True
userInformationController.updateUserInfo(userId,newUserInformation); //Can you tell me why this does not work
Assert.assertNotEquals(this.userInformationHashMap.get(userId),newUserInformation); //False
}
#Test
public void deleteUser(){
UserInformationController userInformationController = new UserInformationController();
this.userInformationHashMap = new HashMap<>();
int user = 0;
UserInformation userInformation = new UserInformation("Camryn","Resele","smartcookie#email.com","28564088");
this.userInformationHashMap.put(user,userInformation);
userInformationController.deleteUser(user);
Assert.assertNull(this.userInformationHashMap.get(user)); //True
Assert.assertTrue(this.userInformationHashMap.containsKey(user)); //False
}
}
UserInformationController
private HashMap<Integer,UserInformation> userInformationHashMap;
/**
* Default json constructor`enter code here`
* #return new user object
*/
#GetMapping(path = "/defaultUserInformation")
public UserInformation test()
{
return new UserInformation("fname", "lname", "email", "pass");
}
/**
* Gets the users information
* #return users information
*/
#GetMapping (path = "/userInfo")
public UserInformation getUserInfo(#RequestParam ("id") int id){
return userInformationHashMap.get(id);
}
/**
* Sets the users information
* #param userInformation userInformation model
* #return users key
*/
#PostMapping (path = "/createUser")
public int createUser(#RequestBody UserInformation userInformation){
if(this.userInformationHashMap == null){
this.userInformationHashMap = new HashMap<>();
}
int maxKey = 0;
if(this.userInformationHashMap.size() != 0){
maxKey = Collections.max(this.userInformationHashMap.keySet()) + 1;
}
this.userInformationHashMap.put(maxKey,userInformation);
return maxKey;
}
#PutMapping (path = "/updateUserInfo")
public void updateUserInfo(#RequestParam ("id") int id, #RequestBody UserInformation userInformation) {
if (this.userInformationHashMap.containsKey(id)) {
this.userInformationHashMap.put(id, userInformation);
}
}
#DeleteMapping (path = "/deleteUser")
public void deleteUser(#RequestParam ("id") int id){
this.userInformationHashMap.remove(id);
}
}
userInformationHashMap within UserInformationController is never initialized, this is why you're getting the NullPointerExceptions.
You're initializing the HashMap in the createUser endpoint and it's never being called within the test.
The createUser endpoint I can't see where it's failing, but anyway this code should really be reorganized because it has many points of failure. The HashMapshould really be initialized when the Bean is created, and you should revisit the way you are calculating the Key.
Also for Controller testing purposes, you should be using MockMvc instead of calling controller methods directly.

Spring MVC annotation #ModelAttribute

i have some question about Spring MVC annotation #ModelAttribute.
In first method named as "addProduct" i create Model model and after call model.addAttribute i can use "product" name in jsp file,for example product.getProductPrice.
But in second method named same as first,i added parameter
" #ModelAttribute("product") Product product ",but why??
If i will delete this annotation, my program works as same as before,please explain me)
Thank you very much,sorry for my English,i am from Ukraine)
#RequestMapping("/admin/productInventory/addProduct")
public String addProduct(Model model) {
Product product = new Product();
// add default for radio button!
product.setProductCategory("Mobile Phone");
product.setProductCondition("New");
product.setProductStatus("active");
model.addAttribute("product", product);
return "addProduct";
}
#RequestMapping(value = "/admin/productInventory/addProduct", method = RequestMethod.POST)
public String addProduct(#ModelAttribute("product") Product product, HttpServletRequest request) {
productDao.addProduct(product);
MultipartFile productImage = product.getProductImage();
String rootDirectory = request.getSession().getServletContext().getRealPath("/");
System.out.println(rootDirectory);
// product id as the file name
// !!!! TODO
// path = Paths.get(rootDirectory + "/WEB-INF/resources/image/" +
// product.getProductId() + ".png");
path = Paths.get("F:\\Spring\\eMusicStore\\src\\main\\webapp\\WEB-INF\\resources\\images\\"
+ product.getProductId() + ".png");
if (productImage != null && !productImage.isEmpty()) {
try {
productImage.transferTo(new File(path.toString()));
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("Product image saving failed", e);
}
}
return "redirect:/admin/productInventory";
}
Purpose #ModelAttribute is bind param/properties from request a model object,
say #ModelAttribute("person") Person person in your method, it will bind properties from object such name, age to Person and construct a object out of it. It does not pass anything to your view, it job finishes once the request submitted. Not carried down to the view of that action.
In contrast, when you have Model model you are explicitly constructing an object with property added to its attribute. It will be carried down to your view unlike what #ModelAttribute does above

Spring MVC, attempting to edit but creating new objects

I have an MVC app that is creating new offices instead of updating them on when using an edit form. Please help me understand why this is happening.
Search method that populates the search results:
#RequestMapping(value = "/searchResults", method = RequestMethod.POST)
public ModelAndView search(#RequestParam String searchCriteria, HttpServletRequest request) {
List<Office> offices = officeServiceImpl.search(searchCriteria);
return new ModelAndView("searchResults", "offices", offices);
}
Here's what the link to the edit form looks like on the search results page:
Edit Office
Here is the Controller's edit GET method that populates the form with the existing Office:
#RequestMapping(value = "/{officeId}/edit", method = RequestMethod.GET)
#Transactional(noRollbackFor=NoResultException.class)
public ModelAndView initUpdateOfficeForm(
#PathVariable("officeId") Long officeId, Model model) {
Office office = officeServiceImpl.find(officeId);
//prepareEditFormModelAndView(office) just converts some objects to strings for typeahead form population
return prepareEditFormModelAndView(office);
}
Here is the edit POST method:
#RequestMapping(value = "/{officeId}/edit", method = RequestMethod.POST)
public ModelAndView processUpdateOfficeForm(#ModelAttribute("office") #Valid Office office,
BindingResult result, SessionStatus status) {
if (! "united states of america".equals(office.getFolderStrings().toLowerCase())) {
//This portion of code converts the typeahead strings to objects
result = tryCountries(office, result);
result = tryDepartments(office, result);
result = tryEmployees(office, result);
}
if (result.hasErrors()) {
return prepareEditFormModelAndView(office);
} else {
officeServiceImpl.save(office);
status.setComplete();
return new ModelAndView("editResult", "office", office);
}
}
officeServiceImpl calls officeRepositoryImpl method save which looks like:
#Override
public Office save(Office office) {
em.merge(office);
em.flush();
return office;
}
Thanks
Edit: Adding prepareEditFormModelAndView(office), This method attempts to build strings from associated objects:
#Transactional(noRollbackFor={NoResultException.class, IndexOutOfBoundsException.class})
private ModelAndView prepareEditFormModelAndView(Office office) {
String departmentStrings = "";
String employeeStrings = "";
List<OOM> officeOOMs = new ArrayList<OOM>();
StringBuilder sb = new StringBuilder();
try {
officeOOMs = oomServiceImpl.getOOMsForCurrentOffice(office.getId());
} catch (NoResultException e) {
officeOOMs = null;
}
for (OOM o : officeOOMs) {
try {
Employee tempEmployee = employeeServiceImpl.find(o
.getEmployeeId());
sb.append(tempEmployee.getDisplayName() + ", ");
} catch (NoResultException e) {
sb.append("Not found in system");
}
}
employeeStrings = sb.toString();
if ((! "".equals(office.getDepartmentStringsOnForm())) && office.getDepartmentStringsOnForm() != null) {
departmentStrings = office.getDepartmentStringsOnForm();
}
String folderStrings = "";
try {
folderStrings = kmlFolderServiceImpl.getInternationalOfficeString(office.getId());
LOGGER.info("Folder Strings: " + folderStrings);
} catch (NoResultException e) {
folderStrings = "";
LOGGER.info("Folder Strings: " + "no result");
}
boolean isInternational = office.isInternational();
ModelAndView result = new ModelAndView("editOfficeForm", "office", office);
result.addObject("departmentStrings", departmentStrings);
result.addObject("isInternational", isInternational);
result.addObject("folderStrings", folderStrings);
result.addObject("employeeStrings", employeeStrings);
return result;
}
I am adding a previous comment here, for better clarification. According to the OP the following fixes the problem:
When the ID is not in the form then when the model is posted back no ID is set to the entity making the persistence provider believe it is new entity.
Therefor the most obvious solution is to post the ID of the entity as well in the save operation (probably using a hidden field).
Another solution would be to try to load the entity in the database based on some business key
to see if the entity is new or not.

Categories