com.quancheng.saluki.boot.runner.GrpcServiceRunner.java Source code

Java tutorial

Introduction

Here is the source code for com.quancheng.saluki.boot.runner.GrpcServiceRunner.java

Source

/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the
 * confidential and proprietary information of Quancheng-ec.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Quancheng-ec.com.
 */
package com.quancheng.saluki.boot.runner;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.type.StandardMethodMetadata;
import org.springframework.util.ClassUtils;

import com.google.common.collect.Sets;
import com.quancheng.saluki.boot.SalukiService;
import com.quancheng.saluki.boot.autoconfigure.GrpcProperties;
import com.quancheng.saluki.boot.common.GrpcAopUtils;
import com.quancheng.saluki.boot.service.HealthImpl;
import com.quancheng.saluki.core.config.RpcServiceConfig;
import com.quancheng.saluki.service.Health;

/**
 * @author shimingliu 20161216 ?5:07:16
 * @version ThrallServiceRunner.java, v 0.0.1 20161216 ?5:07:16 shimingliu
 */
public class GrpcServiceRunner implements DisposableBean, CommandLineRunner {

    private final GrpcProperties thrallProperties;

    @Value("${spring.application.name}")
    private String applicationName;

    @Value("${server.port}")
    private int httpPort;

    @Autowired
    private AbstractApplicationContext applicationContext;

    private RpcServiceConfig rpcService;

    public GrpcServiceRunner(GrpcProperties thrallProperties) {
        this.thrallProperties = thrallProperties;
    }

    @Override
    public void destroy() throws Exception {
        if (rpcService != null) {
            rpcService.destroy();
        }
        if (applicationContext != null) {
            applicationContext.destroy();
        }
    }

    @Override
    public void run(String... arg0) throws Exception {
        System.out.println("Starting GRPC Server ...");
        RpcServiceConfig rpcSerivceConfig = new RpcServiceConfig();
        this.addRegistyAddress(rpcSerivceConfig);
        rpcSerivceConfig.setApplication(applicationName);
        this.addHostAndPort(rpcSerivceConfig);
        rpcSerivceConfig.setMonitorinterval(thrallProperties.getMonitorinterval());
        Collection<Object> instances = getTypedBeansWithAnnotation(SalukiService.class);
        if (instances.size() > 0) {
            try {
                for (Object instance : instances) {
                    SalukiService serviceAnnotation = instance.getClass().getAnnotation(SalukiService.class);
                    String serviceName = serviceAnnotation.service();
                    Set<String> serviceNames = Sets.newHashSet();
                    Object target = instance;
                    if (StringUtils.isBlank(serviceName)) {
                        if (this.isGrpcServer(instance)) {
                            throw new java.lang.IllegalArgumentException(
                                    "you use grpc stub service,must set service name,service instance is"
                                            + instance);
                        } else {
                            target = GrpcAopUtils.getTarget(target);
                            Class<?>[] interfaces = ClassUtils.getAllInterfacesForClass(target.getClass());
                            for (Class<?> interfaceClass : interfaces) {
                                String interfaceName = interfaceClass.getName();
                                if (StringUtils.startsWith(interfaceName, "com.quancheng")) {
                                    serviceNames.add(interfaceName);
                                }
                            }
                        }
                    } else {
                        serviceNames.add(serviceName);
                    }
                    for (String realServiceName : serviceNames) {
                        rpcSerivceConfig.addServiceDefinition(realServiceName, getGroup(serviceAnnotation),
                                getVersion(serviceAnnotation), instance);
                    }
                }
            } finally {
                Object healthInstance = new HealthImpl(applicationContext);
                BeanDefinitionRegistry beanDefinitonRegistry = (BeanDefinitionRegistry) applicationContext
                        .getBeanFactory();
                BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder
                        .genericBeanDefinition(Health.class);
                beanDefinitonRegistry.registerBeanDefinition(Health.class.getName(),
                        beanDefinitionBuilder.getRawBeanDefinition());
                applicationContext.getBeanFactory().registerSingleton(Health.class.getName(), healthInstance);
                String group = thrallProperties.getGroup() != null ? thrallProperties.getGroup() : "default";
                String version = thrallProperties.getVersion() != null ? thrallProperties.getVersion() : "1.0.0";
                rpcSerivceConfig.addServiceDefinition(Health.class.getName(), group, version, healthInstance);
            }
        }
        this.rpcService = rpcSerivceConfig;
        rpcSerivceConfig.export();
        System.out.println(String.format("GRPC server has started!You can do test by %s \n %s",
                "http://localhost:" + httpPort + "/doc", "http://saluki.dev.quancheng-ec.com"));
    }

    private void addHostAndPort(RpcServiceConfig rpcSerivceConfig) {
        rpcSerivceConfig.setRealityRpcPort(getRealityRpcPort());
        rpcSerivceConfig.setRegistryRpcPort(thrallProperties.getRegistryRpcPort());
        rpcSerivceConfig.setHost(thrallProperties.getHost());
        rpcSerivceConfig.setHttpPort(thrallProperties.getRegistryHttpPort());
    }

    private void addRegistyAddress(RpcServiceConfig rpcSerivceConfig) {
        String registryAddress = thrallProperties.getRegistryAddress();
        if (StringUtils.isBlank(registryAddress)) {
            throw new java.lang.IllegalArgumentException("registry address can not be null or empty");
        } else {
            String[] registryHostAndPort = StringUtils.split(registryAddress, ":");
            if (registryHostAndPort.length < 2) {
                throw new java.lang.IllegalArgumentException("the pattern of registry address is host:port");
            }
            rpcSerivceConfig.setRegistryAddress(registryHostAndPort[0]);
            rpcSerivceConfig.setRegistryPort(Integer.valueOf(registryHostAndPort[1]));
        }
    }

    private int getRealityRpcPort() {
        int rpcPort = thrallProperties.getRealityRpcPort();
        if (rpcPort == 0) {
            throw new java.lang.IllegalArgumentException("rpcPort can not be null or empty");
        }
        return rpcPort;
    }

    private String getGroup(SalukiService service) {
        if (StringUtils.isNoneBlank(service.group())) {
            return service.group();
        } else {
            String group = thrallProperties.getGroup();
            if (StringUtils.isBlank(group)) {
                throw new java.lang.IllegalArgumentException("group can not be null or empty");
            }
            return group;
        }
    }

    private String getVersion(SalukiService service) {
        if (StringUtils.isNoneBlank(service.version())) {
            return service.version();
        } else {
            String version = thrallProperties.getVersion();
            if (StringUtils.isBlank(version)) {
                throw new java.lang.IllegalArgumentException("version can not be null or empty");
            }
            return version;
        }
    }

    private boolean isGrpcServer(Object instance) {
        if (instance instanceof io.grpc.BindableService) {
            return true;
        } else {
            return false;
        }
    }

    private Collection<Object> getTypedBeansWithAnnotation(Class<? extends Annotation> annotationType)
            throws Exception {
        return Stream.of(applicationContext.getBeanNamesForAnnotation(annotationType)).filter(name -> {
            BeanDefinition beanDefinition = applicationContext.getBeanFactory().getBeanDefinition(name);
            if (beanDefinition.getSource() instanceof StandardMethodMetadata) {
                StandardMethodMetadata metadata = (StandardMethodMetadata) beanDefinition.getSource();
                return metadata.isAnnotated(annotationType.getName());
            }
            return null != applicationContext.getBeanFactory().findAnnotationOnBean(name, annotationType);
        }).map(name -> applicationContext.getBeanFactory().getBean(name)).collect(Collectors.toList());

    }

}