spring application can't find mapped view - java

In my spring application, I have one generic controller class with serve as base class for several other controllers in my application. These derived controllers have this structure:
#Controller
#RequestMapping(value="usuario")
public class UsuarioController extends controller<Usuario> {
public UsuarioController() {
super(Usuario.class);
}
}
I will have one of this for each entity class from my application. In the generic controller, I have two methods for each action (ie.: insert, update, delete, select). this two methods (and the generic controller) have this form:
public class controller<E> {
#Autowired
private service<E> serv;
private final Class<E> entityClass;
#RequestMapping(value="cadastra")
#PreAuthorize("hasPermission(#user, 'cadastra_'+#this.this.name)")
public ModelAndView cadastra() throws InstantiationException, IllegalAccessException {
return new ModelAndView("privado/"+this.entityClass.getName()+"/cadastra", "command", this.entityClass.newInstance());
}
#RequestMapping(value="cadastra", method=RequestMethod.POST)
#ResponseBody
public String cadastra(#ModelAttribute("object") E object, BindingResult result) {
if(serv.cadastra(object))
return "yes";
else
return "not";
}
}
The problem is that when I run the application, and try access the view mapped by this method, I am getting a 404 error.
Anyone can tell what I am doing wrong here?

The problem is that Spring cannot locate the correct JSP to forward the processing. After reviewing your code it seems that you need to change this.entityClass.getName() with this.getName()

Related

How to Disable Spring's "typeMismatch" Exception? - Spring MVC

Basically I want to be able stop Spring from checking if my fields contain bad data, and instead let me handle all the validation and exceptions manually.
Suppose I have a class:
public class MyClass {
int aNumber;
}
and a Controller:
#Controller
public class MyController {
#Autowired
private MyValidator validator;
public MyClass() {}
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
#RequestMapping(value="/postsomething", method=RequestMethod.POST)
public ModelAndView onPost(#ModelAttribute("myObject") MyClass myObject, BindingResult result) {
validator.validate(myObject, result);
if (result.hasErrors()) {
return "postsomething";
}
return "redirect:success";
}
And finally a Validator:
public class MyValidator implements Validator {
#Override
public void validate(Object target, Errors errors) {
MyClass myObject = (MyClass) target;
if (someCondition) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "aNumber", "error.myclass.anumber.null");
}
}
}
The point is that I only want an error message to be displayed once from MY validator if someCondition is true. But if I leave my port field in my form empty then it also displays Spring's error message for typeMismatch no matter what.
Can I disable the typeMismatch error, or should I go about all of this some other way?
The short answer: declare members of your backing object as String.
The long answer: typeMismatch error occurs during binding and before validation. All user's data represented as String values (because this is what ServletRequest.getParameter() returns) and Spring tries to convert String value to the type of the field in your backing object. In your example, Spring will try to convert value of parameter aNumber to int. When you left field empty, then Spring tried to convert empty string to the int and of course it complains about mismatching types.
(This answer is still incomplete, because there is also different converters that Spring also tries to use, but I believe that you got the picture.)

Implementing dynamic menu for Spring MVC/AOP application

I wish to implement dynamically changeable menu (updating whenever annotated method or controller added) for my Spring MVC application.
What i want is to introduce new annotation (#RequestMenuMapping) which will go to #Controller beans and their methods (just like #RequestMapping works).
Heres is what i want, User class, producing menu like
Users
Index | List | Signup | Login
with following code:
#Controller
#RequestMapping("user")
#RequestMenuMapping("Users")
public class User {
#RequestMapping("")
#RequestMenuMapping("Index")
public String index(/* no model here - just show almost static page (yet with JSP checks for authority)*/) {
return "user/index.tile";
}
#RequestMapping("list")
#RequestMenuMapping("List")
public String list(Model model) {
model.addAttribute("userList",/* get userlist from DAO/Service */);
return "user/list.tile";
}
#RequestMapping("signup")
#RequestMenuMapping("Signup")
public String signup(Model model) {
model.addAttribute("user",/* create new UserModel instance to be populated by user via html form */);
return "user/signup.tile";
}
#RequestMapping("login")
#RequestMenuMapping("Login")
public String login(Model model) {
model.addAttribute("userCreds",/* create new UserCreds instance to be populated via html form with login and pssword*/);
return "user/login.tile";
}
}
I think that Spring AOP may help me to pointcut methods with #RequestMenuMapping annotation and via #AfterReturning add something representing web-site menu to model.
But this raises two questions:
How do i get Model instance in #AfterReturning advice method in case it is missing in adviced method (as in .index())?
How do i get all methods (as in java reflection Method) and classes (as in java reflection Class) annotated with #RequestMenuMapping in order to build complete menu index?
I think a better soultion would be a bean post processor to scan all controller classes for the #RequestMenuMapping and a HandlerInterceptor to add the menu items to every model map.
InterceptorDemo:
#Aspect
#Component
public class InterceptorDemo {
#Pointcut("#annotation(org.springframework.web.bind.annotation.RequestMapping)")
public void requestMapping() {
}
#Pointcut("#annotation(you.package.RequestMenuMapping)")
public void requestMenuMapping() {
}
#AfterReturning("requestMapping() && equestMenuMapping()")
public void checkServer(JoinPoint joinPoint,Object returnObj) throws Throwable {
Object[] args = joinPoint.getArgs();
Model m = (Model)args[0];
// use joinPoint get class or methd...
}
}
If you want to intercept Contoller with you own, you can wirte another pointcut and ProceedingJoinPoint object can get what you want.
Q1:
ModelAndView object create at org.springframework.web.servlet.DispatcherServlet.doDispatch()
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// Do we need view name translation?
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
}
So, you can intercept handle method after returing or override the method.
Q2:As far as i know, there are two ways getting annotation methods.
1.Use AOP:
You can declare a pointcut like this:
#Pointcut("#annotation(you.package.RequestMenuMapping)")
public void requestMenuMappingPountcut() {
}
2.Use reflection.
Class clazz = Class.forName(classStr);
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(RequestMapping.class)
&& method.isAnnotationPresent(RequestMenuMapping.class)) {
// do something
}
}

