SpringBoot 2.1 spring.main.allow-bean-definition-overriding=true not working - spring-boot

We are upgrading to SpringBoot 2.1.x and Spring Security 5.1.x. We have our own SecurityConfig that overrides springSecurityFilterChain bean that is found in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration. I have added that property to the applications.property file and set it to true but it is still not allowing overrides.
Our class:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public FilterChainProxy springSecurityFilterChain() throws Exception {
blahblahblah
}
}
And the Spring class:
package org.springframework.security.config.annotation.web.configuration;
#Configuration
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
#Bean(
name = {"springSecurityFilterChain"}
)
public Filter springSecurityFilterChain() throws Exception {
blahblah
}
}
The error:
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'springSecurityFilterChain' defined in class path resource
Its not clear to me why setting the override property to true is not being picked up. I have also tried to annotate our bean as primary, the #autoconfigureBefore(WebSecurityConfiguration.class) and removing non-wanted bean from registry (but haven't figured out how to do that successfully). Is there something special about the bean I am trying to override that prevents it? Do I need to have the applications.property file loaded earlier somehow?

same issue here. what is the solution for this. I have
#Bean
#Primary
public ScheduledLockConfiguration taskScheduler(LockProvider lockProvider) {
}
But it doesn't seem to be invoked as another bean in third party library exists with same name.

Related

Error with using #ComponentScan on multiple packages in Spring Boot

Here's my issue--I have a service that relies on an external library. I was trying to autowire the service so I can use it but was not able to
import org.keycloak.admin.client.token.TokenService;
public class SimpleService {
#Autowired
private TokenService keycloakTokenSvc; // Could not autowire, no beans of type 'TokenService' found
public void execute() {
keyCloakTokenSvc.doSomething();
}
}
I then added this to my SpringBootApplication and got it working:
#SpringBootApplication
#ComponentScan({"org.keycloak.admin.client.token"})
public MyApp {}
Sweet -- all good now, right? Nope. It seems like this overrides some of my auto configuraitons like my security config, so I was no longer to make RESTful requests to my application while it was running. I then did this next:
#SpringBootApplication
#ComponentScan({"org.keycloak.admin.client.token", "com.project.pkg"})
public MyApp {}
Still nothing. I get the same error as before:
Field keycloakTokenSvc in com.mark43.jms.services.TokenRefreshService required a bean of type 'org.keycloak.admin.client.token.TokenService' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.keycloak.admin.client.token.TokenService' in your configuration.
I'm new to Spring Boot so not sure what to do here. Is there a way to use the TokenService without Autowiring? Is there a way to scan both packages?
It seems to me that you need to create a TokenService bean as follows:
#Configuration
public class TokenConfig {
#Bean
public TokenService tokenService() {
return new TokenService(); // Or whatever you need to instantiate it
}
}
This will register a TokenService object as a Spring-managed bean so that it can be autowired into SimpleService.

A bean with that name has already been defined in class path resource [path] and overriding is disabled

I have the java configuration for the Spring Data Elaticsearch(using Transport Client) and ESTemplate.
Here some except:
#Configuration
#EnableElasticsearchRepositories(basePackages = "subpackage-in-this-project")
#PropertySource("file:path-to-file")
public class ESConfig {
#Bean
ElasticsearchTemplate elasticsearchTemplate(Client client) {
return new ElasticsearchTemplate(client);
}
#Bean
Client client() {
// configuration of the ES client
}
}
And I have a config that extends the one above in the different project.
#Configuration
#ComponentScan("package-prefix-that-matches-packages-in-both-projects")
#EnableElasticsearchRepositories(basePackages = "subpackage-in-this-project")
#PropertySource("file:same-path-to-file-as-in-the-config-above")
public class ExtendedESConfig extends ESConfig {
#Value("index-name")
private String indexName;
#Bean
public String indexName() {
return indexName;
}
}
Upon executing a third Spring Boot application, which uses the dependency on the project with ExtendedESConfig, I get this and I can't quite understand why does it happen, started to happen after upgrading to 2.2.9.RELEASE from 2.0.5.RELEASE Spring Boot version.
***************************
APPLICATION FAILED TO START
***************************
Description:
The bean 'elasticsearchTemplate', defined in class path resource [my/package/ESConfig.class], could not be registered. A bean with that name has already been defined in class path resource [my/other/package/ExtendedESConfig.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
2020-08-30 16:49:46 ERROR [main] org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter:40 -
Important remark from my comment:
... sadly, I am not the one who wrote this ES config and built the whole infrastructure around it. ...
At the time of this question, I don't own ExtendedESConfig nor can change it.
Or you can add the next property to your application.properties :
spring.main.allow-bean-definition-overriding=true
The default behaviour of overriding bean has been disabled in Spring Boot 2.1. Spring Boot 2.1 Release Notes
Since you don't own / or don't want to modify both configuration classes. You can exclude parent configuration form your SpringBootApplication class using #ComponentScan
#SpringBootApplication
#ComponentScan(excludeFilters =
{#ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ESConfig.class)})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
I had a similar problem with my custom springSecurityFilterChain method, in my #Configuration class. The application told me it couldn't create a Bean named springSecurityFilterChain since it was defined elsewhere (in my case, in a Spring Security package, which, as is your case, I couldn't modify).
I found the solution here and it amounted to simply changing my custom method's name; I chose customFilterChain. So it went from
#Bean
public SecurityFilterChain springSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
// etc
}
to:
#Bean
public SecurityFilterChain customFilterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
// etc
}
Amazingly it worked. Like the article says, Spring builds the bean using the method's name by default. Hope it helps.
find in your modul: resources/application.properties and write:
spring.main.allow-bean-definition-overriding=true
it help you, you need to enable the beans override mechanism.

