sample.GemFireClientServerReadyBeanPostProcessor.java Source code

Java tutorial

Introduction

Here is the source code for sample.GemFireClientServerReadyBeanPostProcessor.java

Source

/*
 * Copyright 2014-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package sample;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.geode.cache.Region;
import org.apache.geode.cache.client.Pool;
import org.apache.geode.cache.client.PoolManager;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.management.membership.ClientMembership;
import org.apache.geode.management.membership.ClientMembershipEvent;
import org.apache.geode.management.membership.ClientMembershipListenerAdapter;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
import org.springframework.util.Assert;

public class GemFireClientServerReadyBeanPostProcessor implements BeanPostProcessor {

    private static final long DEFAULT_TIMEOUT = TimeUnit.SECONDS.toMillis(60);

    private static final CountDownLatch LATCH = new CountDownLatch(1);

    private static final String GEMFIRE_DEFAULT_POOL_NAME = "DEFAULT";

    static {
        ClientMembership.registerClientMembershipListener(new ClientMembershipListenerAdapter() {
            @Override
            public void memberJoined(ClientMembershipEvent event) {
                LATCH.countDown();
            }
        });
    }

    @Value("${spring.session.data.gemfire.port:${application.gemfire.client-server.port}}")
    private int port;

    @Value("${application.gemfire.client-server.host:localhost}")
    private String host;

    private final AtomicBoolean checkGemFireServerIsRunning = new AtomicBoolean(true);
    private final AtomicReference<Pool> gemfirePool = new AtomicReference<Pool>(null);

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (shouldCheckWhetherGemFireServerIsRunning(bean, beanName)) {
            try {
                validateCacheClientNotified();
                validateCacheClientSubscriptionQueueConnectionEstablished();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }

        return bean;
    }

    private boolean shouldCheckWhetherGemFireServerIsRunning(Object bean, String beanName) {
        return (isGemFireRegion(bean, beanName) ? this.checkGemFireServerIsRunning.compareAndSet(true, false)
                : whenGemFirePool(bean, beanName));
    }

    private boolean isGemFireRegion(Object bean, String beanName) {
        return (GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME.equals(beanName)
                || bean instanceof Region);
    }

    private boolean whenGemFirePool(Object bean, String beanName) {
        if (bean instanceof Pool) {
            this.gemfirePool.compareAndSet(null, (Pool) bean);
        }

        return false;
    }

    private void validateCacheClientNotified() throws InterruptedException {
        boolean didNotTimeout = LATCH.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);

        Assert.state(didNotTimeout, String.format("GemFire Cache Server failed to start on host [%s] and port [%d]",
                this.host, this.port));
    }

    @SuppressWarnings("all")
    private void validateCacheClientSubscriptionQueueConnectionEstablished() throws InterruptedException {
        boolean cacheClientSubscriptionQueueConnectionEstablished = false;

        Pool pool = defaultIfNull(this.gemfirePool.get(), GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME,
                GEMFIRE_DEFAULT_POOL_NAME);

        if (pool instanceof PoolImpl) {
            long timeout = (System.currentTimeMillis() + DEFAULT_TIMEOUT);

            while (System.currentTimeMillis() < timeout && !((PoolImpl) pool).isPrimaryUpdaterAlive()) {

                synchronized (pool) {
                    TimeUnit.MILLISECONDS.timedWait(pool, 500L);
                }

            }

            cacheClientSubscriptionQueueConnectionEstablished |= ((PoolImpl) pool).isPrimaryUpdaterAlive();
        }

        Assert.state(cacheClientSubscriptionQueueConnectionEstablished,
                String.format(
                        "Cache client subscription queue connection not established; GemFire Pool was [%s];"
                                + " GemFire Pool configuration was [locators = %s, servers = %s]",
                        pool, pool.getLocators(), pool.getServers()));
    }

    private Pool defaultIfNull(Pool pool, String... poolNames) {
        for (String poolName : poolNames) {
            pool = (pool != null ? pool : PoolManager.find(poolName));
        }

        return pool;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}
// tag::end[]