adding #EnableAuthorizationServer throws exception on server startup - spring-boot

The following works fine
#Configuration
#EnableCaching
#EnableOAuth2Sso
#EnableWebSecurity
#EnableOAuth2Client
#SpringBootApplication
#Import({ AppConvConfig.class, AppPropConfig.class, AppSecConfig.class })
#EnableAspectJAutoProxy(proxyTargetClass = true)
#EnableTransactionManagement(proxyTargetClass = true)
#EntityScan(basePackages = { BeanConstants.SCAN_PKG_JDBC_ENTITY })
#EnableJpaRepositories(basePackages = { BeanConstants.SCAN_PKG_JDBC_REPO })
#ComponentScan(basePackages = { BeanConstants.SCAN_PKG_SERVI, BeanConstants.SCAN_PKG_FLICK_WEB })
public class AppConfig extends WebMvcConfigurerAdapter {
..
}
But if I add #EnableAuthorizationServer to the above, start seeing the following exception on startup
***************************
APPLICATION FAILED TO START
***************************
Description:
Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
- remoteTokenServices: defined by method 'remoteTokenServices' in org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration$RemoteTokenServicesConfiguration$TokenInfoServicesConfiguration
- defaultAuthorizationServerTokenServices: defined by method 'defaultAuthorizationServerTokenServices' in org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration
Action:
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed

Nevermind, #EnableOAuth2Sso & #EnableOAuth2Client were redundant, removed #EnableOAuth2Sso and it starts up fine.. testing the rest. Final list:
#Configuration
#EnableCaching
#EnableWebSecurity
#EnableOAuth2Client
#EnableAuthorizationServer
#SpringBootApplication
#Import({ AppConvConfig.class, AppPropConfig.class, AppSecConfig.class })
#EnableAspectJAutoProxy(proxyTargetClass = true)
#EnableTransactionManagement(proxyTargetClass = true)
#EntityScan(basePackages = { BeanConstants.SCAN_PKG_JDBC_ENTITY })
#EnableJpaRepositories(basePackages = { BeanConstants.SCAN_PKG_JDBC_REPO })
#ComponentScan(basePackages = { BeanConstants.SCAN_PKG_SERVI, BeanConstants.SCAN_PKG_FLICK_WEB })

Related

Why does EnableJpaRepositories registers beans twice?

I have one abstract configuration:
#Configuration
#EnableJpaRepositories(basePackages = {
"x","y" }, entityManagerFactoryRef = "entityManager", transactionManagerRef = "transactionManager", repositoryBaseClass = BaseRepositoryImpl.class)
#EnableTransactionManagement
#EnableConfigurationProperties({ DataSourceProperties.class })
public abstract class AbstractBaseConfiguration {}
Then its implemented by the concrete Configuration class
#ComponentScan(basePackages = { "x", "z" })
public class BaseConfiguration extends AbstractBaseConfiguration {}
Combined in
#Configuration
#Import({ BaseConfiguration.class, RestConfiguration.class })
#ComponentScan(basePackages = { "x", "z" })
public class RestBaseConfiguration {}
So nested configurations, in the application at the end RestBaseConfiguration is used.
This was working before when using SpringBoot 2.0.X.
Now I upgraded SpringBoot to latest version (2.6.1). Suddenly I get exception:
org.springframework.beans.factory.support.BeanDefinitionOverrideException:
Invalid bean definition with name 'com.example.XRepository' defined in com.example.XRepository defined in #EnableJpaRepositories declared on AbstractBaseConfiguration
Cannot register bean definition JpaRepositoryFactoryBean defined in XRepository defined in #EnableJpaRepositories declared on AbstractBaseConfiguration
There is already JpaRepositoryFactoryBean defined in XRepository defined in #EnableJpaRepositories declared on BaseConfiguration
I guess underlying issue is because beans are being overwritten https://stackoverflow.com/a/53723731/978302.
The question is why? Based on the error message, is EnableJpaRepositories being also proxied for the abstract class and for this reason repositories will be instantiated twice? Or somehow basePackages parameter of the annotation is interfering with the scans and then scan are executed twice..

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 {
}

spring boot - spring data jpa error

main class annotations -
#SpringBootApplication
#ComponentScan( basePackages = "com.webstar" )
#EntityScan(basePackages = "com.webstar.models" )
#EnableJpaRepositories(basePackages = "com.webstar.repository")
#EnableAutoConfiguration
public interface UserAccounts extends JpaRepository<Registration, Long>
{
}
my test class -
#RunWith( SpringJUnit4ClassRunner.class )
#WebAppConfiguration
public class RegistrationTest
{
#Autowired
private UserAccounts userRepo;
#Test
public void testRegistration()
{
Registration reg = new Registration("1212","1212","1212","121","1212",null,null);
userRepo.save(reg);
}
}
Error - Caused by the following:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
My repository and models are in different packages.
Let's say that you have the following configuration:
Your entity package com.other.model
Your repository package: com.other.repository
Your testing class that is in a totally different package: foo.test.mydemo.MyOtherAppTest
Go to foo.test.mydemo.MyOtherAppTest class and add the following annotation:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
#SpringBootConfiguration
#EnableAutoConfiguration
#EntityScan(basePackages = "com.other.model")
#EnableJpaRepositories(basePackages = "com.other.repository")
public class MyOtherAppTest {
on you RegistrationTest.class
add annotation:
#SpringApplicationConfiguration(class=classname.class)
//classname is you main class name
if you use springBootTest
use #SpringBootTest(class=classname.class)
//classname is you main class name
wish help you ~

No transactional EntityManager available;

My app using spring and jpa, i have two config file:
AppConfig:
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = { "com.test.api" })
#EnableJpaRepositories("com.test.api.repository")
#PropertySource("classpath:application.properties")
public class AppConfig {
}
WebAppConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.test.webservice" })
public static class WebAppConfig extends WebMvcConfigurerAdapter {
}
Almost work fine, but sometime it throw an exception: Caused by: java.lang.IllegalStateException: No transactional EntityManager available even I just select record (Not create, update or delete data.)
If I move annotation: #ComponentScan(basePackages = { "com.test.api" }) to Class WebAppConfig and remove: #ComponentScan(basePackages = { "com.test.webservice" }) then exception is disappear, but spring context load many time when server startup and spring beans are duplicate.
Or If I use entityManager.getEntityManagerFactory().createEntityManager().unwrap(Session.class) instead for entityManager.unwrap(Session.class) then exception also disappear.
How can I solve it?
Remove the ComponentScan on WebAppConfig and add the package in the ComponentScan annotation on AppConfig, that should solve your problem.

Why Spring's AsyncConfigurer messes up context loading order

I'm experiencing a strange behavior with Spring context initialization ordering. I have the following configuration class:
#Configuration
#ComponentScan(basePackageClasses = foo.Bar.class, useDefaultFilters = false, includeFilters = #Filter(Service.class))
#Import({ PersistenceConfig.class, SecurityConfig.class })
#EnableAsync
#EnableScheduling
public class RootConfiguration {
#PostConstruct
public void done() throws Exception {
}
}
This works just fine. My done method gets executed AFTER PersistenceConfig and ServiceConfig.
But whey I make my Rootconfiguration implement AsyncConfigurer, the done method gets executed BEFORE PersistenceContext and SecurityContext, which is problematic in my case!
Any ideas of why such behavior?
Is it documented somewhere?
Any insight would be greatly appreciated.

Resources