I see that with a change introduced in 2.4 in IgniteSpringBean to delay ignite instance start until all other spring beans are initialized may have broken Ignite SpringTransactionManager resulting in inability to configure it for Spring transaction abstraction of Ignite transactions. I really, badly need to find a way to work around this. Any ideas/suggestions anyone?
Below is the line from IgniteSpringBean java doc "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. "
The problem is since SpringTransactionManager implements org.springframework.beans.factory.InitializingBean & in the afterPropertiesSet() call that spring calls it tries to look for the igniteInstanceName that's specified but since the instance is started only AFTER all other Spring beans have been initialized, it fails with IgniteIllegalStateException,
Please see below stack trace,
lass]: Invocation of init method failed; nested exception is class org.apache.ignite.IgniteIllegalStateException: Ignite instance with provided name doesn't exist. Did you call Ignition.start(..) to start an Ignite instance? [name=ObjectManagerGrid] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122) at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) at com.brocade.dcm.Application.main(Application.java:63) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48) at org.springframework.boot.loader.Launcher.launch(Launcher.java:87) at org.springframework.boot.loader.Launcher.launch(Launcher.java:50) at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51) Caused by: org.apache.ignite.IgniteIllegalStateException: Ignite instance with provided name doesn't exist. Did you call Ignition.start(..) to start an Ignite instance? [name=ObjectManagerGrid] at org.apache.ignite.internal.IgnitionEx.grid(IgnitionEx.java:1376) at org.apache.ignite.Ignition.ignite(Ignition.java:530) at org.apache.ignite.transactions.spring.SpringTransactionManager.afterPropertiesSet(SpringTransactionManager.java:357) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ... 22 common frames omitted
Thanks
For other facing this issue, as commented by Dennis (@dmagda) it has been fixed with this ticket, https://issues.apache.org/jira/browse/IGNITE-8740 & will be available in 2.6.
In the meanwhile what i did to work around this is to hack the injection this way in a configuration 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;
}
}