Adding #Conditional to an existing spring annotation in spring boot

I have an application which uses an existing spring annotation (#EnableResourceServer). I want this particular annotation to be enabled only when a particular property value is not false.
To do this, I created a meta-annotation and applied #ConditionalOnProperty on that :
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#ConditionalOnProperty(prefix = "custom.resource", name = "enabled", matchIfMissing = true)
#EnableResourceServer
public #interface EnableCustomResourceSecurity {
}
In my application I'm now using #EnableCustomResourceSecurity like :
#EnableCustomResourceSecurity
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
and it all works fine if the property is missing or true but when I change the property to custom.resource.enabled=false I get the following exception :
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
I tried putting this annotation in a couple of other places and noticed that when the conditional expression fails for this annotation, any annotation after this also stops getting processed.
What would be the correct way to achieve what I'm trying to do?
Your annotation #EnableCustomResourceSecurity has the meta annotation #ConditionalOnProperty. While it may seem as if it enables/disables the #EnableResourceServer annotation, it actually enables/disables your MyApplication bean as a whole. It is as if you would write:
#SpringBootApplication
#ConditionalOnProperty(...)
#EnableResourceServer
public class MyApplication {
To avoid this, simply create an empty SomeConfiguration class and annotate it with your custom annotation:
#Configuration
#EnableCustomResourceSecurity
public class SomeConfiguration {}
Instead of adding it to your MyApplication class.
I would recommend, you don't even need a custom annotation but just an empty configuration as mentioned by Michiel. This configuration, in turn, will also import the #EnableResourceServer annotation.
#Configuration
#EnableResourceServer
#ConditionalOnProperty(prefix = "custom.resource", name = "enabled", matchIfMissing = true)
public class ResourceServerConfig {
public ResourceServerConfig() {
System.out.println("initializing ResourceServerConfig ...");
}
}
If you want to control based on annotation, you can import the same configuration in the custom annotation as below:
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Import(ResourceServerConfig.class)
public #interface EnableCustomResourceSecurity {
}

Requested bean is currently in creation: Is there an unresolvable circular reference when use AspectJ and security

Hi i am developing a web application with using spring security and doing logging with AspectJ.
When i add new bean which is created with AspectJ getting this error.
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'loggingAspect': Requested bean is currently in creation: Is there an unresolvable circular reference?
My Spring configuration file ;
#Configuration
#EnableWebMvc
#EnableAspectJAutoProxy
#ComponentScan( basePackages = { "com.org" } )
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public LoggingAspect loggingAspect() {
return new LoggingAspect();
}
My Spring security configuration file with annotation;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { }
Logging aspect
#Aspect
#Component
public class LoggingAspect {
/**
* Default Constructor.
*/
public LoggingAspect() {
}
I can't create this bean and couldn't find any solution.
May anyone help for this please.
Thanks.

spring data JPA & spring data elasticsearch; No property index found for type?

I'm unsure why this is happening! I've got a class that is used by spring data elasticsearch and spring data jpa, but when I try run my application I get an error.
Error creating bean with name 'articleSearch':
Invocation of init method failed; nested exception is
org.springframework.data.mapping.PropertyReferenceException:
No property index found for type Article!
Caused by: org.springframework.data.mapping.PropertyReferenceException:
No property index found for type Article!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:77) ~[spring-data-commons-1.11.4.RELEASE.jar:na]
I've got the following application class:
#SpringBootApplication
#EnableAsync
#ComponentScan(basePackages = {"com.article.models", "com.user"})
public class ArticleApplication {
And the following elasticsearch config:
#Configuration
#EnableElasticsearchRepositories(basePackages = "com.article.search")
public class ElasticSearchConfiguration {
#Resource
private Environment environment;
#Bean
public Client client() {
TransportClient client = new TransportClient();
TransportAddress address = new InetSocketTransportAddress(environment.getProperty("elasticsearch.host"), Integer.parseInt(environment.getProperty("elasticsearch.port")));
client.addTransportAddress(address);
return client;
}
#Bean
public ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(client());
}
}
This is how I've setup my model class:
#Entity
#Table(name="article")
#Document(indexName="article", type="articles")
public class Article implements Serializable {
I've then got a package search that extends the elasticsearchrepository, like so:
public interface ArticleSearch extends ElasticsearchRepository<Article, String> {
I'm trying to autowire the articlesearch class inside another service which is causing the error to occur:
#Autowired
ArticleSearch articleSearch;
What am I missing here?! I guess it's a bit more complex when trying to use data-jpa + data-elasticsearch.
I found out why this was happening. I'm not sure why, but spring didn't seem to be picking up my ElasticSearchConfiguration configuration class!
So I simply moved all the contents from that and dumped it in my main application class (where all my other config is).
I also removed component scan & added the enablejparepository + enableelasticsearchrepository annotations to my main class. Here is what it looks like now:
#SpringBootApplication
#EnableAsync
#EnableElasticsearchRepositories(basePackages = "com.article.search")
#EnableJpaRepositories(basePackages = {"com.article.dao", "com.user.dao"})
public class ArticleApplication {

Resources