Spring WebSecurityConfigurerAdapter keeps throwing IllegalStateException because of #Order - spring

I have extended WebSecurityConfigurerAdapter, but every time I start Jetty, I get the exception:
java.lang.IllegalStateException: #Order on WebSecurityConfigurers must be unique. Order of 2147433647 was already used, so it cannot be used on com.xtl.mis.support.config.SecurityConfig$$EnhancerByCGLIB$$11a4eacf#332c45ff too.
I previously had not annotated the class with #Order and started getting the exception. Currently, I have my class annotated with #Order(Ordered.LOWEST_PRECEDENCE - 50000). I've tried several different values for this annotation, but always get the above exception saying the #Order must be unique and the one calculated was already used. I'm using Spring Security 3.1.4.RELEASE and Spring Security JavaConfig 1.0.0.M1.

I believe I've fixed this. I had a central #Configuration class called AppConfig which also had an #Import({SecurityConfig.class}) annotation on it. I removed the #Import annotation and added #ComponentScan and now it works.

When extending WebSecurityConfigurerAdapter in an integration test, you may as well replace..
#Import({SecurityConfig.class})
..by..
#ContextConfiguration(classes = SecurityConfig.class)

Related

what is the significance of #Component annotation for Filter in spring boot?

Why do we need to use #Component annotation for Filter in spring boot, why we can't use #Configuration annotation.
Please note: I am not trying to register filter in FilterRegistrationBean.
#Configuration indicates that the class may contain #Bean methods and should be processed to define those beans in the application context. This isn't something that a Filter does so it should not be annotated with #Configuration.
If you look at the source for #Configuration, you'll see that it's annotated with #Component. #Configuration is a special kinds of #Component. In this case, all you need is for the Filter itself to be a bean. It doesn't have any #Bean methods so it's sufficient for it to be annotated with #Component. This will ensure that the Filter is a bean and Spring Boot will the register the Filter bean with the servlet container without any need for a FilterRegistrationBean and without wasting resources unnecessarily processing your Filter's class looking for #Bean methods.

How do I make #WebMvcTest pickup WebMvcConfigurer classes from custom starters?

I'm building a custom starter library which registers an ObjectMapper in a WebMvcConfigurer class. One of the settings on this ObjectMapper is an Instant serialization format.
When I use #SpringBootTest with #AutoConfigureMockMvc the configured ObjectMapper is picked up, and everything works as expected. However the same assertions using #WebMvcTest fail. It seems like the WebMvcConfigurer class is not being picked up in the #WebMvcTest autoconfiguration, although the docs state that it should be picked up.
Is there a way to extend the autoconfiguration for WebMvcTest's without having to resort to putting #Import with every #WebMvcTest annotation?
code example
Similar to what you have done to include your starter’s configuration in the main auto-configuration, you can include a configuration class in a particular test slice by adding an entry to spring.factories. In this case, you should use the key org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureWebMvc.
If you look at the Spring Boot source code you can see that this is how Boot’s Jackson auto-configuration is included, for example.

How is #ConfigurationProperties-annotated classes detected automatically with #SpringBootApplication Annotation

I am learning Spring Boot and have a question with one example in the reference documentation.
Following section of the documentation mentions
6. Using the #SpringBootApplication Annotation
A single #SpringBootApplication annotation can be used to enable those
three features, that is:
#EnableAutoConfiguration: enable Spring Boot’s auto-configuration
mechanism
#ComponentScan: enable #Component scan on the package where the
application is located (see the best practices)
#Configuration: allow to register extra beans in the context or import
additional configuration classes
and the following example to replace this single annotation by any of the features that it enables is bit confusing for me . The example
package com.example.myapplication;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
#Configuration(proxyBeanMethods = false)
#EnableAutoConfiguration
#Import({ MyConfig.class, MyAnotherConfig.class })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Explanation for the example
In this example, Application is just like any other Spring Boot
application except that #Component-annotated classes and
#ConfigurationProperties-annotated classes are not detected
automatically and the user-defined beans are imported explicitly (see
#Import).
The only major difference I see in the example code above is that it does not have #ComponentScan annotation. I also read in the comments section of an SO answer (Stephane Nicoll May 5 '17 at 11:07) that #Component annotation is not recommended officially to auto detect #ConfigurationProperties. So my assumption is that Spring framework classes with #ConfigurationProperties are not annotated with #Component.
Also I checked the #SpringBootApplication annotation source and couldn't identify anything that should enable the automatic detection of #ConfigurationProperties annotated classes.
The reference document 2.8.3. Enabling #ConfigurationProperties-annotated types section shows the following way to scan and autodetect #ConfigurationProperties
#SpringBootApplication
#ConfigurationPropertiesScan({ "com.example.app", "org.acme.another" })
public class MyApplication {
}
With all these details , I would like to understand
Why is it explicitly mentioned for this example that #ConfigurationProperties-annotated classes are not detected automatically ? and How is #ConfigurationProperties annotated classes automatically detected when #SpringBootApplication is used.
Additional note : I saw a small difference between the prior version of the documentation and the current one. The following reference is missing the current one
Keep in mind that the #EnableConfigurationProperties annotation is
also automatically applied to your project so that any existing bean
annotated with #ConfigurationProperties is configured from the
Environment
Following is what I understand from my analysis.
#ConfigurationProperties annotated types can be registered to the ApplicationContext by
Annotating the class with #ConfigurationProperties with an
annotation that falls in the scope of #ComponentScan (
#Component, #Service and the like ) . Not recommended as per the comment from Stephane Nicoll , which makes sense to me now.
Using annotation
#EnableConfigurationProperties . For this to
work the class annotated with #EnableConfigurationProperties
should be annotated with an annotation that falls in the scope of
#ComponentScan ( #Component, #Service and the like )
Using annotation #ConfigurationPropertiesScan and by making sure
the classes annotated with #ConfigurationProperties is placed
under its radar. The usage is similar to #ComponentScan .
Now , when we replace #SpringBootApplication with individual annotations that it enables and omit #ComponentScan (as in example) , the #EnableConfigurationProperties way (Point 2) of registering the types with #ConfigurationProperties will not work. This probably answers both my questions on why and how .
This was explicitly mentioned probably because the connection between #EnableConfigurationProperties and #ComponentScan is not that obvious for people like me.
Additional details.
The registration of #ConfigurationProperties annotated types when we use #EnableConfigurationProperties happens through of the EnableConfigurationPropertiesRegistrar class that is imported by the annotation
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Import(EnableConfigurationPropertiesRegistrar.class)
public #interface EnableConfigurationProperties {..}

How SpringBoot dependency injection works with different type of annotations

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.

spring boot #autowired filed injected with null in the #configuration class but worked with #import

According to the reference using-boot-configuration-classes, I used #ComponentScan on the Application class and use the #Configuration on my config class, in my config class, I want to inject beans defined in other config class by using #Autowired annotation, but when I run the application, I got null for these fields, I tried to use import on the application and remove the #Configuration from config class, everything works fine.
Is it a bug of spring boot or I am misunderstanding about the usage of #Configuration annotation?
Are you trying to autowire other configuration classes into Application class?
Use a fresh method along with #PostConstruct to make it call automatically after Spring creates an instance of Application class.

Resources