Spring MVC isFormSubmission() equivalent for annotations? - java

With Spring MVC, it's easy to express a concept like "A user is submitting the form if they use POST or if they include the 'isSubmit' parameter." You'd just extend SimpleFormController and override the isFormSubmission method.
However, Spring MVC now uses these neat annotations like #RequestMapping to handle requests. #RequestMapping has an obvious filter for whether somebody used a GET or a POST, but I don't see any inherent support for all of the useful logic SimpleFormController provided. Is it still available to me with annotations?

So, after a bit of investigation, there are in fact a couple of ways to handle this situation.
The first way is to go ahead and use a SimpleFormController with with #RequestMapping annotation at the class level. A lesser-known but pretty cool property of #RequestMapping is that it knows perfectly well how to deal with the classes that implement Spring's Controller interface. The only downside here is that I'm still using the old MVC interfaces and classes, and they're going to be deprecated in Spring 3.0.
The second way was pointed out by kgiannakakis above. Simply create a #RequestMapping method for every way that the submit can be called, and have them all just call a single submit method, either in a constructor-chaining style or with some private method. Simple and easy to understand. Thanks, kgiannakakis!

Copying from here:
Path mappings can be narrowed through parameter conditions: a sequence of
"myParam=myValue" style expressions, with a request only mapped if each such
parameter is found to have the given value. "myParam" style expressions are
also supported, with such parameters having to be present in the request
(allowed to have any value). Finally, "!myParam" style expressions indicate
that the specified parameter is not supposed to be present in the request.
You can only use the RequestMapping options to define the desired functionality. The Annotations Controller doesn't implement any interface to work with.

Here is one example of using Path mappings:
#RequestMapping(params = "formAction=APPROVE", method = RequestMethod.POST)
public String myMethod ()....
This method will only be called then for POSTs where there is a field named "formAction" with a value of "APPROVE".

