I'm working on a Spring MVC project and I use thymeleaf for my html pages. I created a session variable in VariableSessionController. However when I call my session variable in my html pages with #session (for session variable in thymeleaf) it won't work. But it work if I call it as a model variable. Then I try to get my session variable after calling an other controller but he didn't find the resource I'm calling.
Here is my controller wher I create my session variable
#Controller
#SessionAttributes("country")
public class VariableSessionController extends AbstractController {
#ModelAttribute("country")
public Country country() {
Country country = new Country();
country.setCodeCountry("FR");
return country;
}
}
Here is where I call this controller.
#Controller
public class FrontpageController extends VariableSessionController {
#Autowired
private ConsulterInformationsFinancieres infosFinancieres;
#RequestMapping(value = "/")
public String welcome(Model model) {
model.addAttribute("version","V1.1");
return PageTemplates.INDEX;
}
}
Here is the second controller I'm calling to try my session variable.
#Controller
public class AdvancedSearchController extends AbstractController {
#RequestMapping(value = "/recherche", method = RequestMethod.GET)
public String init(#RequestParam Map<String, String> requestParams, Model model) {
String debug = String.valueOf(model.containsAttribute("country"));
logger.info(debug); // return false
model.addAttribute("label", "label");
return PageTemplates.ADVANCED_SEARCH;
}
}
Thanks for your help!
Related
I get org.springframework.beans.factory.UnsatisfiedDependencyException when i call SaleRestService in ProductRestService like in the code below.
How can i do it properly?
#RestController
#CrossOrigin("*")
public class ProductRestService {
#Autowired
private ProductRepository productRepository;
#Autowired
public SaleRestService saleRestService ;
#RequestMapping(value="/productQuatityMinusOne", method=RequestMethod.GET)
#ResponseBody
public void ProductQuatityMinusOne(#RequestParam(name="id") Long id){
Product p = productRepository.findProductById(id);
double salePrice = p.getPrice();
Date now = new java.util.Date();
Sale s = new Sale(id,salePrice,now);
saleRestService .saveOneSale(s);
p.setId(id);
int q = p.getQuantity()-1;
p.setQuantity(q);
productRepository.save(p);
}
}
#RestController
#CrossOrigin("*")
public class SaleRestService {
#Autowired
private SaleRepository saleRepository;
//Save one sale
#RequestMapping(value="/saveOneSale", method=RequestMethod.POST)
#ResponseBody
public Sale saveOneSale(#RequestBody Sale s){
return saleRepository.save(s);
}
}
You should not be calling your controllers from one another.
Two solutions:
Put the code of the saveOneSale in another #Service, and call that from your #RestControllers
You could redirect the http call of ProductQuatityMinusOne in ProductRestService to saveOneSale in SaleRestService by using a spring boot redirect, like this return "redirect:/saveOneSale";, but I dont know if that will work because you'd be redirecting to a POST handler.
Personlly I'd do the first solution:
remove #RestController from SaleRestService
create a SaleRestController class, anotate it with #RestController, and put a method with the following annotation: #RequestMapping(value="/saveOneSale", method=RequestMethod.POST)
in that method, call SaleRestService.saveOneSale
Everything should just work (TM)
I have following controller to return view:
#RequestMapping(value = "/admin/adminUsers", method = RequestMethod.GET)
public String adminUsers(ModelMap model, HttpSession session) {
Set<TerminalAdmin> users = terminalAdminService.getAllAdmins();
session.setAttribute("users", users);
model.addAttribute("adminRoles", terminalAdminService.findAllAdminRoles());
model.addAttribute("terminalAdmin", new TerminalAdmin());
model.addAttribute("generatedPassword", PasswordUpdateStatus.generatePassword());
return "admin/adminUsers";
}
terminalAdminService.findAllAdminRoles()
returns collection with ids:
On jsp I render it like this:
<form:form modelAttribute="terminalAdmin" action="/admin/addNewAdmin">
...
<form:checkboxes items="${adminRoles}" path="adminRoles"/>
...
</form:form>
I have the follwing controller to accept this object:
#RequestMapping(value = "/admin/addNewAdmin")
public String adminUsers(#ModelAttribute #Valid TerminalAdmin terminalAdmin...){
....
}
In debug I see that terminalAdmin comes with adminRoles without ids.
How to fix this?
P.S.
It is continue of Dependent collection duplicates when I save entity
i prefer to use Converters, because for me it's cleaner
you should have something like the following:
public class StringToAdminRoleConverter implements Converter<String, AdminRole> {
#Autowired
TerminalAdminService terminalAdminService;
#Override
public AdminRole convert(String role) {
return terminalAdminService.findRoleByName(role);
}
}
I am pretty new in Spring MVC and I have the following doubt.
In a controller, I have a method annotated in this way:
#Controller
#RequestMapping(value = "/users")
public class UserController {
#RequestMapping(params = "register")
public String createForm(Model model) {
model.addAttribute("user", new Customer());
return "user/register";
}
}
So this method handle HTTP Request toward the URL /users?register where register is a parameter (because the entire class handle request toward /users resource).
Is it the same thing if, instead using the params = "register" I use the following syntaxt:
#Controller
public class UserController {
#RequestMapping("/users/{register}")
public String createForm(Model model) {
model.addAttribute("user", new Customer());
return "user/register";
}
}
I have deleted the mapping at class level and I use #RequestMapping("/users/{register}").
Is it the same meaning of the first example?
NO, they are completely different constructs:
Code 1
#Controller
#RequestMapping(value = "/users")
public class UserController {
#RequestMapping(params = "register")
public String createForm(Model model) {
model.addAttribute("user", new Customer());
return "user/register";
}
}
In this case, createForm method will be called when a HTTP request is made at URL /users?register. Quoting from Spring Javadoc, it means this method will be called whatever the value of the register HTTP parameter; it just has to be present.
"myParam" style expressions are also supported, with such parameters having to be present in the request (allowed to have any value).
Code 2
#Controller
public class UserController {
#RequestMapping("/users/{register}")
public String createForm(Model model) {
model.addAttribute("user", new Customer());
return "user/register";
}
}
In this case, #RequestMapping is declaring register as a PathVariable. The method createForm will be called if a HTTP request is made at URL /users/something, whatever the something. And you can actually retrieve this something like this:
#RequestMapping("/users/{register}")
public String createForm(#PathVariable("register") String register, Model model) {
// here "register" will have value "something".
model.addAttribute("user", new Customer());
return "user/register";
}
I'm trying out Spring MVC 3.0 for the first time and like to make it RESTfull.
This is my controller:
#Controller
#RequestMapping(value = "/product")
#SessionAttributes("product")
public class ProductController {
#Autowired
private ProductService productService;
public void setProductValidator(ProductValidator productValidator, ProductService productService) {
this.productService = productService;
}
#RequestMapping(method = RequestMethod.GET)
public Product create() {
//model.addAttribute(new Product());
return new Product();
}
#RequestMapping(method = RequestMethod.POST)
public String create(#Valid Product product, BindingResult result) {
if (result.hasErrors()) {
return "product/create";
}
productService.add(product);
return "redirect:/product/show/" + product.getId();
}
#RequestMapping(value = "/show/{id}", method = RequestMethod.GET)
public Product show(#PathVariable int id) {
Product product = productService.getProductWithID(id);
if (product == null) {
//throw new ResourceNotFoundException(id);
}
return product;
}
#RequestMapping(method = RequestMethod.GET)
public List<Product> list()
{
return productService.getProducts();
}
}
I have 2 questions about this.
I'm a believer in Convention over Configuration and therefor my views are in jsp/product/ folder and are called create.jsp , list.jsp and show.jsp this works relatively well until I add the #PathVariable attribute. When I hit root/product/show/1 I get the following error:
../jsp/product/show/1.jsp" not found how do I tell this method to use the show.jsp view ?
If I don't add the RequestMapping on class level my show method will be mapped to root/show instead of root/owner/show how do I solve this ? I'd like to avoid using the class level RequestMapping.
add your 'product' to Model and return a String /product/show instead of Product. In your show.jsp, you can access the product object form pageContext
Check out the section in the manual about "Supported handler method arguments and return types".
Basically, when your #RequestMapping method returns just an object, then Spring uses this as a single model attribute, and, I'm guessing, attempts to use the request URL as the basis for the view name.
The easiest way to return the view and data you want from the same method is probably to just have the method return a ModelAndView, so you can explicitly specify the viewName and the model data.
I want to read a domain object (UserVO) from session scope.
I am setting the UserVO in a controller called WelcomeController
#Controller
#RequestMapping("/welcome.htm")
public class WelcomeController {
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(BindingResult result, SessionStatus status,HttpSession session){
User user = loginService.loginUser(loginCredentials);
session.setAttribute("user", user);
return "loginSuccess";
}
}
I am able to use the object in jsp pages <h1>${user.userDetails.firstName}</h1>
But I am not able to read the value from another Controller,
I am trying to read the session attribute as follows:
#Controller
public class InspectionTypeController {
#RequestMapping(value="/addInspectionType.htm", method = RequestMethod.POST )
public String addInspectionType(InspectionType inspectionType, HttpSession session)
{
User user = (User) session.getAttribute("user");
System.out.println("User: "+ user.getUserDetails().getFirstName);
}
}
The code you've shown should work - the HttpSession is shared between the controllers, and you're using the same attribute name. Thus something else is going wrong that you're not showing us.
However, regardless of whether or not it works, Spring provides a more elegant approach to keeping your model objects in the session, using the #SessionAttribute annotation (see docs).
For example (I haven't tested this, but it gives you the idea):
#Controller
#RequestMapping("/welcome.htm")
#SessionAttributes({"user"})
public class WelcomeController {
#RequestMapping(method = RequestMethod.POST)
public String processSubmit(ModelMap modelMap){
User user = loginService.loginUser(loginCredentials);
modelMap.addtAttribute(user);
return "loginSuccess";
}
}
and then
#Controller
#SessionAttributes({"user"})
public class InspectionTypeController {
#RequestMapping(value="/addInspectionType.htm", method = RequestMethod.POST )
public void addInspectionType(InspectionType inspectionType, #ModelAttribute User user) {
System.out.println("User: "+ user.getUserDetails().getFirstName);
}
}
However, if your original code isn't working, then this won't work either, since something else is wrong with your session.
#SessionAttributes works only in context of particular handler, so attribute set in WelcomeController will be visible only in this controller.
Use a parent class to inherit all the controllers and use SessionAttributes over there. Just that this class should be in the package scan of mvc.
May be you have not set your UserVO as Serializable.