Spring MVC Bean Validation

I have to implement validations for a web app that uses Spring MVC 3. The problem is that the bean class has methods like getProperty("name") and setProperty("name",valueObj). The validations have to be done on the data that is returned by passing different values to getProperty("name") , for eg: getProperty("age") should be greater than 16 and getProperty("state") should be required.
I would like to know if there is any support for validation this kind of Bean and if not, what can be the work around.
Thanks,
Atif
I don't think so. Bean validation is performed on javabeans, i.e. class fields with getters and setters. Even if you can register a custom validator, and make validation work, binding won't work. You would need to also register a custom binder that populates your object. It becomes rather complicated. So stick to the javabeans convention.
It sounds like you want to a custom validation class which implements org.springframework.validation.Validator.
#Component
public class MyValidator implements Validator {
#Override
public boolean supports(Class<?> clazz) {
return MyBean.class.isAssignableFrom(clazz);
}
#Override
public void validate(Object target, Errors errors) {
MyBean myBean = (MyBean) target;
if (StringUtils.isBlank(myBean.getProperty("state"))) {
errors.rejectValue("state", "blank");
}
}
}
In your controller you would do manual validaton like follows:
#Autowired
private MyValidator myValidator;
#RequestMapping(value = "save", method = RequestMethod.POST)
public String save(#ModelAttribute("myBean") MyBean myBean, BindingResult result) {
myValidator.validate(myBean, result);
if (result.hasErrors()) {
...
}
...
}

Spring MVC customized method parameter binding

I'm looking for a way to customize the default Spring MVC parameter binding. Take this method as an example:
#RequestMapping(value="/index.html")
public ModelAndView doIndex(#RequestParam String param) {
...
This is easy, when I have just a Stringthat I want to extract from the request. However, I want to populate a more complete object, so that my method looks like this:
#RequestMapping(value="/index.html")
public ModelAndView doIndex(Foo bar) {
...
What I'm looking for is some way to declare a binding like this;
#RequestMapping(value="/index.html")
public ModelAndView doIndex(#FooPopulator Foo bar) {
...
And have some other kind of implementor (determined by the #FooPopulator annotation) that does this:
public void doBind(Foo target, ServletRequest originalRequest) {
target.setX(this.computeStuffBasedOn(originalRequest));
target.sety(y);
}
So far I've found out about the #InitBinderbinder annotaion but I'm unsure whether that's really the right choice for this scenarion.
What's the best way?
It is very easy. You can use Converters (that work like one way PropertyEditors but are stateless).
See chapter 5.5 Spring 3 Type Conversion in Spring reference.
If such an converter is registered once, you do not need any additional information, you can simply use
#RequestMapping(value="/index.html")
public ModelAndView doIndex(#RequestParam Foo param) {
For example a simple converter that load an object by its id:
#Component
#CustomConverter //custom qualifyer
public class BUdToUserConverter implements Converter<String, User> {
#Resource
private UserDao userDao;
#Override
public User convert(String source) {
Integer id = Integer.parse(source);
return this.userDao.getByBusinessId(id);
}
}
A "helper" that registers all Beans with #CustomConverter anntoation
public class ApplicationConversionServiceFactoryBean extends FormattingConversionServiceFactoryBean {
#Resource
#CustomConverter
private List<Converter<?, ?>> customConverter;
#Override
protected void installFormatters(final FormatterRegistry registry) {
super.installFormatters(registry);
for (Converter<?, ?> converter : customConverter) {
registry.addConverter(converter);
}
}
}
How to use it
UserController {
...
#RequestMapping(value = "/{id}", method = RequestMethod.GET)
public ModelAndView show(#PathVariable("id") User user) {
return new ModelAndView("users/show", "user", user);
}
}
just a quick thank you and the info, that I've found the "correct" solution to the problem. Spring already provides the WebArgumentResolver for this scenario.
http://sergialmar.wordpress.com/2011/03/29/extending-handler-method-argument-resolution-in-spring-mvc/
http://scottfrederick.blogspot.com/2011/03/customizing-spring-3-mvcannotation.html

Dynamic Command Class in Annotated Controller

As of Spring MVC 3, AbstractCommandController is deprecated so you can no longer specify the command class in setCommandClass(). Instead you hard-code the command class in the parameter list of a request handler. For example,
#RequestMapping(method = RequestMethod.POST)
public void show(HttpServletRequest request, #ModelAttribute("employee") Employee employee)
My problem is that I'm developing a generic page that allows the user to edit a generic bean, so the command class isn't known until the run-time. If the variable beanClass holds the command class, with AbstractCommandController, you would simply do the following,
setCommandClass(beanClass)
Since I can't declare the command object as a method parameter, is there any way to have Spring bind request parameters to a generic bean in the body of the request handler?
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> { ... }

Categories

Resources