All Downloads are FREE. Search and download functionalities are using the official Maven repository.

codes.sf.springboot.grpc.client.context.GrpcStubFactoryBean Maven / Gradle / Ivy

package codes.sf.springboot.grpc.client.context;

import codes.sf.springboot.grpc.client.GrpcChannelSource;
import codes.sf.springboot.grpc.client.autoconfigure.GrpcClientAutoConfiguration;
import codes.sf.springboot.grpc.client.stubpostprocess.GenericGrpcStubPostProcessor;
import io.grpc.stub.AbstractStub;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.util.MethodInvoker;

import java.util.List;

import static java.util.Arrays.asList;

/**
 * {@link FactoryBean} for instantiating gRPC stubs from static classes
 * generated by the
 * 
 * gRPC Java Protobuf Compiler
 * .
 *
 * 

These static factory classes follow a consistent pattern where each * stub type is instantiated with static function: *

    *
  • {@code .newXyzStub(Channel)}
  • *
  • {@code .newXyzFutureStub(Channel)}
  • *
  • {@code .newXyzBlockingStub(Channel)}
  • *
* where Xyz is the stub service name. This factory invokes * the appropriate static function via reflection. * * @param the gRPC stub type this factory produces * @author Semyon Fishman * @since 0.0.1 */ class GrpcStubFactoryBean> implements FactoryBean { // Order matters! private static final List STUB_SUFFIXES = asList("BlockingStub", "FutureStub", "Stub"); private final String factoryClassName; private final Class stubClass; private GrpcChannelSource channelSource; private List postProcessors; public GrpcStubFactoryBean(String factoryClassName, Class stubClass) { this.factoryClassName = factoryClassName; this.stubClass = stubClass; } @Required public void setChannelSource(GrpcChannelSource channelSource) { this.channelSource = channelSource; } @Required @Qualifier(GrpcClientAutoConfiguration.GENERIC_GRPC_STUB_POST_PROCESSORS_BEAN_NAME) public void setGrpcStubPostProcessors(List postProcessors) { this.postProcessors = postProcessors; } @Override public boolean isSingleton() { return true; } @Override @SuppressWarnings("unchecked") public S getObject() throws Exception { String suffix = STUB_SUFFIXES.stream() .filter(s -> stubClass.getCanonicalName().endsWith(s)) .findFirst() .get(); MethodInvoker methodInvoker = new MethodInvoker(); methodInvoker.setStaticMethod(factoryClassName + ".new" + suffix); methodInvoker.setArguments(channelSource.resolve(stubClass)); methodInvoker.prepare(); S stub = (S) methodInvoker.invoke(); for (GenericGrpcStubPostProcessor processor : postProcessors) { if (processor.supportsStubType(stub.getClass())) stub = (S) processor.postProcess(stub); } return stub; } @Override public Class getObjectType() { return stubClass; } }