Spring MVC annotation #ModelAttribute - java

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

Related

SpringBoot - How do I create a request which can be based on user input and is then picked up by a controller method?

I have managed to send a parameterised request based on the URL entered by the user, however I am not sure how to get the 2nd controller to properly receive the route for the URL field of the Project class object. How do I do this? I don't even know what to search.
//ProjectController
//Creating Project Object
Project project = new Project();
System.out.println("userID: " + userID);
//Getting values using webuser userid (Parameter that passed by model attribute)
WebUser webUser = webUserRepo.findUserById(Long.parseLong(userID));
//Setting values to project object to save
project.setUserID(webUser);
project.setDescription(description);
project.setTargets(targets);
project.setUrl(url);
// Getting date
Date date = new Date();
project.setPublishedOn(date);
//Save Project Object and get that saved Object for system.print
Project savedProject = projectRepo.save(project);
//Print saved Object
System.out.println("saved Project Object : "+ savedProject.toString());
//Set user id in model attribute for return page
model.addAttribute("userID", userID);
model.addAttribute("url", url);
return "/project-dashboard/" + savedProject.getUrl();
//Dashboard Controller:
#GetMapping("project/{url}")
public String serveProject(#PathVariable("url") String url, #RequestParam Long userID, Model model){
System.out.println("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO ADKLLDAL " + userID);
Project project = projectRepo.getById(userID);
System.out.println(project.toString());
model.addAttribute(project);
return "project";
}
Thanks for any help!

Thyme, Spring: stuck on creating a single item view

