In Broadleaf Commerce framework, I am looking for a way to pull domain entity objects like product, admin user from entity form that we receice as model attribute in CRUD methods of EntityController classes like AdminProductController. Is it possible? If yes, how?
Below is a sample code from AdminProductController class.
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String addEntity(HttpServletRequest request, HttpServletResponse response, Model model,
#PathVariable Map<String, String> pathVars,
#ModelAttribute(value="entityForm") EntityForm entityForm, BindingResult result) throws Exception {
//some code
}
Related
I am trying to look for a way to extend a controller such that I can use the existing request mapping but with a different implementation/method tied to it.
Say for example, below is a code snippet from AdminBasicEntityController in BLC where viewAddEntityForm method is tied to /add request mapping. Now I want to have my own logic of showing entityForm(Say Product entity) using /add request mapping. Is it possible?
#Controller("blAdminBasicEntityController")
#RequestMapping("/{sectionKey:.+}")
public class AdminBasicEntityController extends AdminAbstractController {
#RequestMapping(value = "", method = RequestMethod.GET)
public String viewEntityList(HttpServletRequest request, HttpServletResponse response, Model model,
#PathVariable Map<String, String> pathVars,
#RequestParam MultiValueMap<String, String> requestParams) throws Exception {
// default implementation
}
#RequestMapping(value = "/add", method = RequestMethod.GET)
public String viewAddEntityForm(HttpServletRequest request, HttpServletResponse response, Model model,
#PathVariable Map<String, String> pathVars,
#RequestParam(defaultValue = "") String entityType) throws Exception {
// default implementation
}
}
Also I found below mentioned information in the documentation of AdminBasicEntityController, so does it mean I can have controller for specific entity. If yes, how?
The default implementation of the {#link #BroadleafAdminAbstractEntityController}. This delegates every call to super and does not provide any custom-tailored functionality. It is
responsible for rendering the admin for every entity that is not
explicitly customized by its own controller
#RequestMapping("/{sectionKey:.+}") uses the generic path variable sectionKey, making the controller handle any requests that are not explicitly mapped. For example,
/product
/product/add
/category
/category/add
/store
/store/add
may all be hitting this controller if these URLs have not been explicitly mapped to their own controllers.
To handle a specific URL yourself, you could do:
#Controller
#RequestMapping("/product")
public class ProductAdminController {
#RequestMapping("/add")
public String viewAddEntityForm(...) { ... }
}
Now, the URL /product/add will be routed to this custom controller while all others will continue to get routed to the generic controller.
Below code in my controller class.
#Controller
#RequestMapping("/library/*")
public class HelloController {
#Autowired
#Qualifier("booksValidator")
private Validator booksValidator;
#Autowired
#Qualifier("loginValidator")
private Validator loginValidator;
#InitBinder("login")
private void initUserBinder(WebDataBinder loginBinder) {
loginBinder.setValidator(loginValidator);
}
#InitBinder("book")
private void initBooksBinder(WebDataBinder booksBinder) {
booksBinder.setValidator(booksValidator);
}
#RequestMapping(value="welcome", method = RequestMethod.POST)
public String printWelcome(#Validated #ModelAttribute("user") User user, BindingResult login, ModelMap model) {
}
#RequestMapping(value="add", method = RequestMethod.POST)
public String addBooks(#Validated #ModelAttribute("books") Books books, BindingResult book, ModelMap model) {enter code here
}
}
#InitBinder("login") belongs to--> BindingResult login
#InitBinder("book") belongs to--> BindingResult book
How I can do?
Please suggest me...
:(
A Spring controller can have multiple #InitBinder methods. But you are not using correctly the value of the annotation. According to InitBinder javadoc about the value parameter, Specifying model attribute names or request parameter names here restricts the init-binder method to those specific attributes/parameters
So in your example, you should use ModelAttribute names and not BindingResult parameter names, that is #InitBinder("user") and #InitBinder("books") instead of (resp.) #InitBinder("login") and #InitBinder("book").
i would suggest you split this into two separate controllers. One that deals with your users/login and the other to deal with books. So, something like LoginController that has the init binder for login, and BooksController that has the book validator for validating books.
In Spring 4 MVC
In my Controller Class
#Controller
public class TesterController{
#RequestMapping(value = "/test", method = RequestMethod.GET)
public ModelAndView show(){
ModelAndView mav = new ModelAndView("Test");
mav.addObject("Test" , "TestObject");
return mav;
}
}
Can some one explain how is the use of the ModelAndView class in this controller.
What is use of addObject Method
and What is use of having constructor.
Thanks in Advance
Pavan
You can just look at the source as spring is open source.
The model is just a map. So the addObject, is just adding the string "TestObject", with a key of "Test".
A model and view is simply a string of the viewname, along with the associated map/model.
The view resolver will then find the appropriate view file based on viewname, and the map values can be resolved in the view using the key.
I am having trouble getting #InitBinder to work with Backbone.js
#InitBinder
public final void initBinder(final WebDataBinder binder) {
// Customer property editors
binder.registerCustomEditor(MyObjectChild.class, new MyObjectChildEditor());
}
I have a controller like this that accepts the object
#RequestMapping(
produces = MediaType.APPLICATION_JSON_VALUE,
consumes = MediaType.APPLICATION_JSON_VALUE,
method = RequestMethod.POST)
#ResponseBody
#ResponseStatus(value = HttpStatus.CREATED)
public final String create(#RequestBody final MyObject myobject) {
return "worked";
}
MyObject has a property of type MyObjectChild. I would like to pass the ID values of this object from the frontend to the controller because it does not make sense for the user to have the ability to modify it (they will select it from the drop down list).
I have read that #RequestBody does not work with #InitBinder so I tried #ModelAttribute instead, but I don't know what the #ModelAttribute name would be because it is created on the frontend in javascript using Backbone.js.
How do I get Backbone.js to work with Spring #InitBinder?
Currently I am using request.setAttribute() and request.getAttribute() as a means to pass an object from a handler interceptor to a controller method. I don't view this as an ideal technique, because it requires that I take HttpServletRequest as an argument to my controller methods. Spring does a good job hiding the request object from controllers, so I would not need it except for this purpose.
I tried using the #RequestParam annotation with the name I set in setAttribute(), but of course that did not work because request attributes are not request params. To my knowledge, there is no #RequestAttribute annotation to use for attributes.
My question is, is there some better way to hand off objects from interceptors to controller methods without resorting to setting them as attributes on the request object?
Use the interceptor prehandle method and session like this:
Interceptor:
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HttpSession session = request.getSession();
String attribute = "attribute";
session.setAttribute("attributeToPass", attribute);
return true;
}
Controller:
#RequestMapping(method = RequestMethod.GET)
public String get(HttpServletRequest request) {
String attribute = (String)request.getSession().getAttribute("attribteToPass");
return attribute;
}
Just to save time for those visiting this page: since Spring 4.3 #RequestAttribute annotation is a part of Spring MVC, so there is no need to create your own #RequestAttribute annotation.
An example using #RequestAttribute:
Interceptor
#Component
public class ExampleRequestInterceptor
implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// Logic to verify handlers, you custom logic, etc.
// Just for illustration, I'm adding a `List<String>` here, but
// the variable type doesn't matter.
List<String> yourAttribute = // Define your attribute variable
request.setAttribute("yourAttribute", yourAttribute);
return true;
}
}
Controller
public ResponseEntity<?> myControllerMethod(#RequestParam Map<String, String> requestParams, #RequestAttribute List<String> yourAttribute) {
// `yourAttribute` will be defined here.
}