Cfile idempotentRepository Bean using a registered bean - idempotent

when using a cFile start point, the use of Spring beans declared at design time work fine for declaring the Fileidempotent repository that I wish to create.
But I want to have the bean configured at Runtime or at design time but soft-coded with parameters.
So I created a bean that is as follows:
public class FileIdempotentRepository(File fileStore,int cacheSize,long maxFileStoreSize){
try{
this.start;
System.out.println(this.getStatus());
}catch (Exception e) {
e.printStackTrace();
}
This bean is registered under the Id "test1" in the beanRegister.and the 3 arguments passed in.
in cFile I declare parameter idempotentRepository as "#test1"
the bean starts and has a running status . The cFile does not see this repository using that parameter argument
Any help would be approeciated
Tony Pearson
I tried instantiating the bean directly from the parameter line thinking the instantiation thru a method would work versus the constructor but that failed.
I did expect the reference to the bean thru cFile to work

Related

#WebMvcTest with #Import does not work. Test context always asks for #Repository beans

Using Spring Boot 2.7.3 I can not create a simple integration test for my API using #WebMvcTest.
Here is my setup:
// GameServerApplicationTests.kt
#SpringBootTest
class GameServerApplicationTests {
#Test
fun contextLoads() { }
}
// CraftService.kt
#Service
class CraftService {
fun getAll(): List<String> {
return listOf("foo", "bar")
}
}
// CraftApiTest.kt
#WebMvcTest
#Import(value = [CraftService::class])
class CraftApiTest {
#Autowired
private lateinit var testRestTemplate: TestRestTemplate
#Test
fun `should do accept craft all endpoint`() {
val response = testRestTemplate.getForEntity("/craft/all", String::class.java)
assertThat(response.statusCode).isEqualTo(HttpStatus.OK)
}
}
When I run the test I see this exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'itemRepository' defined in com.gameserver.item.ItemRepository defined in #EnableJpaRepositories declared on GameServerApplication: Cannot create inner bean '(inner bean)#3fba233d' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#3fba233d': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
I have no idea why it is looking for the itemRepository bean at all. I never asked for that.
I then added this
#WebMvcTest
#ComponentScan(excludeFilters = [ComponentScan.Filter(Repository::class)]) // <<
#Import(value = [CraftService::class])
Which resulted in this exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'playerRepository' defined in com.gameserver.player.PlayerRepository defined in #EnableJpaRepositories declared on GameServerApplication: Cannot create inner bean '(inner bean)#30c1da48' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#30c1da48': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available
Which confuses me even more. I explictly excluded all #Repository beans - but it just skipped ItemRepository and then asked for PlayerRepository now.
I am totally lost and have no idea why I am not able to setup a simple integration test for my API endpoint.
EDIT #1:
Other tests run just fine:
EDIT #2:
I tried to use a #Configuration bean for #Import.
// CraftApiTestConfiguration
#Configuration
class CraftApiTestConfiguration {
#Bean
fun getCraftService(): CraftService {
return CraftService()
}
}
// CraftApiTest.kt
#WebMvcTest
#Import(CraftApiTestConfiguration::class)
class CraftApiTest { // ... }
That did not help either. It just gave me the second exception mentioned above (the one asking for playerRepository)
I'll try to answer although without seeing the actual code it might not be correct.
So #WebMvcTest loads a "slice" of your application with all the beans annotated with #RestControllers. It doesn't load #Service or #Repository annotated beans.
When you run the test with #WebMvcTest annotation it will load all the controllers, and if, by accident the controller references others than the reference on the service (here I can't say for sure what it is), you might end up loading the stuff that you don't actually need.
Now when you use #WebMvcTest there are two things you can/should do:
Work with MockMvc instead of rest template that queries a web server, its not a full-fledged web layer test anyway.
Try using #WebMvcTest with your controller only:
#WebMvcTest(CraftApisController.class)
Also instead of injecting the real implementation of service, you can use #MockBean so that the real service implementation will be covered by a regular unit test (without spring at all, just plain JUnit/Mockito) and this test could check that your annotations are defined correctly

Spring tries to initialize AutoConfiguration beans using default constructor

We are having issues starting up our Spring Boot Web application. The main problem to properly diagnose the startup is that it only seems to happen in 1% of the startups. In 99% of the startup procedures all works fine and we end up having a properly working spring boot application. However in those 1% of those cases we see issues like this:
WARN o.s.b.w.s.c.AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'errorPageFilterRegistration' defined in org.springframework.boot.web.servlet.support.Error
PageFilterConfiguration: Unsatisfied dependency expressed through method 'errorPageFilterRegistration' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'errorPageFilter' defined in org.springframework.boot.web.servlet.support.ErrorPageFilterConfiguration: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.spring
framework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.boot.autoconfigu
re.web.servlet.error.ErrorMvcAutoConfiguration]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration.<init>() []
For some reason it tries to initialize AutoConfiguration beans by using a default constructor which obviously is not present. There is a constructor present which should be autowired.
Also the AutoConfiguration that is in the stacktrace can be different. Sometimes it is another one like e.g. org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration
Any help or ideas on why this could be happening is appreciated. As this happens very occasionally this is hard to debug as we cannot relyably reproduce. Note that the stacktrace does not contain any custom code. Our application is quite big and we rely mostly on #Configuration classes to do configure the Beans.
Why would spring attempt to initialize an AutoConfiguration bean with a default constructor ?
The errorPageFilterConfiguration source of spring looks like this:
#Configuration(proxyBeanMethods = false)
class ErrorPageFilterConfiguration {
#Bean
ErrorPageFilter errorPageFilter() {
return new ErrorPageFilter();
}
#Bean
FilterRegistrationBean<ErrorPageFilter> errorPageFilterRegistration(ErrorPageFilter filter) {
FilterRegistrationBean<ErrorPageFilter> registration = new FilterRegistrationBean<>(filter);
registration.setOrder(filter.getOrder());
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
return registration;
}
}
According to the stack on creation of the errorPageFilter it is initializing the ErrorMvcAutoConfiguration as a prerequisite ? Why ?
We are not initializing these beans manually. The only relevant code for error page handling that we have is this following:
#Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> webServerFactoryCustomizer() {
return webServerFactory -> {
ErrorPage errorPage = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error");
webServerFactory.addErrorPages(errorPage);
};
}
This is a bug in Spring framework, introduced in version 5.3 in AbstractBeanFactory.
BeanPostProcessorCacheAwareList and accesses to the beanPostProcessors instance are not Thread safe. If multiple Threads are running during initialization and a Thread calls getBeanPostProcessorCache() while another Thread is calling addBeanPostProcessors, you can create a cache which does not contain all BeanPostProcessor instances and thus doesn't find the appropriate constructor.
I will submit a bug for this to spring-framework.
https://github.com/spring-projects/spring-framework/blob/16ea4692bab551800b9ba994ac08099e8acfd6cd/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java#L964
Issue created : https://github.com/spring-projects/spring-framework/issues/29299

