spring MVC extended controllers don't resolve - spring-mvc

I have the following:
#Controller
#RequestMapping("/admin")
public class AdminController extends BaseHtmlController{
#Autowired
protected DeviceCustomerMap deviceCustomerMap;
#Autowired
protected CustomerDao customerDao;
String layout = "template/admin";
#RequestMapping(value="/login", method = RequestMethod.GET)
public String login(ModelMap model) {
model.addAttribute("meta", meta);
String view = "login";
return view;
}
}
public class AdminCustomerController extends AdminController{
#RequestMapping(value="/customer/mapping", method = RequestMethod.GET)
public String customerMapping(ModelMap model, #RequestParam(required=false) boolean refresh) throws Exception {
if (refresh){
deviceCustomerMap.initCustomerUrlMap();
}
model.addAttribute("meta", meta);
model.addAttribute("view", "customer/mapping");
model.addAttribute("customers", deviceCustomerMap.getCustomerMap());
return layout;
}
}
However, the extended controller doesn't resolve the requests, but when they're in the base controller, they're resolved just fine, I've poked around several threads but couldn't find a solution, any idea?

Is the problem that you are able to get a response when executing a request to the /admin/login resource, but not to /admin/customer/mapping resource, unless you move the customerMapping() method to the AdminController class?
The solution is to annotate the AdminCustomerController class with the #Controller annotation. Without a stereotype annotation (and appropriate component scanning), Spring will not recognise the class as a Spring bean.

Related

Combining POST and GET in SpringMvc

For a user registration form (registration.html) I created a view controller through:
#Configuration
#EnableWebMvc
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(final ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/user/registration").setViewName("registration");
}
This works fine, and if I go to /user/registration (i.e. GET), I can see the registration form.
However if I now want to create a controller for POST requests at the same uri through:
#Controller
public class RegistrationController {
#RequestMapping(value = "/user/registration", method = RequestMethod.POST)
#ResponseBody
public GenericResponse registerUserAccount(#Valid final UserDto accountDto, final HttpServletRequest request) {
// some code
}
}
I get an error message at the /user/registration uri saying:
Request method 'GET' not supported
So it seems that my post controller is somehow overriding the GET controller which was working before. Why is that? Is it possible to make the two work together or do I have to write my own GET controller in the same way as my post controller?

Spring MVC - Request Return Value in Browser

I imported the Getting Started - Securing a Web Application in STS and added a controller for navigation, the request gets called and the return value instead of redirecting gets displayed in the browser. Any idea why it does this and how to fix it?
Here is the code:
#RestController
public class BetController {
#RequestMapping("/")
public String username(Model model) {
System.out.println("Test");
model.addAttribute("username", WebSecurityConfig.getUsername());
return "statpage";
}
The page start page is registered in this manner:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("startpage");
registry.addViewController("/login").setViewName("login");
}
All I get in the browser is a blank page with "startpage" on it, looking at the page's source there is no html just "startpage"
Returning ModelAndView instead of a String in the RequestMapping method solved the problem:
#RequestMapping("/")
public ModelAndView username(Model m) {
ModelAndView mav = new ModelAndView();
mav.addObject("username", WebSecurityConfig.getUsername());
mav.setViewName("betting");
return mav;
}
Another solution is changing #RestController to #Controller and making sure all the names match

#ModelAttribute("classname") dynamic paramater binding

spring mvc
#ModelAttribute("classname"),
How to make the argument "classname" a dynamic one ?
Whatever comes from view can get appended there.
Instantiation of the command object is the only place where Spring needs to know a command class. However, you can override it with #ModelAttribute annotated method:
#RequestMapping(method = RequestMethod.POST)
public void show(HttpServletRequest request,
#ModelAttribute("objectToShow") Object objectToShow)
{
...
}
#ModelAttribute("objectToShow")
public Object createCommandObject() {
return getCommandClass().newInstance();
}
By the way, Spring also works fine with the real generics:
public abstract class GenericController<T> {
#RequestMapping("/edit")
public ModelAndView edit(#ModelAttribute("t") T t) { ... }
}
#Controller #RequestMapping("/foo")
public class FooController extends GenericController<Foo> { ... }

Creating a custom controller parameter automatically populated with HttpServletRequest?

Using a strictly annotation-based/Java-only Spring MVC 3.2.2 configuration, I'm trying to create a controller method with a custom class (I'll call it Context) as a parameter. I want to have Context constructed with knowledge of the current HttpServletRequest and then passed along to the controller method. In essence, I want to create my own custom wrapper around the request object before it's sent to the controller. e.g. I want to accomplish this:
#Controller
#RequestMapping(value = "/")
public class MainController {
#RequestMapping(value = "/")
public #ResponseBody
String process(HttpServletRequest request) {
Context context = new Context(request);
...
}
}
automatically like this:
#Controller
#RequestMapping(value = "/")
public class MainController {
#RequestMapping(value = "/")
public #ResponseBody
String process(Context context) {
...
}
}
Is this possible? I looked into implementing a HandlerMethodArgumentResolver as a #Bean in my WebMvcConfigurerAdapter but I don't think that's the correct route to take. I've tried adding #AutoWired to Context (as a #Bean) to no avail as well. I imagine there's WebMvcConfigurerAdapter or possibly in a AbstractAnnotationConfigDispatcherServletInitializer?
HandlerMethodArgumentResolver and WebMvcConfigurerAdapter is certainly a right way to achieve your goal.
In order to register custom argument resolver you need to make your #Configuration extend WebMvcConfigurerAdapter and override its addArgumentResolver() method.

Binding from Headers in Spring MVC

Can Spring MVC bind HTTP headers to Java classes?
I've got three headers, and I'd like to marshall them into a POJO, much like you'd do with a form or a request body.
I can see two ways that you could achieve this with Spring and request or prototype scoped beans.
It is worth first being clear on the different scopes of beans and how Spring creates proxies for different scopes if you are not already.
The first method uses Spring Expression Language to directly reference the current HttpServletRequest instance.
#Component
#Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyClass
{
#Value({#request.getHeader('headerName')})
private String myHeaderValue;
public String getMyHeaderValue()
{
return myHeaderValue;
}
}
An alternative is to simply inject the current HttpServletRequest as a constructor parameter:
#Component
#Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyClass
{
private String myHeaderValue;
#Autowired
public MyClass(HttpServletRequest httpServletRequest)
{
this.myHeaderValue = httpServletRequest.getHeader("headerValue");
}
public String getMyHeaderValue()
{
return this.myHeaderValue;
}
}
You can then inject this bean into your Controller or Service beans as needed:
#Controller
public class MyController
{
#Autowired
private MyClass myClass;
}
Either method should let you achieve what you want, you can pick which best suits your requirements and preferences.

Resources