I have a Spring MVC 3.2.8 application with Java configuration. I want to disable url decoding as I have this issue with / in the uri. Spring 3.2.8 should fix this.
The problem is, I can't set Url decoding to false in RequestMappingHandlerMapping. I tried to override it with:
#Configuration
public class MobileWebPublicConfig extends WebMvcConfigurationSupport {
#Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
handlerMapping.setUrlDecode(false);
return handlerMapping;
}
}
But when I do this, it breaks my application an auto-wiring stops working.
What am I missing?
UPDATE: container is Tomcat 6, there is no stacktrace related, the app fails when trying to access an autowired element due to it being null. Commenting the configuration above makes it work fine.
The documentation for #EnableWebMvc describes three levels of customization for tailoring your configuration. You can:
Use #EnableWebMvc on its own to import the standard configuration.
Use #EnableWebMvc with configuration classes that extend WebMvcConfigurerAdapter; the subclasses will have their implemented methods called automatically to apply your changes to the standard configuration.
Don't use #EnableWebMvc, but instead make your configuration class extend WebMvcConfigurationSupport to gain full control over your configuration.
However, what the documentation does not make clear is that if you go for option 3 it will not automatically apply the methods implemented in classes that extend WebMvcConfigurerAdapter.
As others have said, we really need to see your full configuration, but if simply extending WebMvcConfigurationSupport and removing #EnableWebMvc breaks other parts of your configuration, my guess is that you are still using WebMvcConfigurerAdapter somewhere else in your config.
If this is the case, you have two options:
Rewrite all your configuration that uses WebMvcConfigurerAdapter and move the code into a single configuration class that extends WebMvcConfigurationSupport.
Extend DelegatingWebMvcConfiguration instead of WebMvcConfigurationSupport. This will give you all the standard configuration behaviour that you normally get when using #EnableWebMvc but still allow you to override methods as required. Note that in any method you override, you'll also need to call the equivalent method in super() if you want to keep the default behaviour too.
EDIT: Also make sure that you don't have #EnableWebMvc annotation somewhere since this annotation will import the original WebMvcConfigurationSupport and not the extended version.
WebMvcConfigurationSupport javadoc says
It is typically imported by adding #EnableWebMvc to an application #Configuration class. An alternative more advanced option is to extend directly from this
class and override methods as necessary remembering to add
#Configuration to the subclass and #Bean to overridden #Bean methods.
Related
I have the following autoconfigure class.
#Configuration
#ConditionalOnWebApplication
#EnableConfigurationProperties({LoggerProviderProperties.class})
#Import({LoggerController.class, LogService.class, LogConfig.class})
public class ProviderAutoConfiguration {
}
I need to import all the components, services, configurations using #import annotation, otherwise for example, when I remove LogService.class (LogController autowires LogService) from #Import parameters, it throws the following error
Consider defining a bean of type 'com.log.LogService' in your configuration.
Do I really have to include all of them manuelly as shown above, or is there any other way to automatically detect classes annotated Service, Component or Configuration?
!This is starter library, not a executable app!
The problem with your "library" is that it already needs a lot of moving parts, like Spring Data JPA, properly setup JPA. If that isn't available it will fail, or if you add #EnableJpaRepositories and/or things like #ComponentScan and #EntityScan it will (quite severely) interfere with the (auto)configuration of Spring Boot or the clients. Which is what you want to prevent.
Instead of all those annotations what you need to do is
Conditionally enable #EnableJpaRepositories or just include the dependency and let the auto-configuration kick in (I suggest the latter)
Don't add #ComponentScan, #EntityScan etc. instead use #AutoConfigurationPackage which is designed for starters.
#Configuration
#ConditionalOnWebApplication
#EnableConfigurationProperties({LoggerProviderProperties.class})
#AutoConfigurationPackage
public class ProviderAutoConfiguration {
}
NOTE: This assumes that the ProviderAutoConfiguration is in the same or a higher package then your other classes. If not specify the basePackages in the #AutoConfigurationPackage.
You can use #ComponentScan to specify the packages you want to scan to find configurations and/or components to load.
Assuming you are using Spring Boot, at least so it seems according to your tags, you should take a look at #SpringBootApplication.
#SpringBootApplication encapsulates #Configuration, #EnableAutoConfiguration, and #ComponentScan annotations with their default attributes. The default value for #ComponentScan means that all the sub packages on the package the #ComponentScan is used are scanned. That is why it is usually a good practice to include the main class in the base package of the project.
If your components, services, configurations are under com.log as direct class or in sub-package, you can use #ComponentScan(basePackages="com.log.*")
#Configuration
#ConditionalOnWebApplication
#EnableConfigurationProperties({LoggerProviderProperties.class})
#ComponentScan(basePackages="com.log.*")
public class ProviderAutoConfiguration {
}
I am trying to extend GlobalMethodSecurityConfiguration with the #EnableGlobalMethodSecurity annotation. I have a separate configuration class that extends WebSecurityConfigurerAdapter with the #EnableWebSecurity annotation.
If I place the #EnableGlobalMethodSecurity on my WebSecurityConfigurerAdapter and not on my GlobalMethodSecurityConfiguration class I am able to see in CglibAopProxy that the method is being intercepted and then invoked. If I remove #EnableGlobalMethodSecurity from WebSecurityConfigurerAdapter and place it on GlobalMethodSecurityConfiguration I no longer see any method interception.
Are the two configurations conflicting? Does anyone have any idea why my methods are no longer properly being invoked after configuring GlobalMethodSecurityConfiguration. I hope to implement method security by extending GlobalMethodSecurityConfiguration so I can provide my own handler and expression root.
I can provide code snippets if needed.
Thanks,
Civerooni
This was solved by the answer in the question Spring Boot: Configure custom MethodSecurityExpressionOperations?. I am not 100% sure why Autowiring my own services, registering them as beans was preventing the method intercept for happening. I suspect it was because it was using different application contexts.
I'm trying to understand the transition from using xml annotation to java based annotation in Spring. I have these definitions
<context:annotation-config>: Scanning and activating annotations for already registered beans in spring config xml.
<context:component-scan>: Bean registration + <context:annotation-config>
is #Configuration and is #ComponentScan.
If lets say I declare all my beans with #Component (disregard first the more specific ones like #Repository, #Service etc) annotation and make sure that the packages are getting scanned by the #ComponentScan annotation, what is a particular use case where I will still annotate my class with both #Configuration together with #ComponentScan?
I ask this question because sometimes I see classes annotated with both #Configuration and #ComponentScan at the same time.
First read the following carefully:
Difference between <context:annotation-config> vs <context:component-scan>
Thus <context:component-scan> does the scan job and the same job than <context:annotation-config> does, it means work around with the DI annotations
Then now consider:
<context:component-scan> equivalent to #ComponentScan
<context:annotation-config> no equivalent for annotation.
what is a particular use case where I will still annotate my class
with both #Configuration together with #ComponentScan?
#Configuration is used to define beans about Infastructure such as Database, JMS etc...
Yes, a class can use both, It could be used for example for MVC Infrastructure #Configuration such as:
#EnableWebMvc
#Configuration
#ComponentScan("com.manuel.jordan.controller", "com.manuel.jordan.rest")
public class WebMvcConfig extends WebMvcConfigurerAdapter {
Thus from that class your are configuring MVC and indicating only to scan the MVC classes created by you for the "web side", such as: #Controller, #RestController.
This really depends on your likings and coding style. Documentation states:
Either basePackageClasses() or basePackages() (or its alias value()) may be specified to define specific packages to scan. If specific packages are not defined, scanning will occur from the package of the class that declares this annotation.
So every time you see just #ComponentScan annotation this means that all sub-packages should be scanned. This is a reasonable approach to take with package per feature layout: when you have a #Configuration class for your feature and all #Components related to the feature in sub-packages.
I encountered this issue when I'm trying to override the RibbonRoutingFilter bean defined in spring zuul. To emphasis, I'm doing an override, not just creating a bean of the same type. So end of the day, I want the "ribbonRoutingFilter" bean from zuul not registered at all.
So I have my own implementation. First thing I tried, I used the #component annotation and autowire the dependencies. Added a breakpoint in the constructor, and it ended up never being called. So I realize my definition must be loaded earlier than zuul's. So I created a configuration class with #Configuration annotation and #Order(Ordered.HIGHEST_PRECEDENCE), and use a #Bean annotation to instantiate my class there. Still, my method is always loaded earlier.
It turned out there's certain order Spring is following when loading configuration classes definitions and that is where overrides happen. Class org.springframework.context.annotation.ConfigurationClassParser has the detailed logic in method doProcessConfigurationClass(). I'll put my simplified summarization or the ordering rule here:
if you application class(where main() method is defined) has any classes defined in it, they are parsed and definition inside them are registered first
then it will registered Beans defined as #component and defined in #Configuration class
then it will add definitions introduced by #Import
then it will add definitions introduced by #ImportResource
then add definitions from #bean methods inside the application class
then from default methods on interfaces( I think it's java 8)
then try to do the same steps above for any parent classes you application class has extended.
This explained why my override was not working. It's because all I have been trying is in step 2. But zuul defined the bean by a #Import which is step 3.
So to solve my problem, I added a #Bean annotated method to my application class there and do the instanciation and the override just happend as expected.
The above summarization might not be accurate, it just give you an idea about what could have failed your override. You'd better debug the ConfigurationClassParser when you are trying your specific use case.
We use #Configuration classes with lots of #Bean annotated methods that essentially read like this:
#Bean
public TeamContactIndexer teamContactIndexer(GroupService groupService, ContactCrudService contactCrudService, ContactRetrieveService contactRetrieveService) {
return new TeamContactIndexer(groupService, contactCrudService, contactRetrieveService);
}
So this returns a new bean and injects other spring declared things via method arguments into the constructor by name.
The only way I know to reduce verbosity is to annotate the beans with #Component and constructor with #Autowired.
For many this is perfectly acceptable but I prefer to not litter my code with Spring annotations just to facilitate plumbing and keep a clean separation between completely spring free business logic and plumbing code in #Configuration annotated classes. I treat them as a more type safe, less verbose replacement for what we used to do in xml.
However, wouldn't it be nice if I could just go ...
#Bean
public TeamContactIndexer teamContactIndexer;
... and have spring figure out that it needs to autowire the constructor of that class (100% spring free) to produce the bean. This is not currently supported in Spring as far as I can see even though it should be quite easy to do as far as I can see. Am I missing something or is there really no way around me micromanaging constructor calls in my #Configuration classes (other than littering my code with annotations)? The vast majority of my #Bean methods should be easily replaced like this.
UPDATE
#bezmax has provided a workable approach here which is to use a component scan annotation.
#Configuration
#ComponentScan(
basePackages={"com.github.jsonj.tools"},
includeFilters = { #Filter(type = FilterType.ASSIGNABLE_TYPE, value = {JsonParser.class})})
public class JsonParserConfig {
}
I've used the above to provide a bean definition for a bean without annotations in a library that I use. This replaces the #Bean annotated factory method I had earlier. It's still somewhat verbose but at least you can put in a comma separated list of classes. The default for type is wrong for this usecase so you must specify it; likewise the package defintion is required even though it could be deduced from the class on the filter.
IMHO there is room for an obvious improvement in Spring, which is to provide an annotation that simply takes a comma separated list of classes. So, instead of scanning a package, simply list the bean classes you want initialized. There are probably still a few hairy issues with autowiring via the constructor.
This feature is implemented in Spring 4.3 (not yet released).
You can read more about that in the changelog (see 6.1)
Added:
As about registering your unannotated classes automatically, there seems to be a flexible way to achieve this using #ComponentScan annotation. This annotation allows you to specify a set of include filters, which, when matched on classes, are automatically registered as beans. I had not actually tried using more complex rules with this filter, and it seems that you have several options there (check out the documentation on #ComponentScan) but the easiest one would be something like this:
#Configuration
#ComponentScan(
value = "some.package.path",
includeFilters = {
#Filter(type = ASSIGNABLE_TYPE, value = {
MyClass1.class,
MyClass2.class,
MyClass3.class
})
})
public class WebConfig extends WebMvcConfigurerAdapter {
...