I had been using the WebMvcConfigurerAdapter for a while. Since i could not get all the registered interceptors with the method getInterceptors(), i have switched to WebMvcConfigurationSupport, which has lot of default registered Spring Beans like ContentNegotiationManager, ExceptionHandlerExceptionResolver usw.
Now i have realised that, the very handy DomainClassConverter (which converts the domain class ids to domain class objects by using a CrudRepository) is not registered by default, although i use the annotation #EnableSpringDataWebSupport on my WebConfig class.
When i define this bean explicitly like this, it works then.
#EnableSpringDataWebSupport
#Configuration
public class WebConfig extends WebMvcConfigurationSupport {
#Bean
public DomainClassConverter<?> domainClassConverter() {
return new DomainClassConverter<FormattingConversionService>(mvcConversionService());
}
}
But why EnableSpringDataWebSupport does not work with WebMvcConfigurationSupport?
It looks like configuration classes that extend WebMvcConfigurationSupport directly suffer from SPR-10565. The solution, at least for me, is to extend from DelegatingWebMvcConfiguration instead.
If you're overriding individual callbacks in your configuration class you'll likely want to call the superclass' implementation of the callback as well to ensure it's all handled correctly.
Related
How can I solve this error. I'm New to Spring-boot
As I can see the spring unable to find the bean UserDetailsServiceImpl, there might be couple of reason for it.
First, you might forgot to put #Service annotation on top of the class UserDetailsServiceImpl. Also, as the context is about Spring security so make sure that this class UserDetailsServiceImpl must implement the interface UserDetailsService
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
}
Second, spring might be unable to scan this folder. So make sure spring IOC must scan this package while intialization and configure the bean.
In order to #Autowired a bean instance, a class should be decorated with Spring stereotype annotation like #Component, #Service, #Repository, #Controller or #Indexed. Just by decorating the class with one of these role annotations, you can use #Autowired to bind with the instance.
Otherwise, if none of these annotations are used, your class instances, you have to manually registered to the BeanFactory like this;
#Configuration
public class SomeClass {
...
#Bean
public UserDetailsServiceImpl userDetailsService() {
return new UserDetailsServiceImpl()
}
}
This answer just talk about your specific question, but you get to find out why #Configuration is used in preceeding example. Define scopes for bindings, singleton (one instance for the application) is the default scope in Spring, you should define scopes for beans if they should be in different scope on your requirements.
I have a simple Spring MVC 5 project, with security layer enabled. Everything works good except the properties loading, only on Security Config.
I let you the scenario so you can see it.
application.properties (located at src/main/resources)
com.company.myapp.prop=myprop
MainConfig.java
#Configuration
public class MainConfig implements WebMvcConfigurer {
#Value("${com.company.myapp.prop}")
private String prop;
#Bean
public MySpecialBean mySpecialBean() {
System.out.println(prop); // output > myprop
return new MySpecialBean();
}
}
SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${com.company.myapp.prop}")
private String prop;
#Bean
public MySpecialSecurityBean mySpecialSecurityBean() {
System.out.println(prop); // output > null
return new MySpecialSecurityBean();
}
}
I don't understand why it's happening. I already switched the #EnableWebSecurity annotation to the app class, try to set the PropertySourcesPlaceholderConfigurer myself, but nothing works.
Do you have any idea what's going on?
From official docs about #PropertySource:
Resolving ${...} placeholders in <bean> and #Value annotations
In order to resolve ${...} placeholders in definitions or #Value annotations using properties from a PropertySource, you must ensure that an appropriate embedded value resolver is registered in the BeanFactory used by the ApplicationContext. This happens automatically when using in XML. When using #Configuration classes this can be achieved by explicitly registering a PropertySourcesPlaceholderConfigurer via a static #Bean method. Note, however, that explicit registration of a PropertySourcesPlaceholderConfigurer via a static #Bean method is typically only required if you need to customize configuration such as the placeholder syntax, etc. See the "Working with externalized values" section of #Configuration's javadocs and "a note on BeanFactoryPostProcessor-returning #Bean methods" of #Bean's javadocs for details and examples.
You should try to add annotation #PropertySource into the your config class.
#Configuration
#PropertySource("classpath:my.properties")
public class MainConfig implements WebMvcConfigurer {}
and then try to access your property in SecurityConfig class
To get full information see official docs
I hope it will help you
This works for me.
I guess you have another class that triggers the application and that is annotated with #SpringBootApplication
Also, your methods mySpecialBean do not return a MySpecialBean instance, so this probably does not even compile.
Is there any other class that you are using? Please advice
Finally got it!
The problem was related with some dependency priorities and unnecessary beans declarations. Getting into details, I'm working with OAuht2 and I started with this tutorial. In the end I've made a mix with this one too (more recent). The problem was related with these #Bean's that don't really need to be declared as beans:
ClientRegistrationRepository
ClientRegistration
OAuth2AuthorizedClientService
Spring was calling these beans before any other configuration, so any properties was not loaded yet. Maybe changing the priority, dependence or even the order would resolve the issue, but as I was analysing the code I found that these methods are only used on security configuration and not really needed along any other part of the app. So I removed the #Bean declaration and all works nice now! At the time these methods are called inside security config the properties are already loaded.
Hope to help someone out there.
I recently started exploring Spring Boot. I see that there are 2 ways to define Beans in Spring Boot.
Define #Bean in the class annotated with #SprinBootApplication
Define #Bean in a class annotated with #Configuration
I am also confused about stereo-type annotation #Repository #Service #Controller etc.
Can someone please explain how dependency-injection works with these annotations?
Yes it is possible.
Either you use #Bean in any of your #Configuration or #SpringBootApplication class or mark the bean classes explicitly with annotations like #Service, #Component #Repository etc.
#Service or #Component
When you mark a class with #Service or #Compoenent and if spring's annotation scanning scope allows it to reach to the package, spring will register the instances of those classes as spring beans.
You can provide the packages to be included/excluded during scan with #ComponentScan
#Bean
#Beans are marked on factory methods which can create an instance of a particular class.
#Bean
public Account getAccount(){
return new DailyAccount();
}
Now in you application you can simply #Autowire Account and spring will internally call its factory method getAccount, which in turn returns an instance of DailyAccount.
There is a simple difference of using #Bean vs #Service or #Compoenent.
The first one makes your beans loosely coupled to each other.
In the #Bean, you have flexibility to change the account implementation without even changing any of the account classes.
Consider if your classes instantiation is a multi-step operation like read properties values etc then you can easily do it in your #Bean method.
#Bean also helps if you don't have source code access to the class you are trying to instantiate.
Spring Boot auto-configuration attempts to automatically configure your Spring application based on the jar dependencies that you have added.
You need to opt-in to auto-configuration by adding the #EnableAutoConfiguration or #SpringBootApplication annotations to one of your #Configuration classes.
You are free to use any of the standard Spring Framework techniques to define your beans and their injected dependencies. For simplicity, we often find that using #ComponentScan (to find your beans) and using #Autowired (to do constructor injection) works well.
One way is to define #Bean in the class annotated with
#SprinBootApplication
If you see #SprinBootApplication it is combination of many annotation, and one of them is #Configuration. So when you define #Bean in the Main class, it means it's inside #Configuration class.
According to Configuration docs :
Indicates that a class declares one or more #Bean methods and may be
processed by the Spring container to generate bean definitions and
service requests for those beans at runtime.
class annotated with #Configuration
When you define #Bean is a class annotated with #Configuration class, it means it is the part of spring configuration all the Beans define in it all available for Dependency-Injection.
I have also seen some code where neither of the 2 above approaches
have been used and yet dependency injection works fine. I have tried
to research a lot on this but could not find any concrete answer to
this. Is this possible?
I am assuming you are talking about Sterio-type annotation. Every sterio type annotation has #Component, according to docs :
Indicates that an annotated class is a "component". Such classes are
considered as candidates for auto-detection when using
annotation-based configuration and classpath scanning.
I am not able to apply an aspect to my spring rest endpoint components for logging purposes.
All of endpoint classes are implemented like
#Component
#Path("mypath")
public class MyEndpointImpl extends MyEndpoint
{...}
Without aspect everything works fine without any errors. When I try to apply aspect I just get list of errors for each endpoint class like "None or multiple beans found in Spring context for type class **.*EndpointImpl" and no aspect is intercepting endpoints' methods. However everything works fine as if there were no error message and no aspect.
Interesting is when I create e.g. simple filter
#Component
#WebFilter(filterName = "MySimpleFilter", urlPatterns = "/*")
public class SimpleFilter implements javax.servlet.Filter
{...}
in package of pointcut, doFilter method of SimpleFilter is intercepted by the aspect as would expect for all endpoint methods.
What could be a problem here, any ideas?
In my environment the Problem disappeared when adding the following to the application.yml file
spring.aop.proxy-target-class: true
I would like to add resource handlers. In the forum they use WebMvcConfigurationSupport: http://forum.springsource.org/showthread.php?116068-How-to-configure-lt-mvc-resources-gt-mapping-to-take-precedence-over-RequestMapping&p=384066#post384066
and docs say WebMvcConfigurerAdapter: http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/web/servlet/config/annotation/EnableWebMvc.html
What's the difference and which one to use? Both has the addResourceHandlers method I need.
This is my current class:
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
public #Override void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources");
}
public #Bean TilesViewResolver tilesViewResolver() {
return new TilesViewResolver();
}
public #Bean TilesConfigurer tilesConfigurer() {
TilesConfigurer ret = new TilesConfigurer();
ret.setDefinitions(new String[] { "classpath:tiles.xml" });
return ret;
}
}
The answer is in the doc you referenced above:
If the customization options of WebMvcConfigurer do not expose
something you need to configure, consider removing the #EnableWebMvc
annotation and extending directly from WebMvcConfigurationSupport
overriding selected #Bean methods
In short, if #EnableWebMvc works for you, there is no need to look any further.
if you use ConfigurationSupport class get ready mind numbing hardwork when trying to serve static resources, because it does not work.
I was recently solving this very same problem when configuring converters and it resulted in quite a long post.
By default Spring Boot uses its implementation of WebMvcConfigurationSupport and does a lot of auto-magic including finding all the WebMvcConfigurer and using them. There is one implementation provided by Boot already and you may add more. This results in seemingly confusing behaviour when the list of converters coming to configureMessageConverters in your implementation of WebMvcConfigurer is already pre-populated from previous configurer.
These types (WebMvcConfigurationSupport and WebMvcConfigurer) have also strikingly similar interface - but the first does NOT implement the other. The point is:
Support class searches for configurers and uses them + does something on its own.
If you extend from WebMvcConfigurationSupport you take over the configuration and while there are some things available that are not in WebMvcConfigurer (like addDefaultHttpMessageConverters) there is also tons of code from EnableWebMvcConfiguration and DelegatingWebMvcConfiguration that does not happen.
Both extending WebMvcConfigurationSupport or WebMvcConfigurer (not sure both at once makes much sense) have their valid usages, but with extending the support class you take over the process much more and lose a lot of "opinionated" Spring Boot functionality.
Its better to extend WebMvcConfigurationSupport. It provides more customization options and also
works fine with
configureMessageConverters(List<HttpMessageConverter<?>> converters)
cause you can add these convertors using
addDefaultHttpMessageConverters(converters);
that is not available with WebMvcConfigurerAdapter.
Click [here] How to configure MappingJacksonHttpMessageConverter while using spring annotation-based configuration?
If you extend WebMvcConfigurerAdapter, it behaves strangely with configuring Jackson and Jaxb.
That happened with me !!!