I am building a web application on Spring.
I am confused whether I should use mvc:annotation-driven or context:annotation-config in configuration to scan annotations to handle HTTP requests?
No, despite the confusingly similar keywords, annotation-config does not handle HTTP requests. For handling HTTP requests you only need mvc:annotation-driven.
context:annotation-config causes Java Configuration classes with #Configuration annotation to be loaded. See documentation
mvc:annotation-driven causes Spring to wire up any #RequestMapping, #Controller annotations etc. See documentation
You need to use mvc:annotation-driven.
The first link will explain what mvc:annotation-driven does and the second link what context:annotation-config does
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config-enable
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-annotation-config
Related
I'm very new to Spring MVC and I have one question for you.
I know that tag <mvc:annotation-driven /> handles the annotation such as #Controller, #RequestMapping in a servlet configuration, but I'm using portlets and I am very curious how this annotation works here?
Thx!
It works the same.
If you go with java configuration you'll use:
...
#Configuration
#EnableWebMvc <- (equivalent to <mvc:annotation-driven />)
#ComponentScan(basePackageClasses = { MyConfiguration.class })
...
Or if you go with xml configuration you'll use:
...
<mvc:annotation-driven />
<context:component-scan base-package="package.*" />
...
mvc:annotation-driven is used for enabling the Spring MVC components with its default configurations.
If you dont include mvc:annotation-driven also your MVC application would work if you have used the context:component-scan for creating the beans or defined the beans in your XML file
. But, mvc:annotation-driven does some extra job on configuring the special beans that would not have been configured if you are not using this element in your XML file.
This tag would registers the HandlerMapping and HandlerAdapter required to dispatch requests to your #Controllers. In addition, it also applies some defaults based on what is present in your classpath. Such defaults are:
Using the Spring 3 Type ConversionService as a simpler and more
robust alternative to JavaBeans PropertyEditors
Support for formatting Number fields with #NumberFormat
Support for formatting Date, Calendar, and Joda Time fields with
#DateTimeFormat, if Joda Time is on the classpath
Support for validating #Controller inputs with #Valid, if a JSR-303
Provider is on the classpath
Support for reading and writing XML, if JAXB is on the classpath
Support for reading and writing JSON, if Jackson is on the classpath
context:component-scan element in the spring configuration file would eliminate the need for declaring all the beans in the XML files. Look at the below declaration in your spring configuration file:
<context:component-scan base-package="org.controller"/>
The above declaration in the spring application configuration file would scan the classes inside the specified package and create the beans instance. Note that it could create beans only if that class is annotated with correct annotations. The following are the annotations scanned by this element:
#Component
#Repository
#Service
#Controller
Following the online docs for adding jersey to Sring boot, it appears I just need to include the following package
spring-boot-starter-jersey
Actually, it states that Spring Boot provides automatic configuration by including this package.
Where can I find out what exactly is happening?
If I don't add this package then what is NOT configured?
I tried searching for the package in google but got no specific explanation only saying that it automatically configures, but configures what?
I would like to know a little more of what is happening behind the scenes.
All of the auto-configuration code for all that Spring Boot supports is in the spring-boot-autoconfigure module. If you look through the packages, you will see a jersey package.
The "starter" modules generally do not have any code (of course unless it is a third-party module). How it works is that the code in the auto-configuration has some annotations that are #ConditionalOnXxx, where the condition be anything from a class being on the classpath. If this class is not available, then the auto-configuration will not take place. That's pretty much all adding the jersey starter module does: it adds the jersey dependencies so that the auto-configurer will applied.
Now what exactly is being auto-configured specifically for Jersey? Check out the source for the JerseyAutoConfiguration. Basically what you are going to see is your ResourceConfig being injected into the configurer. From that ResourceConfig, it creates Jersey's ServletContainer (which is the main entry point for Jersey.
Then, depending on our properties configuration, either a FilterRegistrationBean or a ServletRegistrationBean is created as a Spring bean, wrapping Jersey's ServletContainer. Jersey can be created as a Servlet or a Servlet Filter. Whichever one we configure we be used.
And that's it for the Jersey configuration. Spring Boot will get a servlet container (e.g. Tomcat, Jetty) from some other auto-configuration, and take the Filter/ServletRegistrationBean and add the Servlet/Filter to that servlet container.
Also, not really that important, but the auto-configuration also give us some Jackson configuration helpers. For example, instead of configuring our own ContextResolver, we can just configure an ObjectMapper Spring bean.
That's really all you get. It's nothing so spectacular that you couldn't just do it yourself without depending on the auto-configuration.
I would recommend learning a little more about how Spring Boot works to provide the automatic configuration in general.
A good reference is the spring boot reference guide. http://docs.spring.io/spring-boot/docs/1.5.3.RELEASE/reference/htmlsingle/#common-application-properties
You can look at the common application properties in appendix A to see what all spring allows you to configure out of the box.
The Reference guide also gives a high level of what "spring-boot-starter-jersey" if you search for it on the page.
They also have a few samples that you can go through and debug to follow along if that is a way for you to learn.
Hope that gives you a starting point for learning!
I'm a newbie with Spring MVC but now i've been moved to a new project which uses Spring Integration to turn in channel some service. Example in the context.xml
<int:channel id="example-channel" />
<int:service-activator input-channel="example-channel" ref="exampleServiceFacade" />
For every servicefacade i have to bind the service to a channel.
I was wandering, what if I could map the classes to be turned into channels as i could map the beans with component-scan?
<context:component-scan base-package="com.package" />
so i ended up with this tutorial which speaks about some annotation:
#IntegrationComponentScan
But i cannot understand how it's related to the xml tag service activator and channel.. So i'm quite confused. Does anyone with more experience have an idea if what i'm trying to do can be done?
I just want to scan con the classes which defines channels in integration without having to declare every class.
Thanks.
Your question is a bit unclear. Any Spring Integration custom XML tag is parsed by infrastructure and registered as beans in the application context. Like you'd do that via raw <bean>.
#ComponentScan, #Configuration, #Bean and so on are marker annotations to say application context which classes treat as beans.
So, using both techniques for application context configuration you don't lose anything and can continue to mark you class with #Service and use its bean name from <service-activator ref="">.
From other side now you can fully build Spring Integration without any XML! Please, read the mentioned doc in its entirety.
I've been researching what additional capabilities we have when using the mvc:annotation-driven tag and I'm having a difficult time digesting the results, especially in regards to the #Controller annotation. I know this is very similar to this question but please hear me out.
According to the Spring docs
The basic purpose of the #Controller annotation is to act as a stereotype for the annotated class, indicating its role. The dispatcher will scan such annotated classes for mapped methods, detecting #RequestMapping annotations (see the next section).
The documentation then goes on to show that the context:component-scan tag provides this support. So that's all well and good, but then I was looking at what mvc:annotation-driven gives us, and the aforementioned stackoverflow question provides the following answer
mvc:annotation-driven declares explicit support for annotation-driven MVC controllers (i.e. #RequestMapping, #Controller, although support for those is the default behaviour), as well as adding support for declrative validation via #Valid and message body marshalling with #RequestBody/ResponseBody.
This seems kind of redundant to me. Maybe I don't get what this explicit support is. Again, referring back to the official Spring documentation we get the following
[mvc:annotation-driven] registers the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter beans that are required for Spring MVC to dispatch requests to #Controllers.
That sounds pretty similar to the last example I provided from the docs. If anyone can provide some examples as to what we can do with the #Controller annotation using only the context:component-scan tag, what some of the limitations are, then the additional functionality of what we get when adding the mvc:annotation-driven tag, I think that would be very helpful. Thanks in advance for any support on this.
Both elements serve an entirely different purpose.
<context:component-scan /> is, as the name implies, for component scanning. It by default scans for all beans with the #Component annotation (or "sub"annotations like #Controller, #Service etc.). It will only register instances of those classes in the application context as beans. That is all.
<mvc:annotation-driven /> is for bootstrapping Spring MVC and it registers, amongst others, a RequestMappingHandlerMapping and RequestMappingHandlerAdapter. The first links requests to a certain method (the #RequestMapping annotation on methods in a #Controller annotated class). The last knows how to execute methods annotated with #RequestMaping.
Now <mvc:annotation-driven /> does nothing for scanning or detecting #Controllers if there are none in the application context then no request mappings are made. Now you have several ways of registering those beans in the application context and one of them is the aforementioned <context:component-scan />.
Basically a #Controller without <mvc:annotation-driven /> is, well, pretty useless as it does nothing but take up memory. It will not be bound to incoming requests, it just hangs around in the application context. It is just another bean like all other beans and nothing special is being done to it. (Recent, but deprecated, versions of Spring register the DefaultAnnotationHandlerMapping which processes the #Controller, this is however deprecated).
The context:component-scan element lists a package that Spring should scan for #Controller annotations (in the base-package attribute).
the mvc:annotation-driven has no such attribute. This is a convenience element that installs a lot of default MVC elements into the application context. These elements are listed in section 16.14.1 of the Spring framework reference. This element does not appear to scan for #Controller annotations.
Contrary to popular belief, there is no dependancy between these elements. An #Controller without mvc:annotation-driven will function without an issue and handle HTTP requests just fine, as long as you have included context:component-scan with an appropriate base-package attribute.
Case 1(annotation-driven)
This is Enabling Spring annotations tag.
All the annotations such as #Controller, #Service, #Autowired etc.. can be used.
This doesn't creates a bean, but find the the annotations, and spring creates corresponding bean for that class if found annotation(such as #Controller, #Service, #Autowired etc..) .
Case 2(component-scan)
Spring will scan the package (and subpackages) of the classes specified in declaration and creates bean for it.
My controller:
#RequestMapping("/createchar")
#PreAuthorize("hasRole('ROLE_USER')")
public String createCharacter(Map<String, Object> map, Principal principal) {
spring-security.xml
<global-method-security pre-post-annotations="enabled"
proxy-target-class="true" />
...
<intercept-url pattern="/game*" access="ROLE_USER" />
<form-login login-page="/account/login" ...
Page is always loaded, even after redeploying the application. I haven't even logged in. Why it doesn't redirect it to login page?
If you need any more info, feel free to ask.
The controller beans typically reside inside the servlet context, so they are not affected neither by the AOP declarations nor by the bean post processors in the root application context.
Difference between applicationContext.xml and spring-servlet.xml in Spring Framework
I believe that proxying the controller classes is not a good idea, see Spring-MVC Problem using #Controller on controller implementing an interface - so I prefer to avoid using AOP on controller classes to avoid surprises - and use it only on service/DAO beans i.e. the beans in the root application context.
In this case you should use intercept-url approach for the web pages.
Being on the internship I faced the same problem. It took me and my teammates 2 days of cranching Spring Security source codes. However, today we were told that the reason of not even seeing any exceptions are "OP mechanisms", which was mentioned earlier.
The reason is the proxy class must be created.
Spring Proxy Mechanisms
So all we needed to do in our particular situation is to add
<aop:config proxy-target-class="true" />
to the app-servlet.xml
If you try to debug your code and look for methods that are invoked by Spring you may solve even similar problems (as the real cause may be different) but it is a great challenge for your patience.
Hope this will help you and others.
I was facing the same issue. My problem solved when i moved the below element from applicationContext.xml to *-servlet.xml (my dispatcher's configuration xml).
<security:global-method-security secured-annotations="enabled"/>
You have to include this element on your dispatcher's xml NOT on your application's xml.
Spring FAQ