Why Spring's AsyncConfigurer messes up context loading order - spring

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.

Related

Spring application with EmptyInterceptor no longer calling `onSave` or `onFlushDirty` in tests

We have a Spring Boot 2.4.5 application that uses a custom EmptyInterceptor. This interceptor is working in both the application and the tests where both the onSave and onFlushDirty methods are being executed properly.
We just updated to Boot which also upgrades Hibernate and JUnit along with many other libraries (details below). With this upgrade, our application still works as expected but for some reason, the interceptor's onSave and onFlushDirty methods are not being executed. We do see other interceptor methods being executed so we can assume that the interceptor is properly registered.
I've been combing through release notes for Spring, Spring JPA, and Hibernate but can't find anything that appears to be related to how this works. Is there something we're missing as part of the upgrade that may be related to changing the way the interceptor works?
Technical details:
Our custom interceptor:
#Component
public class AuditedEntityInterceptor extends EmptyInterceptor implements BeanFactoryAware
.. which is then wired into the application by:
#Configuration
#Slf4j
public class HibernateInterceptorConfig implements HibernatePropertiesCustomizer {
#Autowired
private AuditedEntityInterceptor auditedEntityInterceptor;
//...
#Override
public void customize(Map<String, Object> hibernateProperties)
{
hibernateProperties.put("hibernate.session_factory.interceptor", auditedEntityInterceptor);
//...
}
}
I'm trying to not overload this question with too much detail but it's probably important how our integration tests are configured:
// Each single integration test is structured like:
#Transactional
public class SomethingSomethingServiceIT extends AppSharedIT
#SpringBootTest(classes = { AppSharedItConfig.class })
public abstract class AppSharedIT extends AppSupportHsqlIT
#SpringBootTest(classes = AppSupportItConfig.class)
#Sql(scripts = {
// ... a bunch of SQL scripts to initialize reference data
})
#Transactional
#ActiveProfiles(profiles = { "test" })
public abstract class AppHsqlIT implements BeanFactoryAware
#Configuration
#EnableAutoConfiguration(exclude = { QuartzAutoConfiguration.class })
#Import({ AppSupportConfig.class })
#ComponentScan(basePackages = {
//...
})
public class AppSupportItConfig
#Configuration
#EnableTransactionManagement
#EntityScan({
//...
})
#EnableJpaRepositories({
//...
})
#ComponentScan(
basePackages = {
//...
})
#Import(value = { //...
HibernateInterceptorConfig.class })
public class AppSupportConfig
Among many other libraries, I've been focusing on the following version changes:
junit-jupiter: 5.7.1 -> 5.8.2
spring-boot: 2.4.5 -> 2.7.4
hibernate-core: 5.4.30.Final -> 5.6.11.Final

Must #ComponentScan be placed with #Configuration? (Spring Core)

I read inside many articles that #ComponentScan should be placed with #Configuration on top of a class. Here some references:
we use the #ComponentScan annotation along with #Configuration
annotation to specify the packages that we want to be scanned
(https://www.baeldung.com/spring-component-scanning)
#ComponentScan(basePackages = "com.zetcode") #Configuration public
class Application { ... } (http://zetcode.com/spring/componentscan)
The #ComponentScan annotation is used with the #Configuration
annotation to tell Spring the packages to scan for annotated
components. (https://dzone.com/articles/spring-component-scan)
I was curious to try if without #Configuration an exception would have been thrown. Surprisingly everything works fine even without #Configuration. Here the code:
#ComponentScan
public class AppConfig {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
}
I had just one sample bean which got printed.
#Component
public class Car {
}
This was the output of the main method:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
appConfig
car
Why does it work? and why do they tell to use it with configuration? was it an old requirement?
And even more surprisingly appConfig becomes a bean, even if it does not have any particular annotation such as #Configuration or #Component. So does that mean that anything that gets put as argument of new AnnotationConfigApplicationContext() gets turned into a bean no matter what annotation does it has or has not?
I probably miss some core spring behavior which would justify this. Any idea?
You are still using #Configuration together with #ComponentScan implicitly. By pasing the AppConfig.class as param to the context, it considers it configuration. That would explain the bean created for it as well

Under what circumstances #Bean excute before #PostConstruct?

i met a urger issue, the anotain #Bean method execute before the #PostConstruct method in the same class,
in spring boot oauth2. there is a class named as
AuthorizationServerEndpointsConfiguration.java
There are 2 methods in it.
#PostConstruct
public void init() {
xxxx
}
}
#Bean
public AuthorizationServerTokenServices defaultAuthorizationServerTokenServices() {
return endpoints.getDefaultAuthorizationServerTokenServices();
}
According to my understanding,the init shuold run before defaultAuthorizationServerTokenServices method, but when i debug it in IDEA, the defaultAuthorizationServerTokenServices before init.
As below config can to reproduce this issue.
#Configuration
#Import({ ClientDetailsServiceConfiguration.class, AuthorizationServerEndpointsConfiguration.class })
class MyAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {
.....
}
Could you tell me what's the reason?
Thanks,
We had this issue when debugging a configurer with #RefreshScope.
When we dropped the RefreshScope lazy loading it appeared to fix the issue
// #RefreshScope
public class MyAuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter {
}

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.

Spring junit error single matching bean but found 2

I have a test class, and have created a java config class to use with this class.. But im having issues as other tests seem to throw up found two instances of bean in configuration...
my test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=TestConfiguration.class)
public class ListenerTest {
// various tests.. just basic stuff..
}
#Configuration
public class TestConfiguration {
#Bean
public MyListsner ListenerImpl() {
return Mockito.mock(MyListsner .class);
}
}
Now for this test class passes fine when i use a mock as above. My other test classes seem to fail and they are as follows:
test class which fails...
This class throws the error
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=GeneratorTestConfiguration.class)
#Transactional
public class GeneratorTest {
// various tests
}
Main config
#Configuration
#Import({
BaseConfiguration.class,
CoreBaseConfiguration.class
})
#Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
#EnableTransactionManagement(proxyTargetClass = true)
#EnableJpaRepositories(basePackages={
"com.persistence.repository"
})
#ComponentScan({ // where the components are
"com.tests"
})
public class GeneratorTestConfiguration {
}
I dont know why, when i add listener mock to the above class ListenerTest, the toher tests fail, as im being specific in those classes to use the relevant configuration when autowiring.
Seems the bean was defined twice.

Resources