What does <mvc:annotation-driven /> do? - spring-mvc

I use filenames in my REST API (example: GET http://xxx/api/myImage.jpg)
problem is #PathVariable dropped ".jpg".
this problems already asked few times in here and answered. but not worked to me.
so I searched then found at the
https://jira.springsource.org/browse/SPR-6524
"... is simply not supposed to be combined with manual DefaultAnnotationHandlerMapping instances; this is designed as an either-or choice at present, quite similar to and ."
"mvc namespace are make simplifed configurations".
Real question is mvc what does do? and changed?
I found my self these things..
intercepter configuration changed. (mvc namspace required in bean configuation)
useDefaultSuffixPattern is not working.
adds JSON message converter. if jackson library is available
#PathVariable arguments are auto added to model
Any others?
Thanks in advance!

The mvc:annotationDriven tag essentially sets you your Spring context to allow for dispatching requests to Controllers.
The tag will configure two beans DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter.
You can find more information from the spring documents:
http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html

Before I provide certain points let me clear up the answer provided by Roy is not accurate. You don't have to provide mvc:annotation-driven tag to instantiate default beans. This tag can be used Spring 3.0+ to enable new feature introduced from Spring 3.0
(Do not use it if you want backward compatibility, especially if you are using old controller based classes like MultiActionController, SimpleFormController)
Now lets come to what this tag actually does -
Prior to Spring 3.1 default beans used where
DefaultAnnotationHandlerMapping
AnnotationMethodHandlerAdapter
AnnotationMethodHandlerExceptionResolver
These are deprecated in Spring 3.1 and if you use above mentioned tag it will be replaced by -
RequestMappingHandlerMapping
RequestMappingHandlerAdapter
ExceptionHandlerExceptionResolver
DefaultAnnotationHandlerMapping decided which controller to use and the AnnotationMethodHandlerAdapter selected the actual method that handled the request. RequestMappingHandlerMapping does both the tasks. Therefore the request is directly mapped right to the method.
There are other infrastructure beans that are instantiated by these tag (chained in addition to defaults) like - MappedInterceptor, ConfigurableWebBindingInitializer, SessionFlashManager, ContentNegociationManager etc. I am not going to explain these :) as they each are long answers themselves, so google it for more info.
PS : And yes Spring 3.1+ automatically expose #PathVariables to the model. Also you have mvc:interceptors tag. But I think it is not related to <mvc:annotation-driven />. I would highly recommend read - http://spring.io/blog/2009/12/21/mvc-simplifications-in-spring-3-0/

To enable MVC Java config add the annotation #EnableWebMvc to one of your #Configuration classes:
#Configuration
#EnableWebMvc
public class WebConfig {
}
To achieve the same in XML use the
mvc:annotation-driven
element in your DispatcherServlet context (or in your root context if you have no DispatcherServlet context defined):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven/>
</beans>
The above registers a RequestMappingHandlerMapping, a RequestMappingHandlerAdapter, and an ExceptionHandlerExceptionResolver (among others) in support of processing requests with annotated controller methods using annotations such as #RequestMapping, #ExceptionHandler, and others.
For details refer the below link :
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config

mvc:annotation-driven tag do extra work from context:component-scan tag
The tag registers the Handler Mapping and Handler Adapter required to dispatch requests to your #Controllers:
tag helps registering the following components.
DefaultAnnotationHandlerMapping - This is a HandlerMapping implementation which maps the HTTP requests to the handler methods defined using the #RequestMapping annotation.
AnnotationMethodHandlerAdapter - It is responsible for scanning the controllers to identify methods (and parameters) annotated with #MVC annotations. It scans and caches handler methods annotated with #RequestMapping. Also handles the #RequestParam, #ModelAttribute, #SessionAttributes and #InitBinder annotations.
ConfigurableWebBindingInitializer - The initializer for the Web Data Binder. Helps in declaratively configuring the Web Binder with validators, conversion services, property editors, etc.
LocalValidatorFactoryBean - Implements the validator interface and enables JSR303 validation. This is injected into ConfigurableWebBindingInitializer.
FormattingConversionServiceFactoryBean - A conversion factory that returns conversion services for basic objects like date and numbers. This factory is again injected into ConfigurableWebBindingInitializer.
Message Converters
ByteArrayHttpMessageConverter - A HTTP request message converter that reads a HTTP message body and returns a byte stream. It can also read a byte stream and construct a response body. Used for receiving and sending documents like PDF, XLS, etc.
StringHttpMessageConverter - A HTTP request message converter that reads a plain text request body and binds it to a String object. And vice-versa with response.
FormHttpMessageConverter - A HTTP request message converter that reads a form encoded request body and binds it to a form Binding object.
SourceHttpMessageConverter - A HTTP request converter that converts a XML message body to/from Binding Object.
If we do not use mvc:annotation-driven tag then we have to do register these components manually in xml file in order to use them , which results in too much extra work.

Related

Annotation Based Handler Mapping in spring mvc

