Replacing BaseCommandController and SimpleFormController with annotated Controller in Spring 4 - java

Where can I find some examples on replacing/migrating Spring Framework controllers from version 2 to version 4? By that I mean migrate/replace SimpleFormController and BaseCommandController into an annotated controller #Controller. I am new to the Spring Framework.
For example, my old controller uses onBind(HttpServletRequest request, Object command) method. How can I migrate method like onBind and onBindAndvalidate using the new spring libraries?
Thank you

I was recently doing this upgradation task and I found a very helpful guide to do upgradation.
posting here so that it can be used further by other potential developers.
SimpleFormController vs #Controller
In XML-based Spring MVC web application, you create a form controller by extending the SimpleFormController class.
In annotation-based, you can use #Controller instead
formBackingObject() vs RequestMethod.GET
In SimpleFormController, you can initialize the command object for binding in the formBackingObject() method. In annotation-based, you can do the same by annotated the method name with #RequestMapping(method = RequestMethod.GET).
onSubmit() vs RequestMethod.POST
In SimpleFormController, the form submission is handle by the onSubmit() method. In annotation-based, you can do the same by annotated the method name with #RequestMapping(method = RequestMethod.POST).
referenceData() vs #ModelAttribute
In SimpleFormController, usually you put the reference data in model via referenceData() method, so that the form view can access it. In annotation-based, you can do the same by annotated the method name with #ModelAttribute.
initBinder() vs #InitBinder
In SimpleFormController, you define the binding or register the custom property editor via initBinder() method. In annotation-based, you can do the same by annotated the method name with #InitBinder.
From Validation
In SimpleFormController, you have to register and map the validator class to the controller class via XML bean configuration file, and the validation checking and work flows will be executed automatically.
In annotation-based, you have to explicitly execute the validator and define the validation flow in the #Controller class manually.
You can see the example implementation screenshots at Click Here

Related

#Controller annotation and Controller Classes in Spring MVC

When I am using Spring 3.x
While using annotations its difficult for me to know Which type of Controller class we are going to fetch using this #Controller
With reference to
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/mvc/Controller.html
These are implementing Controller class
AbstractController
AbstractUrlViewController
MultiActionController
ParameterizableViewController
ServletForwardingController
ServletWrappingController
UrlFilenameViewController
AbstractWizardFormController
SimpleFormController
However when we are using #Controller annotation in our Spring MVC
program how to know that Our #Controller annotation is implementing
any of these controllers, Kindly anyone explain me
I think you are missing the point here. In the old times to register a controller, your class must have implemented controller interface and choose request mapping type. Sometimes you had to implement lots of code to achieve single request mapping.
Nowadays, when we have annotations, the model has changed. We can handle multiple request types per controller class. Because in single #Controller annotated class we can handle many request mappings.
Controller annotation is a specialized #Component, that tells Spring that inside it will find #RequestMapping handlers. Those handlers can be used either for returning Json, HTML or for uploading files.
Now logic connected with same module can be placed under single controller class, you are more flexible in what you want to achieve. Secondly #Controller enables us to reduce code anount significantly.
You aren't using any of those classes. You confuse the Controller interface with the annotation.
The annotation is just a marker that states that your bean is a Spring Controller and can send an receive HTTP requests.
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/stereotype/Controller.html
The Controller interface was introduced when there were no annotations in the Java language.
Which type of Controller class we are going to fetch using this
#Controller ?
The #Controller annotation is to tell the web container that this is the controller class for requests with urls specified with #RequestMapping(URI). you are going to fetch no class if you are annotating your class with #Controller , you just need to provide a request handler method within the class and annotate it with #RequestMapping , though the controller class can also be annotated with #RequestMapping and in that case , only method inside the class will work as request handler method.
how to know that Our #Controller annotation is implementing any of
these controllers ?
The names of the classes you have mentioned are implementing Controller interface , not that #Controller annotation is implementing anything .Those controller classes are for specific purposes ,as their names suggest .

isHandler Method of RequestMappingHandlerMapping retunrs true for both RequestMapping and Controller annotation

I am looking into Dispatcher Servlet code. Here i found that dispatcher servlet uses HandlerMapping to select the handler for the request. Also, RequestMappingHandlerMapping is used as an implementation for HandlerMapping. Now, isHandlerMethod of RequestMappingHandlerMapping returns true if the bean under consideration has either #Controller or #RequestMapping annotation. If certain bean has only #RequestMapping annotation applied at class level would it still be considered as Handler?.
Any Help would be greatly appreciated.
The #RequestMapping and #Controller annotation have different meanings. The request mapping is used to decide, which class / method is used to handle a request to a speciffic URL. If you look at the source of the #Controller adnotation you will find that it is annotated with #Component itself. This way it can be used to set up the component scan that will register an instance of the class as a bean.
I'm quessing that, since those annotations are usually used together, it's done so that a minute performance gain can be achieved. Also, you could declare your controllers differently, either by java config or xml.
Edit:
I have done a quick prototype with a controller bean declared in java config, without the #Controller annotation. The answer is yes, the method will be used to handle a request, even if the class is not annotated.

