This is a prerelease version.

View latest

Enable SpringAware data structures

You can mark Hazelcast distributed objects with Hazelcast’s @SpringAware annotation. This enables the objects to apply:

  • Bean properties

  • Factory callbacks such as ApplicationContextAware and BeanNameAware

  • Bean post-processing annotations such as InitializingBean and @PostConstruct

Any Hazelcast object can benefit from these features. For more information, see Customizing the Nature of a Bean in the Spring Framework documentation.

Configuration

To enable SpringAware objects:

  1. Configure a HazelcastInstance using the hazelcast namespace as described in Configure Hazelcast in Spring.

  2. Add the <hz:spring-aware /> tag.

Spring-managed properties and fields are always transient.

SpringAware examples

The following examples show how to use the @SpringAware annotation on different objects.

Hazelcast instance

  1. Configure a Hazelcast instance via Spring configuration and define someBean as a bean.

  2. Add <hz:spring-aware /> to Hazelcast configuration to enable @SpringAware.

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:hz="http://www.hazelcast.com/schema/spring"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-3.0.xsd
                    http://www.hazelcast.com/schema/spring
                    http://www.hazelcast.com/schema/spring/hazelcast-spring.xsd">
    
        <context:component-scan base-package="..."/>
    
        <hz:hazelcast id="instance">
            <hz:config>
                <hz:spring-aware />
                <hz:cluster-name name="dev"/>
                <hz:network port="5701" port-auto-increment="false">
                    <hz:join>
                        <hz:multicast enabled="false" />
                        <hz:tcp-ip enabled="true">
                            <hz:members>10.10.1.2, 10.10.1.3</hz:members>
                        </hz:tcp-ip>
                    </hz:join>
                </hz:network>
                ...
            </hz:config>
        </hz:hazelcast>
    
        <bean id="someBean" class="com.hazelcast.examples.spring.SomeBean"
          scope="singleton" />
        ...
    </beans>

IMap

  1. Create a class called SomeValue that contains bean definitions ApplicationContext and SomeBean.

    @SpringAware
    @Component("someValue")
    @Scope("prototype")
    public class SomeValue implements Serializable, ApplicationContextAware {
    
        private transient ApplicationContext context;
        private transient SomeBean someBean;
        private transient boolean init = false;
    
        public void setApplicationContext( ApplicationContext applicationContext )
            throws BeansException {
            context = applicationContext;
        }
    
        @Autowired
        public void setSomeBean( SomeBean someBean)  {
            this.someBean = someBean;
        }
    
        @PostConstruct
        public void init() {
            someBean.doSomethingUseful();
            init = true;
        }
    }
  2. Get SomeValue object from context and put it into the Hazelcast distributed map on the first member.

    HazelcastInstance hazelcastInstance =
        (HazelcastInstance) context.getBean( "instance" );
    SomeValue value = (SomeValue) context.getBean( "someValue" );
    IMap<String, SomeValue> map = hazelcastInstance.getMap( "values" );
    map.put( "key", value );
  3. Read SomeValue object from the Hazelcast distributed map and assert that the init method is called because it is annotated with @PostConstruct.

    HazelcastInstance hazelcastInstance =
        (HazelcastInstance) context.getBean( "instance" );
    IMap<String, SomeValue> map = hazelcastInstance.getMap( "values" );
    SomeValue value = map.get( "key" );
    Assert.assertTrue( value.init );

ExecutorService

  1. Create a callable class called SomeTask that contains bean definitions ApplicationContext and SomeBean.

    @SpringAware
    public class SomeTask
        implements Callable<Long>, ApplicationContextAware, Serializable {
    
        private transient ApplicationContext context;
        private transient SomeBean someBean;
    
        public Long call() throws Exception {
            return someBean.value;
        }
    
        public void setApplicationContext( ApplicationContext applicationContext )
            throws BeansException {
            context = applicationContext;
        }
    
        @Autowired
        public void setSomeBean( SomeBean someBean ) {
            this.someBean = someBean;
        }
    }
  2. Submit SomeTask to two Hazelcast Members and assert that someBean is autowired.

    HazelcastInstance hazelcastInstance =
        (HazelcastInstance) context.getBean( "instance" );
    SomeBean bean = (SomeBean) context.getBean( "someBean" );
    
    Future<Long> f = hazelcastInstance.getExecutorService("executorService")
        .submit(new SomeTask());
    Assert.assertEquals(bean.value, f.get().longValue());
    
    // choose a member
    Member member = hazelcastInstance.getCluster().getMembers().iterator().next();
    
    Future<Long> f2 = (Future<Long>) hazelcast.getExecutorService("executorService")
        .submitToMember(new SomeTask(), member);
    Assert.assertEquals(bean.value, f2.get().longValue());