I have successfully implemented adding a visit and showing a list of all visits, but now I'm stuck on creating a view for a single visit.
My findById function works:
logger.info("Visit id 2 -> {}", repository.findById(2));
Visit id 2 -> DentistVisitDTO[id='0', dentistName='Mait Kuusevaik', visitTime='2018-10-12T12:15']
And when I click on a list item it sucessfully redirects to a url using ID (i.e "/results/1" and so on. Is there a way I can use the ID from the URL and somehow render the item on the page using findById()?
I'm new to Spring and Thyme.
public DentistVisitDTO findById(long id) {
return jdbcTemplate.queryForObject("SELECT * FROM DENTIST_VISIT where id=?", new Object[] { id },
new BeanPropertyRowMapper<DentistVisitDTO>(DentistVisitDTO.class));
}
You can use the #RequestMapping annotation of SpringMVC/SpringWeb to get the id attribute from the URL:
import org.springframework.web.bind.annotation.RequestMapping;
#RequestMapping(value="/results/{id}", method=RequestMethod.GET)
public String detail(#PathVariable(value="id") String id, Model model) {
DentistVisitDTO dentistVisit = repository.findById(id);
System.out.println("GET /results [" + id + "]");
model.addAttribute("dentistVisit", dentistVisit);
return "details";
}

DynamoDB - how to get Primary Key (which is random id) from database to make endpoind class?

I've made method that I use to edit Item from database.
This is how my method looks:
public Product editProduct(PrimaryKey primaryKey, Product content) {
UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey(primaryKey).withValueMap(createValueMap(content));
UpdateItemOutcome itemOutcome = databaseController.getTable(PRODUCT_TABLE).updateItem(updateItemSpec);
return convertToProduct(itemOutcome);
}
private Map<String, Object> createValueMap(Product content) {
Map<String, Object> result = new HashMap<>();
result.put("name", content.getName());
result.put("calories", content.getCalories());
result.put("fat", content.getFat());
result.put("carbo", content.getCarbo());
result.put("protein", content.getProtein());
result.put("productKinds", content.getProductKinds());
result.put("author", content.getAuthor());
result.put("media", content.getMedia());
result.put("approved", content.getApproved());
return result;
}
private Product convertToProduct(UpdateItemOutcome itemOutcome) {
Product product = new Product();
product.setName(itemOutcome.getItem().get("name").toString());
product.setCalories(itemOutcome.getItem().getInt("calories"));
product.setFat(itemOutcome.getItem().getDouble("fat"));
product.setCarbo(itemOutcome.getItem().getDouble("carbo"));
product.setProtein(itemOutcome.getItem().getDouble("protein"));
product.setProductKinds(itemOutcome.getItem().getList("productKinds"));
ObjectMapper objectMapper = new ObjectMapper();
try {
Author productAuthor = objectMapper.readValue(itemOutcome.getItem().getString("author"), Author.class);
product.setAuthor(productAuthor);
} catch (IOException e) {
e.printStackTrace();
}
try {
Media productMedia = objectMapper.readValue(itemOutcome.getItem().getString("media"), Media.class);
product.setMedia(productMedia);
} catch (IOException e) {
e.printStackTrace();
}
return product;
}
Now I want to create endpoint class for this method but I have problem, I need to get primarykey as parameter (it's looks like this for example: 2567763a-d21e-4146-8d61-9d52c2561fc0) and I don't know how to do this.
At the moment my class looks like that:
public class EditProductLambda implements RequestHandler<Map<String, Object>, ApiGatewayResponse> {
private LambdaLogger logger;
#Override
public ApiGatewayResponse handleRequest(Map<String, Object> input, Context context) {
logger = context.getLogger();
logger.log(input.toString());
try{
Product product = RequestUtil.parseRequest(input, Product.class);
//PrimaryKey primaryKey = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
KitchenService kitchenService = new KitchenService(new DatabaseController(context, Regions.EU_CENTRAL_1), logger);
Product editedProduct = kitchenService.editProduct(primaryKey, product);
return ResponseUtil.generateResponse(HttpStatus.SC_CREATED, editedProduct);
} catch (IllegalArgumentException e){
return ResponseUtil.generateResponse(HttpStatus.SC_BAD_REQUEST, e.getMessage());
}
}
Can someone give me some advice how to do that? Or maybe my method is done wrong?
So first you have to create a trigger to Lambda function and ideal prefer here would be an API gateway. You can pass your data as query string or as a request body to API gateway.
You can use body mapping template in the integration request section of API gateway and get request body/query string. Construct a new json at body mapping template, which will have data from request body/query string. As we are adding body mapping template your business logic will get the json we have constructed at body mapping template.
Inside body mapping template to get query string please do ,
$input.params('querystringkey')
For example inside body mapping template (If using query string),
#set($inputRoot = $input.path('$'))
{
"primaryKey" : "$input.params('$.primaryKey')"
}
if passing data as body then,
#set($inputRoot = $input.path('$'))
{
"primaryKey" : "$input.path('$.primaryKey')"
}
Please read https://aws.amazon.com/blogs/compute/tag/mapping-templates/ for more details on body mapping template

the map of the model always returns an empty object

Good evening, I have a Spring MVC project on an e-commerce site.
concerning cart management, when I add a product to the cart by clicking the "Ajouter au panier", it adds good, but the problem if I add another product, I show that the second product .
I made "println" and I noticed that "model.asMap (). get (" panier ")" always returns null. what is the problem please?
Here are some screen prints on the console, controller and index.jsp
Controller
#RequestMapping(value = "/ajouterAuPanier")
public String ajouterAuPanier(#RequestParam Long idArticle, #RequestParam int quantite, Model model) {
System.out.println("111111111111111111111111111111111111111111111");
Panier panier = null;
if (model.asMap().get("panier") == null) {
System.out.println("222222222222222222222222222222222222222222222");
panier = new Panier();
System.out.println("333333333333333333333333333333333333333333333");
model.addAttribute("panier", panier);
System.out.println("9999999999999999999999999999999" + panier.getItems().size());
} else System.out.println("555555555555555555555555555555555555555555555");
panier = (Panier) model.asMap().get("panier");
panier.addArticle(metier.getArticle(idArticle), quantite);
model.addAttribute("categories", metier.listCategories());
model.addAttribute("articles", metier.listArticles());
return "index";
}

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