Creating A pointcut using args designator with no types results in BeanCurrentlyInCreationException

Using Spring AOP, when attempting to create a Pointcut using the designator args while not providing any types results in a series of exceptions starting with BeanCurrentlyInCreationException
The Example
object _001_Spring_AOP_Pointcut_Args_NoArgs {
open class BeanA {
open fun m() {
println("BeanA#m()")
}
}
#Aspect
class AspectA {
#Pointcut("args()")
private fun pc_noArgs() = Unit
#After("sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs.AspectA.pc_noArgs()")
private fun ac_noArgs() = println("ac_noArgs")
}
#Configuration
#EnableAspectJAutoProxy(proxyTargetClass = true)
open class Config {
#Bean
open fun beanA(): BeanA = BeanA()
#Bean
open fun aspectA(): AspectA = AspectA()
}
fun runJava() {
AnnotationConfigApplicationContext(Config::class.java)
}
}
The Run Method
#Test
fun test_run() {
_001_Spring_AOP_Pointcut_Args_NoArgs.runJava()
}
The Exception Summary
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanA' defined in sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$Config: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$BeanA]: Factory method 'beanA' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'aspectA' defined in sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$Config: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs$AspectA]: Factory method 'aspectA' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'aspectA': Requested bean is currently in creation: Is there an unresolvable circular reference?
args() vs. execution(* *())
This is an unusual way of intercepting all methods without parameters. I would rather make it more explicit and use execution(* *()) instead. If you ever migrate from Spring AOP to AspectJ, you will notice that args() matches all kinds of pointcuts there, e.g. call, initialization, preinitialization, staticinitialization, get and constructor calls/executions without parameters.
Pointcut scoping
Here in Spring AOP your problem might be another one, though: Your pointcut is too broad. It matches many joinpoints in Spring beans, also in Spring or third-party classes themselves. So you want to limit the scope of your pointcut, e.g. something like
execution(* *()) && within(my.own.package.**)
When to (not) use fully qualified class names in pointcuts
BTW, if your pointcut is defined in the very same class as the advice using it, it should not be necessary to use a fully qualified class name, i.e. instead of
#After("sero4.spring.z_added._001_Spring_AOP_Pointcut_Args_NoArgs.AspectA.pc_noArgs()")
you could use
#After("pc_noArgs()")
Inline pointcuts
If you have no plans to re-use the same pointcut in other advices, just get rid of #Pointcut and define an inline pointcut such as
#After("execution(* *()) && within(my.own.package.**)")
Advices should be public
While it is OK to define the #Pointcut method as private if you do not refer to it from other classes, the #After advice should be public. It might work in Spring AOP, but is against conventions. Again, if you ever migrate to AspectJ, you will even get a compile error because an AspectJ advice must be public.
The code shared fails with the following exception -
org.springframework.beans.factory.BeanCurrentlyInCreationException
, when the pointcut expression has a scope within the package the aspect class resides.
Example:
Fully qualified names for the beans :
rg.spring.boot.AspectA
rg.spring.boot.bean.BeanA
And a pointcut expression like the following would fail:
#Pointcut("args() && within(rg.spring.boot..*)")
whereas, the following pointcut expression succeeds :
#Pointcut("args() && within(rg.spring.boot.bean..*)")
The exception, as per me, is because the pointcut targets framework methods of the aspect during initialization. To resolve the exception, you may move the bean to a specific package and fine tune the scope of the pointcut expression for that package.

