IgniteSpringBean 和 Ignite SpringTransactionManager 在 2.4 中不再协同工作
IgniteSpringBean & Ignite SpringTransactionManager do not work together anymore in 2.4
我看到在 IgniteSpringBean 中引入了 2.4 中的更改,以延迟 ignite 实例启动,直到所有其他 spring bean 初始化可能已经破坏 Ignite SpringTransactionManager 导致无法为 Ignite 交易的 Spring 交易抽象配置它。我真的非常需要找到解决这个问题的方法。 ideas/suggestions 有人吗?
下面是 IgniteSpringBean java 文档中的行
"Ignite instance is started after all other Spring beans have been initialized and right before Spring context is refreshed. That implies that it's not valid to reference IgniteSpringBean from any kind of Spring bean init methods like PostConstruct. If it's required to reference IgniteSpringBean for other bean initialization purposes, it should be done from a ContextRefreshedEvent listener method declared in that bean. "
问题是,因为 SpringTransactionManager 在 spring 调用的 afterPropertiesSet() 调用中实现了 org.springframework.beans.factory.InitializingBean & 它会尝试查找指定的 igniteInstanceName,但由于实例仅在 所有其他 Spring beans 已初始化之后启动,它因 IgniteIllegalStateException、
请查看下面的堆栈跟踪,
las]: init方法调用失败;嵌套异常是 class org.apache.ignite.IgniteIllegalStateException:具有提供名称的 Ignite 实例不存在。你调用 Ignition.start(..) 来启动 Ignite 实例了吗? [名称=ObjectManagerGrid]
在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628)
在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
在 org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737)
在 org.springframework.boot.SpringApplication.refresh上下文(SpringApplication.java:370)
在 org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
在 com.brocade.dcm.Application.main(Application.java:63)
在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)
在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
在 java.lang.reflect.Method.invoke(Method.java:498)
在 org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
在 org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
在 org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
在 org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)
原因:org.apache.ignite.IgniteIllegalStateException:具有所提供名称的 Ignite 实例不存在。你调用 Ignition.start(..) 来启动 Ignite 实例了吗? [名称=ObjectManagerGrid]
在 org.apache.ignite.internal.IgnitionEx.grid(IgnitionEx.java:1376)
在 org.apache.ignite.Ignition.ignite(Ignition.java:530)
在 org.apache.ignite.transactions.spring.SpringTransactionManager.afterPropertiesSet(SpringTransactionManager.java:357)
在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
...省略了 22 个公共帧
谢谢
对于其他面临此问题的人,正如 Dennis (@dmagda) 所评论的那样,它已通过此票证得到修复,https://issues.apache.org/jira/browse/IGNITE-8740 并将在 2.6 中提供。
与此同时,我为解决此问题所做的工作是在配置 bean (@Configuration) 中以这种方式破解注入,
/**
* @author mlekshma
*
*/
@Configuration
@ComponentScan("com.***.***")
@EnableIgniteRepositories(basePackages={"com.***.***"})
@ImportResource("classpath:ignite-client-conf.xml")
@EnableTransactionManagement
public class IgniteClientConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(IgniteClientConfig.class);
public IgniteClientConfig() {
}
/**
* @return
*/
@Bean
@DependsOn("igniteInstance")
@Primary
@Lazy
public PlatformTransactionManager transactionManager() {
final SpringTransactionManager springTransactionManager = new SpringTransactionManager() {
@Override
public void afterPropertiesSet() throws Exception {
// Do nothing..
}
/**
* @param event
*/
@EventListener
public void handleContextRefresh(final ContextRefreshedEvent event) throws Exception {
LOGGER.info("Setting up tx support..");
super.afterPropertiesSet();
}
};
// Use default grid client instance created..
springTransactionManager.setTransactionConcurrency(TransactionConcurrency.PESSIMISTIC);
return springTransactionManager;
}
}
我看到在 IgniteSpringBean 中引入了 2.4 中的更改,以延迟 ignite 实例启动,直到所有其他 spring bean 初始化可能已经破坏 Ignite SpringTransactionManager 导致无法为 Ignite 交易的 Spring 交易抽象配置它。我真的非常需要找到解决这个问题的方法。 ideas/suggestions 有人吗?
下面是 IgniteSpringBean java 文档中的行 "Ignite instance is started after all other Spring beans have been initialized and right before Spring context is refreshed. That implies that it's not valid to reference IgniteSpringBean from any kind of Spring bean init methods like PostConstruct. If it's required to reference IgniteSpringBean for other bean initialization purposes, it should be done from a ContextRefreshedEvent listener method declared in that bean. "
问题是,因为 SpringTransactionManager 在 spring 调用的 afterPropertiesSet() 调用中实现了 org.springframework.beans.factory.InitializingBean & 它会尝试查找指定的 igniteInstanceName,但由于实例仅在 所有其他 Spring beans 已初始化之后启动,它因 IgniteIllegalStateException、
请查看下面的堆栈跟踪,
las]: init方法调用失败;嵌套异常是 class org.apache.ignite.IgniteIllegalStateException:具有提供名称的 Ignite 实例不存在。你调用 Ignition.start(..) 来启动 Ignite 实例了吗? [名称=ObjectManagerGrid] 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) 在 org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) 在 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) 在 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) 在 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) 在 org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) 在 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) 在 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) 在 org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) 在 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) 在 org.springframework.boot.SpringApplication.refresh上下文(SpringApplication.java:370) 在 org.springframework.boot.SpringApplication.run(SpringApplication.java:314) 在 com.brocade.dcm.Application.main(Application.java:63) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) 在 org.springframework.boot.loader.Launcher.launch(Launcher.java:87) 在 org.springframework.boot.loader.Launcher.launch(Launcher.java:50) 在 org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) 原因:org.apache.ignite.IgniteIllegalStateException:具有所提供名称的 Ignite 实例不存在。你调用 Ignition.start(..) 来启动 Ignite 实例了吗? [名称=ObjectManagerGrid] 在 org.apache.ignite.internal.IgnitionEx.grid(IgnitionEx.java:1376) 在 org.apache.ignite.Ignition.ignite(Ignition.java:530) 在 org.apache.ignite.transactions.spring.SpringTransactionManager.afterPropertiesSet(SpringTransactionManager.java:357) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) 在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ...省略了 22 个公共帧
谢谢
对于其他面临此问题的人,正如 Dennis (@dmagda) 所评论的那样,它已通过此票证得到修复,https://issues.apache.org/jira/browse/IGNITE-8740 并将在 2.6 中提供。
与此同时,我为解决此问题所做的工作是在配置 bean (@Configuration) 中以这种方式破解注入,
/**
* @author mlekshma
*
*/
@Configuration
@ComponentScan("com.***.***")
@EnableIgniteRepositories(basePackages={"com.***.***"})
@ImportResource("classpath:ignite-client-conf.xml")
@EnableTransactionManagement
public class IgniteClientConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(IgniteClientConfig.class);
public IgniteClientConfig() {
}
/**
* @return
*/
@Bean
@DependsOn("igniteInstance")
@Primary
@Lazy
public PlatformTransactionManager transactionManager() {
final SpringTransactionManager springTransactionManager = new SpringTransactionManager() {
@Override
public void afterPropertiesSet() throws Exception {
// Do nothing..
}
/**
* @param event
*/
@EventListener
public void handleContextRefresh(final ContextRefreshedEvent event) throws Exception {
LOGGER.info("Setting up tx support..");
super.afterPropertiesSet();
}
};
// Use default grid client instance created..
springTransactionManager.setTransactionConcurrency(TransactionConcurrency.PESSIMISTIC);
return springTransactionManager;
}
}