You can't just inject the created Ignite bean in your application beans. The
official documentation mentions the IgniteSpringBean, however it can't be used
either, because there is a race condition inside that class.
In order to use the Ignite instance in my beans I have extended the
IgniteSpringBean class the following way (two classes):
/**
* It is quite complex to explain the reason I have added this class.
* Basically there is a race between the {@link
Service#execute(ServiceContext)},
* Ignite initialization event {@link LifecycleEventType#AFTER_NODE_START} and
{@link IgniteSpringBean}.
*/
public class CustomizedIgniteSpringBean extends IgniteSpringBean {
private static final long serialVersionUID = 2884332981397959158L;
private final NodeInitializationWaiter initializationWaiter;
public CustomizedIgniteSpringBean(NodeInitializationWaiter
initializationWaiter) {
this.initializationWaiter = initializationWaiter;
}
@Override
public void afterSingletonsInstantiated() {
super.afterSingletonsInstantiated();
initializationWaiter.onIgniteSpringBeanInitialized();
}
}
/**
* Oftentimes, we would like to execute some runnable or execute some cache
operation
* just from the {@link Service#execute(ServiceContext)} method.
* Ignite, unfortunately, can fail if we are working with IgniteSpringBean and
are executing
* some cache operation, using a bean that has an Ignite instance injected by
Spring. In that
* case an {@link IllegalStateException} exception may be thrown, warning us
that we should
* not use from Spring bean init methods like @PostConstruct. Probably this is
a bug, but
* we have to somehow workaround it.
* So this waiter allows services to wait until the grid node becomes fully
functional and
* invoke some code afterwards.
*/
public class NodeInitializationWaiter implements LifecycleBean, DisposableBean {
private static final Set<LifecycleEventType> INITIALIZED_STATE_TYPES =
EnumSet.of(
LifecycleEventType.AFTER_NODE_START,
LifecycleEventType.BEFORE_NODE_STOP,
LifecycleEventType.AFTER_NODE_STOP);
@LoggerResource(categoryClass = NodeInitializationWaiter.class)
private transient IgniteLogger logger;
/**
* Current node state
*/
private volatile LifecycleEventType nodeState;
/**
* A flag that determines if {@link IgniteSpringBean} has been initialized
*/
private volatile boolean springBeanInitialized;
/**
* Determines if this bean should
*/
private volatile boolean cancelled;
@Override
public synchronized void onLifecycleEvent(LifecycleEventType evt) throws
IgniteException {
nodeState = evt;
notifyAll();
}
/**
* @see CustomizedIgniteSpringBean
*/
public synchronized void onIgniteSpringBeanInitialized() {
springBeanInitialized = true;
notifyAll();
}
/**
* Wait until the grid node is initialized
*/
public void waitUntilInitialized() {
while (!cancelled && !isInitialized()) {
synchronized (this) {
if (!cancelled && !isInitialized()) {
try {
wait();
} catch (InterruptedException e) {
logger.warning("Interrupted", e);
}
}
}
}
}
private boolean isInitialized() {
return INITIALIZED_STATE_TYPES.contains(nodeState) &&
springBeanInitialized;
}
@Override
public void destroy() throws Exception {
cancelled = true;
}
}
Then you will be able to wait in your beans for Ignite to be fully initialized.
Best regards,
Ivan Fedorenkov
On 10/14/20, 6:14 PM, "mweiss" <[email protected]> wrote:
yes
--
Sent from:
https://urldefense.com/v3/__http://apache-ignite-users.70518.x6.nabble.com/__;!!PNmPxbqrAcYR!yG9-oziWdJlTTpyUz0L5CDBdO2a5a3BfH8PdrQqoww8V1ZlNoaBXdlGMoMSfs_SN_LjNGbr0Xg$