esanchezros / quickfixj-spring-boot-starter

Spring Boot Starter for QuickFIX/J
Apache License 2.0
125 stars 57 forks source link

problem when trying to migrate form SpringBoot 2.x to 3.x #109

Open koliplus opened 1 year ago

koliplus commented 1 year ago

Hi,

when I try to upgrade SpringBoot in my app, which uses quickfixj-spring-boot-starter (v. 2.14.0) I have the following error:

2023-07-10 10:14:17.650 DEBUG 52708 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : Application failed to start due to an exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'quickfix.SessionSettings' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1812) ~[spring-beans-6.0.4.jar:6.0.4]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1371) ~[spring-beans-6.0.4.jar:6.0.4]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1325) ~[spring-beans-6.0.4.jar:6.0.4]
        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:885) ~[spring-beans-6.0.4.jar:6.0.4]
        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:789) ~[spring-beans-6.0.4.jar:6.0.4]
2023-07-10 10:14:17.650 ERROR 52708 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   :

I try to upgrade SpringBoot from 2.7.6.to 3.0.2.

Could you help me to solve this problem.

Best Regards koliplus

esanchezros commented 1 year ago

Hi @koliplus ,

Was it working with Spring Boot 2.7.6?

Thanks

koliplus commented 1 year ago

Yes, it works with 2.7.6.

esanchezros commented 1 year ago

Could you send a repo with a reproducible example? I haven't notice any issues when I upgraded my projects to 3.x

esanchezros commented 1 year ago

In the examples project there is an example using Spring Boot 3.1.0 which works fine. I have changed the version to 3.0.2 to see if there was any issue but seems to also work fine. Here are the logs:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.2)