I want to understand how HandlerMapping work in Annotation based Spring MVC applications. As while working in XML based configuration we have one default and if we want to use other implementation then we have to define it in XML file as well as URL mapping strategies.
To understand HandlerMapping in Annotation based Controller application i came across to
DefaultAnnotationHandlerMapping which used to be default before v3. 1 and now
RequestMappingHandlerMapping is currently used. So I want to understand how to define this HandlerMapping if we are not using XML based configuration and URL mapping strategies. Another thing I came across was HandlerAdapter. So these two things are confusing me.
Please explain step by step when Dispatcher Servlet intercept a request how it find which HandlerMapping to use and how URL mapping strategies work in Annotation based apps.
You can think that HandlerMapping determine a request/URL should be handled by which ways/frameworks (e.g use #Controller to handle ? Use JSP to handle ? etc)
HandlerAdapter drives the actual workflow of handling this request , containing the actual implementation of handling logic.
High Level Logic:
DispatcherServlet intercepts a request
Find out which HandlerMapping can handle this request. Refer to HandlerMapping#getHandler() for the matching logic. It will return a generic object (called a handler object) if the request can be handled.
Find out which HandlerAdapter can handle this handler object (By checking HandlerAdapter#supports()). If a HandlerAdapter can handle , it will handle it (by HandlerAdapter#handle).

Spring Tool Suite ignores #GetMapping #PostMapping

It seems to be, that Spring Tool Suite 3.8.3 ignores the newer MVC mapping annotations #GetMapping, #PostMapping etc. on creating the request mapping view. If a #RestController annotated class uses #RequestMapping only, all handler methods are shown in both Spring Tools => Show RequestMappings and Spring Explorer => Beans => Request Mapping. But if only the #RestController annotated class uses #RequestMapping and all handler methods uses #GetMapping, #PostMapping or #DeleteMapping, then those handler method mapping are not shown.
Boot Dashboard can show these request mapping if app is running. However, there is no support probably to show these in Request Mappings view based on annotations scanning. Feel free to raise this issue via Spring-IDE GitHub page: https://github.com/spring-projects/spring-ide/issues

Spring MVC handle same request parameter in common place for different URIs

I've spent a few days researching this, but haven't found a suitable answer for my situation. I have a Spring 3.1 MVC application. Currently, some vendors log into the application via a web client in which case the user information is stored in the session. I want to expose some services to other vendors via RESTFul web services, but have the vendor pass their vendor id as a part of the URI or via PARAMS. Is there a way to handle the vendor id in a single place that then forwards to the respective controller for request processing? Should the vendor id be a part of the URI or should the vendor id be passed in the request body? I've looked into Interceptors, but how would I do this with multiple URIs or for every controller for the RESTFul webservice? Any suggestion would be greatly appreciated
Having a custom header is the most clean option but parameters also work equally well.
In the interceptors preHandle method you could lookup the vendor by either a header or a parameter and attach it to the request by adding the object to it's attributes.
request.addAttribute("vendor", myVendorInstance);
From that point on the vendor can be retrieved from the request like:
Vendor vendor = (Vendor) request.getAttribute("vendor");
Interceptors can be mapped to any URL you like using a mapping e.g.
<mvc:interceptor>
<mvc:mapping path="/vendors/**" />
<bean class="my.package.VendorLookupInterceptor" />
</mvc:interceptor>
Another way of making the vendor object available to controllers is to inject it. For instance, say that controllers interested in the object should implement this interface.
public interface VendorAware {
public void setVendor(Vendor vendor);
}
Controllers implementing this interface could be handled by the interceptor and get the vendor injected.
if (handler instanceof HandlerMethod) {
Object bean = ((HandlerMethod) handler).getBean();
if (bean instanceof VendorAware) {
Vendor vendor = getVendor();
((VendorAware) bean).setVendor(vendor);
}
}
Obviously the problem with adding the vendor id to the URI is that it affects all your URL's, so cannot easily make the controller generic.
Another way is to have the vendor id passed as a header to the controllers. You could use the X-User header.
Then you can write some kind of handler to check for this header, possibilities:
spring interceptor
servlet filter
spring security
aspectj

How do you create CouchDB Views using Spring Bean Deployment with LightCouch

I am using Spring-MVC LightCouch and CouchDB and I have custom Views that need to be inserted into the DB on deployment. I have found the LightCouch has a method for pulling documents "from desk" as noted on their website:
DesignDocument designDoc = dbClient.design().getFromDesk("example");
Response response = dbClient.design().synchronizeWithDb(designDoc);
This Works good from within JAVA code, however I need to be able to do it in the Spring ApplicationContext.xml I have more than one so I would like to mimick the call of:
dbClient.dessign().synchronizeAllWithDB()
How would I do this in the bean definition of the ApplicationContext I already have this:
<bean id="dbClient" class="org.lightcouch.CouchDbClient" lazy-init="false" destroy- method="shutdown">
<constructor-arg value="couchdb.properties" />
</bean>
It seems you can't do it with Spring xml config, as the init method falls under a different instance; that is returned by the call to design() factory method. Maybe you can try Java code equivalence, i.e. #PostConstruct.
I ended up having to make a bean that synchronized the database on init and created that when the app starts

Accessibility of a servlet class from within an external web.xml file

I have two web applications.But only one among them includes Java servlet class.I want to access that servlet class from within the web.xml file of other application.Is it possible?.If yes,How will be it possible?.
You can't do that in the web.xml. You can however create a new servlet which in turn redirects/forwards the request to the servlet of the other webapplication. Redirecting is easy, just let the URL point to the particular servlet.
response.sendRedirect("/otherwebapp/theservlet");
Forwarding requires a bit more work. This is by default not possible due to security restrictions. First you need to configure the servletcontainer to enable cross context access between the webapplications in question. It's unclear which one you're using, so here's just a Tomcat targeted example so that you understand in what direction you should look for your own servletcontainer: for the both webapps, you need to set the crossContext attribute of the <Context> element to true:
<Context crossContext="true">
This way you can obtain the other context by ServletContext#getContext() inside a servlet:
ServletContext othercontext = getServletContext().getContext("/otherwebapp");
Finally you can forward the request through it as follows:
othercontext.getRequestDispatcher("/theservlet").forward(request, response);

Resources