Bean Validation with groups using Spring in Service Layer

I am developing a service(not a web application) using Spring-3.1.0.GA. I want to use hibernate-validator along with Spring to validate my service inputs.
I have enabled the bean validation support with:
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
I have annotated my service interface with #Validated and method parameters with #NotNull, #Size, #Valid etc and it is working fine.
But I have to validate my parameter, say Customer, based on validation group(s).
If I annotate method parameter with #Validated or #Validated(Group1.class) Spring is not performing any validation.
If I annotate with #Valid then validations are happening but with Default validation group(as expected).
I can't annotate #Validate(Group1.class) at interface level because various methods operate on various groups.
How can I perform service layer validations using Spring and hibernate-validator with groups support?
I have gone through Spring Source code and why the validation groups on method params are not being picked...As per the code it is picking the validation groups configuration only from #Validated on interface level, not on method level.
But I haven't gone through how it is working in SpringMVC context, I haven't checked yet.
Also in this process I came to know If you configure MethodValidationPostProcessor in child application context it is not picked up by Spring. I mean if you are using SpringMVC, MethodValidationPostProcessor will be registered only if you configure it in [servlet-name]-servlet.xml. If you configure in any child context configuration files that are picked by ContextLoaderListener Spring won't register MethodValidationPostProcessor. Also I am not sure it is only for MethodValidationPostProcessor or for any BeanPostProcessors also.
I get the following code working, I need to attach the #Validated at the method header and #Valid in the method parameters.
#Validated(Default.class)
public UserDto updateUser(#Valid UserDto userDto) {
In Spring 3.1.0+ you can use groups directly in #Valid annotation. E.g.:
#Valid(groups={Default.class, Group1.class})

Migration to Spring Annotated Controllers and traditional onSubmit method

I am trying to migrate from Spring 2.0 to Spring 3.0.
Previously I defined a controller MyController inheriting from SimpleFormController and have some logic written in the onSubmit method. All my controllers having the handler methods are inherited from MyController. Thus, the logic written in onSubmit of MyController used to get executed for all requests.
Now as I migrate to annotated controller wherein my controller is a simple pojo, how do I ensure the execution of onSubmit everytime? One way is to call onSubmit from all handler methods of all the controllers. This is cumbersome.
Can anyone suggest any feasible solution. As annotating formBackingObject with #ModelAttribute ensures the invocation for all requests, isn't there an analogy for onSubmit method?
If you want to perform the same action before each invokation of any annotated controller, you could use an interceptor. You can write your own interceptor by just implementing the preHandle method.
You will then need to register this interceptor in the DefaultAnnotationHandlerMapping or whatever Handler mapping you use to dispatch to your controllers.
Registering interceptors is explained in this article:
http://www.scottmurphy.info/spring_framework_annotation_based_controller_interceptors
Annotate the method you wish to invoke. The method signature is very flexible. Take a look at the docs for #RequestMapping
#RequestMapping(value={"/foo"}, method=RequestMethod.POST)
public String myMethod(many options for parameters) {...
Ok so if i understand correctly you want inheritance to continue to play a role in the stack when a request is handled by a controller. You can extend any class in an #RequestMapping annotated POJO but you will have to define an #override method to annotate it. All you do basically is call super with the arguments in the overriding method. If you extend an annotated class and both are declared as Controller then you will get an exception since the route will be defined more then once.
it would look like this
public class Pojo{
public String someBaseMethod(){
return "";
}
}
#Controller
public class ChildController extends Pojo {
#Override
#RequestMapping("/do_it")
public String someBaseMethod() {
return super.someBaseMethod();
}
}
A good case could be made to use composition over inheritance. I even suggest that you use the filtering mechanism instead if it can apply to perform common operations. AOP could also be a good tool.

Spring #Controller and custom MethodNameResolver

I have several controllers in a spring mvc application. They are regular beans that inherit from MultiActionController. They also have a custom MethodNameResolver that inspects a certain request parameter.
Now I am trying to use a new controller - a pojo with #Controller annotation. I am using #RequestMapping to resolve methods.
I am not sure if I understand this correctly, but as explained here in the spring reference, it is possible to use #RequestMapping with various filters (e.g. GET vs POST) without specifying a path, and then if a url applies to several methods then Spring falls back to InternalPathMethodNameResolver to decide which method to invoke.
How can I tell Spring to fall back to my custom MethodNameResolver? Is it enough to inject the resolver to my pojo controller?
(my controller doesn't inherit from any Spring specific class)
I guess you need to declare AnnotationMethodHandlerAdapter bean and set its methodNameResolver property.

Categories

Resources