2023-07-11 10:29:00.263  INFO 21261 --- [           main] i.a.q.s.b.s.examples.client.AppClient    : Starting AppClient using Java 17.0.1 with PID 21261 (/home/eduardo/dev/projects/quickfixj-spring-boot-starter-examples/simple-client-spring-3/target/classes started by eduardo in /home/eduardo/dev/projects/quickfixj-spring-boot-starter-examples)
2023-07-11 10:29:00.265  INFO 21261 --- [           main] i.a.q.s.b.s.examples.client.AppClient    : No active profile set, falling back to 1 default profile: "default"
2023-07-11 10:29:00.985  INFO 21261 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8081 (http)
2023-07-11 10:29:00.992  INFO 21261 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-07-11 10:29:00.992  INFO 21261 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.5]
2023-07-11 10:29:01.044  INFO 21261 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-07-11 10:29:01.044  INFO 21261 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 748 ms
2023-07-11 10:29:01.166  INFO 21261 --- [           main] i.a.q.s.b.s.c.SessionSettingsLocator     : Loading settings from 'classpath:quickfixj-client.cfg'
2023-07-11 10:29:03.760  INFO 21261 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 1 endpoint(s) beneath base path '/actuator'
2023-07-11 10:29:03.798  INFO 21261 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8081 (http) with context path ''
2023-07-11 10:29:03.799  INFO 21261 --- [           main] i.a.q.s.b.s.connection.ConnectorManager  : start: Starting ConnectorManager
2023-07-11 10:29:03.841  INFO 21261 --- [           main] quickfix.DefaultSessionSchedule          : [FIXT.1.1:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:03.848  INFO 21261 --- [           main] i.a.q.s.b.s.e.c.ClientApplicationAdapter : onCreate: SessionId=FIXT.1.1:BANZAI->EXEC
2023-07-11 10:29:03.866  INFO 21261 --- [           main] quickfix.DefaultSessionSchedule          : [FIX.4.2:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:03.867  INFO 21261 --- [           main] i.a.q.s.b.s.e.c.ClientApplicationAdapter : onCreate: SessionId=FIX.4.2:BANZAI->EXEC
2023-07-11 10:29:03.872  INFO 21261 --- [           main] quickfix.DefaultSessionSchedule          : [FIX.4.0:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:03.873  INFO 21261 --- [           main] i.a.q.s.b.s.e.c.ClientApplicationAdapter : onCreate: SessionId=FIX.4.0:BANZAI->EXEC
2023-07-11 10:29:03.881  INFO 21261 --- [           main] quickfix.DefaultSessionSchedule          : [FIX.4.1:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:03.882  INFO 21261 --- [           main] i.a.q.s.b.s.e.c.ClientApplicationAdapter : onCreate: SessionId=FIX.4.1:BANZAI->EXEC
2023-07-11 10:29:03.902  INFO 21261 --- [           main] quickfix.DefaultSessionSchedule          : [FIX.4.3:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:03.903  INFO 21261 --- [           main] i.a.q.s.b.s.e.c.ClientApplicationAdapter : onCreate: SessionId=FIX.4.3:BANZAI->EXEC
2023-07-11 10:29:03.929  INFO 21261 --- [           main] quickfix.DefaultSessionSchedule          : [FIX.4.4:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:03.929  INFO 21261 --- [           main] i.a.q.s.b.s.e.c.ClientApplicationAdapter : onCreate: SessionId=FIX.4.4:BANZAI->EXEC
2023-07-11 10:29:03.935  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketTcpNoDelay=true
2023-07-11 10:29:03.935  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWrites=false
2023-07-11 10:29:03.935  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWriteTimeout=30000
2023-07-11 10:29:03.954  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketTcpNoDelay=true
2023-07-11 10:29:03.954  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWrites=false
2023-07-11 10:29:03.954  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWriteTimeout=30000
2023-07-11 10:29:03.955  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketTcpNoDelay=true
2023-07-11 10:29:03.955  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWrites=false
2023-07-11 10:29:03.955  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWriteTimeout=30000
2023-07-11 10:29:03.956  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketTcpNoDelay=true
2023-07-11 10:29:03.956  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWrites=false
2023-07-11 10:29:03.956  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWriteTimeout=30000
2023-07-11 10:29:03.956  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketTcpNoDelay=true
2023-07-11 10:29:03.956  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWrites=false
2023-07-11 10:29:03.956  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWriteTimeout=30000
2023-07-11 10:29:03.957  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketTcpNoDelay=true
2023-07-11 10:29:03.957  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWrites=false
2023-07-11 10:29:03.957  INFO 21261 --- [           main] quickfix.mina.NetworkingOptions          : Socket option: SocketSynchronousWriteTimeout=30000
2023-07-11 10:29:03.958  INFO 21261 --- [           main] quickfix.SocketInitiator                 : SessionTimer started
2023-07-11 10:29:03.960  INFO 21261 --- [ssage Processor] quickfix.SocketInitiator                 : Started QFJ Message Processor
2023-07-11 10:29:03.972  INFO 21261 --- [           main] i.a.q.s.b.s.examples.client.AppClient    : Started AppClient in 4.163 seconds (process running for 4.785)
2023-07-11 10:29:04.106  INFO 21261 --- [on(5)-127.0.0.1] quickfix.DefaultSessionSchedule          : [FIX.4.3:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:04.107  INFO 21261 --- [on(5)-127.0.0.1] quickfix.DefaultSessionSchedule          : [FIX.4.4:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:04.107  INFO 21261 --- [on(5)-127.0.0.1] quickfix.DefaultSessionSchedule          : [FIXT.1.1:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:04.108  INFO 21261 --- [on(5)-127.0.0.1] quickfix.DefaultSessionSchedule          : [FIX.4.2:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:04.108  INFO 21261 --- [on(5)-127.0.0.1] quickfix.DefaultSessionSchedule          : [FIX.4.0:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
2023-07-11 10:29:04.109  INFO 21261 --- [on(5)-127.0.0.1] quickfix.DefaultSessionSchedule          : [FIX.4.1:BANZAI->EXEC] daily, 00:00:00-UTC - 00:00:00-UTC
koliplus commented 1 year ago

I followed your lead as in the example you pointed out. When I changed quickfixj-spring-boot-starter to 2.15.4 and Spring Boot to 3.0.2 then dependency in pom (to quickfixj-spring-boot-starter, quickfixj-spring-boot-actuator) as in quickfixj- spring-boot-starter-examples v.2.15.5-SNAPSHOT - this error with 'quickfix.SessionSettings' stopped appearing. But yet another one appeared:

2023-07-11 13:48:33.264 DEBUG 63956 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : Application failed to start due to an exception
org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'clientMessageStoreFactory' defined in pl.nnn.nnn.microservice.nnn.nnn.AphelionSpringBootClient: Cannot regis
ter bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=aphelionSpringBootClient; factoryMethodName=clientMessa
geStoreFactory; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in pl.nnn.nnn.microservice.nnn.nnn.AphelionSpringBootClient] for bean 'clientMessageStoreFactory' since there is already [Root bean: class 
[null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=io.allune.quickfixj.spring.boot.starter.configuration.client.QuickFixJClientConfiguration$Mem
oryMessageStoreFactoryConfiguration; factoryMethodName=clientMessageStoreFactory; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in io.allune.quickfixj.spring.boot.starter.configuration.client.QuickFixJClientConfiguration$MemoryMessageStoreFactoryConfiguration] bound.
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition(DefaultListableBeanFactory.java:1003) ~[spring-beans-6.0.4.jar:6.0.4]
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:277) ~[spring-context-6.0.4.jar:6.0.4]
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:144) ~[spring-context-6.0.4.jar:6.0.4]
        at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:120) ~[spring-context-6.0.4.jar:6.0.4]
        at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:410) ~[spring-context-6.0.4.jar:6.0.4]
2023-07-11 13:48:33.269 ERROR 63956 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

... in my app I use JdbcStoreFactory as MessageStoreFactory:

    @Bean
    public MessageStoreFactory clientMessageStoreFactory(SessionSettings clientSessionSettings, DataSource dataSource) {
        JdbcStoreFactory jdbcStoreFactory = new JdbcStoreFactory(clientSessionSettings);
        jdbcStoreFactory.setDataSource(dataSource);
        return jdbcStoreFactory;
    }
esanchezros commented 1 year ago

I think you need to explicitly tell Spring to allow bean overriding:

spring:
  main:
    allow-bean-definition-overriding: true
esanchezros commented 1 year ago

@koliplus, any update on this issue?

koliplus commented 1 year ago

You are all right, it works with allow-bean-definition-overriding: true and when I use DependsOn annotation on some beans

But, I am not sure, is this a good way ... As we know, usage of allow-bean-definition-overriding: true is not recommended regarding to unexpected results: it is difficult to investigate which bean was the last one and which overrided others (Previously I worked based on quickfixj-spring-boot-starter-examples version 2.12.0-SNAPSHOT and spring-boot 2.x, which didn't require usage allow-bean-definition-overriding: true)

I have situation that spring-boot create beans from quickfixj-spring-boot-starter-examples library earlier than beans from my implementation of these so (I think) annotation like ConditionalOnMissingBean has no chance to work

Maybe is this possible to avoid creation of beans like "clientMessageStoreFactory" etc. internally by QuickFixJClientAutoConfiguration if they are implemented (as custom) outside of "quickfixj.spring.boot.starter" ?

esanchezros commented 1 year ago

The default behaviour was changed in Spring Boot 3, the BeanDefinitionOverrideException was introduced to allow developers to automatically throw the exception to prevent any unexpected bean overriding. The Spring Boot starter makes an effort to autoconfigure as many QuickFixJ dependencies as possible, allowing developers to override any bean in particular if necessary. I'll have a look at other ways of achieving the same thing without having to set this property to true. Thanks

koliplus commented 1 year ago

If I may suggest something. Assuming the developer knows what he's doing, he replaces the default MessageStore beans that would be created by quickfixj-spring-boot-starter, with his implementations. I imagine if there was an option in the springboot-starter configuration given e.g. in application.yml that: a.) would completely disable the creation of MessageStore related beans by quickfixj-spring-boot-starter (maybe an additional condition in @ConditionalOnProperty or using @ConditionalOnExpression) b.) would force the developer to create a custom implementation(s) of these beans (there would be an exception if the necessary implementation did not exist) then, imho, it should be better, overriding beans will not be needed.

esanchezros commented 1 year ago

Hi @koliplus I think that would be quite a nice feature, for example:

quickfixj.server.override-log-factory=true

would not create the LogFactory bean (default set to screen). Same for the other beans created by the starter:

quickfixj.server.override-session-settings=true
quickfixj.server.override-application=true
quickfixj.server.override-message-store-factory=true
quickfixj.server.override-acceptor=true
quickfixj.server.override-executor-factory=true
quickfixj.server.override-executor=true

but this still won't stop developers from using allow-bean-definition-overriding=true

Let me play with this idea.