Hi!
I have a project composed of OSGi bundles and Spring beans. (That is, application itself is already running on top of Spring beans residing in the OSGi bundles.) In order to create an abstraction layer for the distributed execution mechanics (which is empowered by Hazelcast) I create a DistributedContext bean as follows.
public final class DistributedContext implements MembershipListener { private HazelcastInstance hazelcast; ... public <T> T remoteCall(Callable<T> callable, Member member) throws InterruptedException, ExecutionException { FutureTask<T> task = new DistributedTask<T>(callable, member); ExecutorService executorService = hazelcast.getExecutorService(); executorService.execute(task); return task.get(); } ...}I am using below
spring/context.xml lines to inject
hazelcast into
DistributedContext.
<hz:hazelcast id="hazelcast"> <hz:config> <hz:group name="cluster" password="so-long-loser" /> <hz:network port="5701" port-auto-increment="false"> <hz:interfaces enabled="true"> <hz:interface>192.168.1.98</hz:interface> </hz:interfaces> </hz:network> </hz:config></hz:hazelcast><bean id="distributedContext" class="cluster.DistributedContext"> <property name="hazelcast" ref="hazelcast" /></bean>I have a
Callable that I want to invoke on some particular Hazelcast member as follows.
import org.springframework.beans.factory.annotation.Autowired;import com.hazelcast.spring.context.SpringAware;@SpringAwarepublic class MoveCall implements Callable<Boolean>, Serializable { private static final long serialVersionUID = -5311091366011857032L; private transient ControllerOperator controllerOperator; public final long orgId; public MoveCall(long orgId) { this.orgId = orgId; } @Override public Boolean call() throws Exception { return controllerOperator.move(this); } @Autowired public void setControllerOperator(ControllerOperator controllerOperator) { this.controllerOperator = controllerOperator; }}If I get from the
Hazelcast Spring Managed Context documentation right,
@SpringAware tells remote
ExecutorService receiver to first render this
MoveCall within the Spring context, and then due to
@Autowired, Spring context will bind the remote
controllerOperator bean into the received
MoveCall. (Right?) The problem is, this simply doesn't work. The invoker receives below exception, where
MoveCall.java:35 points to line
controllerOperator.move(this).
java.util.concurrent.ExecutionException: java.lang.NullPointerException at com.hazelcast.core.DistributedTask.get(DistributedTask.java:126) ~[hazelcast-2.1.2.jar:2.1.2] at cluster.DistributedContext.remoteCall(DistributedContext.java:50) ~[cluster_1.0.0.jar:na] at cluster.ControllerOperator.replaceMapping(ControllerOperator.java:497) [cluster_1.0.0.jar:na] at cluster.ControllerOperator.ensureMapping(ControllerOperator.java:373) [cluster_1.0.0.jar:na] at cluster.ControllerOperator.check(ControllerOperator.java:308) [cluster_1.0.0.jar:na] at cluster.ControllerOperator.access$1(ControllerOperator.java:306) [cluster_1.0.0.jar:na] at cluster.ControllerOperator$1.run(ControllerOperator.java:44) [cluster_1.0.0.jar:na] at java.lang.Thread.run(Thread.java:662) [na:1.6.0_30]java.lang.NullPointerException: null at cluster.MoveCall.call(MoveCall.java:35) ~[cluster_1.0.0.jar:na] at cluster.MoveCall.call(MoveCall.java:1) ~[cluster_1.0.0.jar:na] at com.hazelcast.impl.ExecutorManager$RequestExecutor.run(ExecutorManager.java:224) ~[hazelcast-2.1.2.jar:2.1.2] at com.hazelcast.impl.executor.ParallelExecutorService$ParallelExecutorImpl$ExecutionSegment.run(ParallelExecutorService.java:212) ~[hazelcast-2.1.2.jar:2.1.2] at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) ~[na:1.6.0_30] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) ~[na:1.6.0_30] at java.lang.Thread.run(Thread.java:662) [na:1.6.0_30] at com.hazelcast.impl.ExecutorThreadFactory$1.run(ExecutorThreadFactory.java:38) ~[hazelcast-2.1.2.jar:2.1.2]Caused by: java.lang.NullPointerException: null ... 8 common frames omittedWhat might I have been missing? Can I make the same configuration using
spring/context.xml, instead of using annotations. (Because, I have never used annotations for Spring stuff.)