The other answers listed work fine for a method annotated with #RequestMapping.
However, if you want to achieve the same thing on a method annotated with #InitBinder, you can simply do this:
#InitBinder
public void initBinder(HttpServletRequest request) {
if ("POST".equals(request.getMethod()){
//Do something
}
}

Related

#RequestMapping with body implementation in superclass

I have some entities and a separate controller for each of them. In these controllers, there is one method that is always the same and it is the edit form route. I have a service that builds a form for any given entity so basically this method has three lines: build the form, assign to the model, return the view name. The view is also the same as the only difference on that page is the form. So what is different is the path and the path variable's type (Entity type).
I would like to move this one method to a common superclass. I could solve the type of the path variable with some generic types. The problem is the path. I know that the value of #RequestMapping has to be a constant so is there any other way around it?
I guess I could technically create a method that does what I need then in every inherited class I can create another method that calls this one or even overrides the original method. I was just curious if there was a better way.
I believe what you're describing: 'creating a method that does what you need in the super class' then assigning the #RequestMapping in the concrete implementation to create the routing, is likely the common best practice for handling this in Spring.
If you want to be fancy with the Spring route mapping you can manipulate them at start up using the RequestMappingHandler to manually assign route mappings to a controller method, but note that #RequestMapping on a class will create a route for the method even if it's an abstract class (not sure about on abstract methods, but I assume not). However you can use #RequestMapping on interfaces abstractly. You can find an example of how to do that here
Using the above handler you could create your own type of inheritance chain using reflections and a custom annotation on the base class that you manually assign to the route base in the request mapping handler.

Is there a way to use Google's Custom Methods with Jersey Resources?

I was looking for a way to make my JAX-RS APIs more readable and came across with Google's Custom Methods approach:
https://cloud.google.com/apis/design/custom_methods
I was looking for this because some of my entities perform more actions than I could express with traditional HTTP verbs. Google pattern is to use a colon (:) at the end of the URI, separating the entity/collection from the desired action.
I tried to apply this pattern to a simple Jersey resource, just to test how it could be done. I've got a resource class StudentDetailsResource annotated with #Path("students/{studentId}") and a few methods also annotated with #Path.
If my method has another entity before the custom method, then all is ok. Let's say the enrol method is annotated with
#Path("subjects/{subjectId}:enroll").
The problem rises when the action is right after the Resource Class URI, because #Path uses a URI Template that prefixWithSlash all sub-resources. So if I have a dropout method, the annotation would look like #Path(":dropout"), but the URI template would become /students/{studentId}/:dropout, an this /: would break in the matching phase.
I have read about Jersey Providers and ResourceDelegates, but I couldn't find a way to replace the URI Template default action of prefixWithSlash.
The question is: how can I apply Google's custom method approach or how can I avoid the default prefixWithSlash behaviour with Jersey?
Note: I know this is a silly example and there are other ways to solve this specific case, but I have more complex cases which can benefit from the custom methods.

How does spring inject arguments into the controller method

public ModelAndView loginPage(HttpServletRequest request, Locale locale) {}
As you know, Spring injects HttpServletRequest and Locale into the method. I want to know
how is it done behind the curtains ? My guess is, there is a data converter system working behind
that takes http request headers and body data and fill them into the suitable classes that are given
in arguments by the coder. Am I right ?
When working with Spring MVC there are multiple parts moving to solve the problem of mapping HandlerMapping and execution HandlerAdapter.
Each #Controller is scanned for #RequestMapping annotated methods, the methods are mapped to URLs based on the metadata available in the #RequestMapping annotation, this is done by the RequestMappingHandlerMapping class.
When a request comes in the specific method is matched on the incoming request. This selected method is passed the RequestMappingHandlerAdapter which consults all method arguments. The actual handling of the method argument is left to different HandlerMethodArgumentResolver implementations (you could also implement your own).
The same happens for the return value of your method although that is delegated to a HandlerMethodReturnValueHandler.
Yes, you're right. In short, there is a single entry point into the application (there may be more than one entry point) that routes incoming traffic, passing incoming data to methods as parameters. This is known as the front controller pattern.
Spring's DispatcherServlet is an implementation of the front controller pattern. The Spring reference details the pattern as followed in Spring, and the pattern is listed among the core Java EE patterns.

Creating Custom Annotation Using Spring that supports Flexible Method Signature

In Spring MVC, Inside a Controller class, the method annotated with #RequestMapping annotation are allowed to have Flexible Method Signature.
If I want to do something like this with my own custom annotation, Can somebody give me some pointers for the same.
Thanks in Advance.
Spring MVC has a lot of features in that regard so it might be easier to look elsewhere as a starting point. The new messaging abstraction that was introduced in Spring 4 has similar features.
Look at #MessageMapping which allows you to build a flexible signature against a Message instance. You could for instance inject a header of the message
public void foo(#Header("myHeader") int myHeader)
Or you could validate that the payload against a Validator
public void bar(#Payload #Validated Order order)
The core of the infrastructure is located in InvocableHandlerMethod which is going to invoke a java.lang.reflect.Method you have provided on a given bean instance based on an incoming Message and additional parameters you may provide (see public final Object invoke(Message<?> message, Object... providedArgs)
To create that instance, you need to provide a set of HandlerMethodArgumentResolver. Each HandlerMethodArgumentResolver is responsible to handle a method parameter. In short, that's basically going to provide you a MethodParameter instance (i.e. a reference to a parameter of the method you want to handle, such as the annotated order in the last example) and you're going to tell if you support it or not and when you do, handle that parameter so that the right value is injected. For the header example, the implementation looks for a header with the name on the annotation. Simple!
A set of default resolvers are created for example in SimpAnnotationMethodMessageHandler (look at initArgumentResolvers). That's going to show you the kind of parameters you can inject there by default. By extending that list (or providing custom instances) you can augment what the user can use in the method signature.
In Spring 4.1, we rely on this infrastructure to provide JMS listener annotated endpoints and those endpoints may have a flexible signature as well. It's actually already implemented so you may want to have a look to that for yet another example.

Replacement for <servlet-mapping> in web.xml & Spring MVC

Because my URLs are really complex and each of the parts between the slashes depends on the content of my database, I suppose the is not sufficient for me. I suppose I need to write some URL parser, which goes through the url parts between the slash and calls some kind of handler.
Is there a way how to write such URL parser, which would get string and return an object, representing the current request, that would replace the ? I only managed to find simple tutorials which use only the url-routing defined by web.xml.
Thanks
Spring is extremely flexible, so you can customize URL parsing. Take a look on this tutorial http://static.springsource.org/spring/docs/3.0.0.M3/spring-framework-reference/html/ch16s11.html, pay attention on DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter. It seems you should study how do they work and override some of the functionality.
But before you are starting, think again. Do you really need this and #RequestMapping does not satisfy you? Really, you can use path variable {myvar} into the URL pattern definition. The variables may be of different types including enums. I used this and found very convenient. You can for example create enum MyType ONE, TWO; define abstract method on enum level and override it for each element. Then you can use path variable of type MyType into the request mapping and call this method directly from the method marked with #RequesteMapping annotation.

Categories

Resources