Spring Managed Context in ExecutorService

1,186 views
Skip to first unread message

Volkan Yazıcı

unread,
Jun 28, 2012, 6:07:49 AM6/28/12
to haze...@googlegroups.com
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;

@SpringAware
public 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 omitted

What 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.)

Volkan Yazıcı

unread,
Jun 28, 2012, 6:38:18 AM6/28/12
to haze...@googlegroups.com
Oops! Adding <context:annotation-config/> at the bottom of spring/context.xml solved the problem. (Sorry for the mess, I have never used Spring annotations before and I have been struggling the solve this problem since 2 days.) But my 2nd question stands still: Can I make the same configuration using spring/context.xml, instead of using annotations.
Reply all
Reply to author
Forward
0 new messages