/**
* The first thing to know about are types. The available types in Thrift are:
*
* bool Boolean, one byte
* i8 (byte) Signed 8-bit integer
* i16 Signed 16-bit integer
* i32 Signed 32-bit integer
* i64 Signed 64-bit integer
* double 64-bit floating point value
* string String
* binary Blob (byte array)
* map<t1,t2> Map from one type to another
* list<t1> Ordered list of one type
* set<t1> Set of unique elements of one type
*
* Did you also notice that Thrift supports C style comments?
*//**
* Thrift files can namespace, package, or prefix their output in various
* target languages.
*/namespaceclexamplenamespacecppexamplenamespacedexamplenamespacedartexamplenamespacejavaexamplenamespacephpexamplenamespaceperlexamplenamespacehaxeexamplenamespacenetstdexampleserviceCalculator{i32add(1:i32num1,2:i32num2),}
@Slf4jpublicclassThriftServerimplementsCloseable{privatestaticfinalStringCLASS_NAME_SUFFIX_IFACE="$Iface";privatestaticfinalStringCLASS_NAME_SUFFIX_PROCESSOR="$Processor";privatefinalTMultiplexedProcessormultiplexedProcessor=newTMultiplexedProcessor();privatefinalAtomicBooleanstarted=newAtomicBoolean(false);privateintport;privateTNonblockingServerSocketserverSocket;publicThriftServer(intport){this.port=port;}publicvoidstartServer(){if(!started.compareAndSet(false,true)){return;}try{serverSocket=newTNonblockingServerSocket(port);}catch(TTransportExceptione){log.error("start thrift server",e);thrownewRuntimeException(e);}TThreadedSelectorServer.Argsargs=newTThreadedSelectorServer.Args(serverSocket).processor(multiplexedProcessor);TServerserver=newTThreadedSelectorServer(args);newThread(()->{log.info("start thrift server on port {}",port);server.serve();log.info("stop thrift server on port {}",port);},"thrift-server").start();}publicvoidaddService(Objectservice){Class<?>interfaceClass=findInterfaceClass(service);addProcessor(interfaceClass,service);}privatesynchronizedvoidaddProcessor(Class<?>interfaceClass,Objectservice){StringprocessorClassName=interfaceClass.getName().replace(CLASS_NAME_SUFFIX_IFACE,CLASS_NAME_SUFFIX_PROCESSOR);Class<?>processorClass;try{processorClass=Class.forName(processorClassName,true,interfaceClass.getClassLoader());}catch(ClassNotFoundExceptione){thrownewRuntimeException(e);}TProcessorprocessor=(TProcessor)ReflectUtil.newInstance(processorClass,service);log.info("add thrift interface {}",interfaceClass);multiplexedProcessor.registerProcessor(interfaceClass.getName(),processor);}privatestaticClass<?>findInterfaceClass(Objectservice){Assert.notNull(service);Class<?>clazz=service.getClass();Class<?>interfaceClazz=null;for(Class<?>c:clazz.getInterfaces()){if(c.getName().contains(CLASS_NAME_SUFFIX_IFACE)){interfaceClazz=c;break;}}if(interfaceClazz==null){thrownewIllegalArgumentException("service is not thrift implement object");}returninterfaceClazz;}@Overridepublicvoidclose()throwsIOException{if(serverSocket!=null){serverSocket.close();}}}
publicclassMultiThriftExampleTest{@Testvoidtest1()throwsException{@CleanupThriftServerthriftServer=newThriftServer(9090);thriftServer.addService(newCalculatorHandler());thriftServer.startServer();@CleanupThriftClientthriftClient=newThriftClient("localhost",9090);thriftClient.startClient();Calculator.Clientclient=thriftClient.getClient(Calculator.Iface.class.getName());intsum=client.add(1,2);assertEquals(3,sum);}@Testvoidtest2()throwsTException{startServer();startClient();}privatevoidstartClient()throwsTException{try{TimeUnit.SECONDS.sleep(3);}catch(InterruptedExceptione){thrownewRuntimeException(e);}TTransporttransport=newTSocket("localhost",9090);transport.open();TTransportframedTransport=newTFramedTransport(transport,Integer.MAX_VALUE);TProtocolprotocol=newTBinaryProtocol(framedTransport);TMultiplexedProtocolmultiplexedProtocol=newTMultiplexedProtocol(protocol,Calculator.Iface.class.getName());Calculator.Clientclient=newCalculator.Client(multiplexedProtocol);intadd=client.add(1,2);System.out.println("add: "+add);transport.close();}privatevoidstartServer(){CalculatorHandlerhandler=newCalculatorHandler();Calculator.Processor<CalculatorHandler>processor=newCalculator.Processor<>(handler);TNonblockingServerSocketserverSocket;try{serverSocket=newTNonblockingServerSocket(9090);}catch(TTransportExceptione){thrownewRuntimeException(e);}TMultiplexedProcessormultiplexedProcessor=newTMultiplexedProcessor();multiplexedProcessor.registerProcessor(Calculator.Iface.class.getName(),processor);TServerserver=newTThreadedSelectorServer(newTThreadedSelectorServer.Args(serverSocket).processor(multiplexedProcessor));newThread(()->{System.out.println("Starting the simple server...");server.serve();}).start();}}