Determine Springs bean instantiation order in Grails 3.3 with GORM 6.1.x

I am using a Grails 3.3 application that uses GORM 6.1.6.RELEASE, Spring-Boot 1.5.4.RELEASE and Spring Core 4.3.9.RELEASE behind the scene. I am trying to declare a Spring bean that get initialized just before Hibernate starts to validate the underlying database schema.
Here is what I like to do. I want to register my Flyway as a Spring bean and inject the dataSource bean into it. In order to have Flyway run before Hibernate starts to validate the current database schema, I add my flyway bean as a dependency onto the sessionFactory bean. The order would be as follows:
dataSource bean
flyway bean
hiberateDatastore bean
GORM 6.1 uses org.grails.orm.hibernate.HibernateDatastore as a Spring bean to initialize the Hibernate ORM and the database. The sessionFactory bean declares the hibernateDatastore#getSessionFactory as factory class.
Therefore the hibernateDatastore always is created first.
What is the way in Grails 3.3 to create a custom Spring bean that has to run after the connection to the database is available but before the Hibernate stuff gets initialized?
In previous versions of Grails 3.x it was possible to declare it in resources.groovy like this.
beans = {
if (Environment.current == Environment.PRODUCTION) {
flyway(Flyway) { bean ->
bean.initMethod = 'migrate'
dataSource = ref('dataSource')
locations = 'classpath:db/h2'
baselineOnMigrate = true
}
BeanDefinition sessionFactoryBeanDef = getBeanDefinition('hibernateDatastore')
if (sessionFactoryBeanDef) {
def dependsOnList = ['flyway'] as Set
if (sessionFactoryBeanDef.dependsOn?.length > 0) {
dependsOnList.addAll(sessionFactoryBeanDef.dependsOn)
}
sessionFactoryBeanDef.dependsOn = dependsOnList as String[]
}
}
}
I don't think Spring provides a visualisation of a 'bean instantion tree' however you could set the log level for org.springframework.beans.factory.support.DefaultListableBeanFactory to DEBUG and you'll get output like this:
Creating shared instance of singleton bean '...fully qualified class name...'
Returning cached instance of singleton bean '...fully qualified class name...'
You could review this log output for beans from the Hibernate namespace.
I presume you'll use the results to declare a DependsOn relationship so just for completeness this would look like:
#Bean
public SomeHibernateClass createHibernate() {
...
}
#Bean
#DependsOn("createHibernate")
public MyClass createMine() {
...
}
Grails 3.3.0 changed the mechanism of the dataSource bean creation. The Grails project lead stated in the related issue:
Previous versions of Grails created the dataSource bean separately from the session factory. We would need to restore this behaviour I guess so the dataSource can be referenced without triggering the creation of the sessionFactory
After upgrading to Grails 3.3.1 the dataSource bean is again available before the session factory gets created. This solves the problem.

spring aop - exception while creating advice around JdbcTemplate methods

I've a web application that uses apache dbcp and spring jdbc to perform database operations on an oracle database. I need to write a performance logger that logs the individual times of each database operation. I tried writing an around advice on all 'execute' methods of org.springframework.jdbc.core.JdbcTemplate but it results in an error when spring gets initialized. The logger class and the exception stacktrace is as follows:-
I also tried to use CGLIB proxies by enabling but it errors out on dao classes that extends from spring's StoredProcedure class and use constructor injection.
#Aspect
public class Logger {
#Around("this(org.springframework.jdbc.core.JdbcTemplate) && execution(* execute(*))")
public Object invoke(ProceedingJoinPoint pjp) throws Throwable {
long time = System.currentTimeMillis();
Object result = pjp.proceed();
LOGGER.debug("time consumed = " + (System.currentTimeMillis() - time));
return result;
}
Exception stacktrace:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'myDao' defined in class path resource [spring/my-dao.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.springframework.jdbc.core.JdbcTemplate]:
Could not convert constructor argument value of type [$Proxy7] to required type [org.springframework.jdbc.core.JdbcTemplate]:
Failed to convert value of type '$Proxy7 implementing org.springframework.jdbc.core.JdbcOperations,org.springframework.beans.factory.InitializingBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised'
to required type 'org.springframework.jdbc.core.JdbcTemplate';
nested exception is
java.lang.IllegalStateException: Cannot convert value of type [$Proxy7 implementing org.springframework.jdbc.core.JdbcOperations,org.springframework.beans.factory.InitializingBean,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised]
to required type [org.springframework.jdbc.core.JdbcTemplate]:
no matching editors or conversion strategy found
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:702)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:196)

Resources