Building Microservices with Spring Boot and Apache Thrift. Part 2. Swifty services
http://bsideup.blogspot.com/2015/04/spring-boot-thrift-part2.html
Few words about Swift. Swift - Java annotation-based generator for Apache Thrift. It's priceless when you develop your APIs in Java and want to expose them to the other world using Apache Thrift.
Protocol
Lets recreate our previous example ( https://github.com/bsideup/spring-boot-thrift ) with it. Start with simple build.gradle file:
| apply plugin: 'java' | |
| apply plugin: 'spring-boot' | |
| buildscript { | |
| repositories { | |
| jcenter() | |
| } | |
| dependencies { | |
| classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.1.RELEASE") | |
| } | |
| } | |
| repositories { | |
| jcenter() | |
| } | |
| sourceCompatibility = 1.8 | |
| targetCompatibility = 1.8 | |
| dependencies { | |
| compile "org.projectlombok:lombok:1.16.2" | |
| compile("org.springframework.boot:spring-boot-starter-web") | |
| compile 'com.facebook.swift:swift-annotations:0.14.1' | |
| compile 'com.facebook.swift:swift-service:0.14.1' | |
| compile 'com.facebook.swift:swift-codec:0.14.1' | |
| compile 'com.facebook.nifty:nifty-core:0.14.1' | |
| compile 'org.apache.thrift:libthrift:0.9.1' | |
| testCompile "org.springframework.boot:spring-boot-starter-test" | |
| } |
Nothing special, Spring Boot with few Facebook Swift libraries.
Next we need to add Swift protocol classes:
| package com.example.calculator.protocol; | |
| import com.facebook.swift.service.ThriftMethod; | |
| import com.facebook.swift.service.ThriftService; | |
| import com.google.common.util.concurrent.ListenableFuture; | |
| @ThriftService | |
| public interface TCalculatorService { | |
| @ThriftMethod | |
| int calculate(int num1, int num2, TOperation op) throws TDivisionByZeroException; | |
| } |
Exception is simple Swift struct which extend Exception (See Ma no TException)
| package com.example.calculator.protocol; | |
| import com.facebook.swift.codec.ThriftStruct; | |
| @ThriftStruct | |
| public final class TDivisionByZeroException extends Exception { | |
| } |
Enums are handled with Swift, so we don't need to annotate them (but we can)
| package com.example.calculator.protocol; | |
| public enum TOperation { | |
| ADD, | |
| SUBTRACT, | |
| MULTIPLY, | |
| DIVIDE | |
| } |
Next - application main class for Spring Boot:
| package com.example.calculator; | |
| import com.example.calculator.protocol.TCalculatorService; | |
| import com.facebook.nifty.processor.NiftyProcessorAdapters; | |
| import com.facebook.swift.codec.ThriftCodecManager; | |
| import com.facebook.swift.service.ThriftEventHandler; | |
| import com.facebook.swift.service.ThriftServiceProcessor; | |
| import org.apache.thrift.protocol.*; | |
| import org.apache.thrift.server.TServlet; | |
| import org.springframework.boot.SpringApplication; | |
| import org.springframework.boot.autoconfigure.EnableAutoConfiguration; | |
| import org.springframework.context.annotation.*; | |
| import javax.servlet.Servlet; | |
| import java.util.Arrays; | |
| @Configuration | |
| @EnableAutoConfiguration | |
| @ComponentScan | |
| public class CalculatorApplication { | |
| public static void main(String[] args) { | |
| SpringApplication.run(CalculatorApplication.class, args); | |
| } | |
| @Bean | |
| TProtocolFactory tProtocolFactory() { | |
| return new TBinaryProtocol.Factory(); | |
| } | |
| @Bean | |
| ThriftCodecManager thriftCodecManager() { | |
| return new ThriftCodecManager(); | |
| } | |
| @Bean | |
| Servlet thrift(ThriftCodecManager thriftCodecManager, TProtocolFactory protocolFactory, TCalculatorService exampleService) { | |
| ThriftServiceProcessor processor = new ThriftServiceProcessor(thriftCodecManager, Arrays.<ThriftEventHandler>asList(), exampleService); | |
| return new TServlet( | |
| NiftyProcessorAdapters.processorToTProcessor(processor), | |
| protocolFactory, | |
| protocolFactory | |
| ); | |
| } | |
| } |
Test
Now we're ready to write some tests:
| package com.example.calculator; | |
| import com.example.calculator.protocol.TCalculatorService; | |
| import com.example.calculator.protocol.TDivisionByZeroException; | |
| import com.example.calculator.protocol.TOperation; | |
| import com.facebook.nifty.client.HttpClientConnector; | |
| import com.facebook.swift.codec.ThriftCodecManager; | |
| import com.facebook.swift.service.ThriftClientManager; | |
| import org.apache.thrift.protocol.TProtocolFactory; | |
| import org.junit.Before; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.springframework.beans.factory.annotation.Autowired; | |
| import org.springframework.beans.factory.annotation.Value; | |
| import org.springframework.boot.test.IntegrationTest; | |
| import org.springframework.boot.test.SpringApplicationConfiguration; | |
| import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | |
| import org.springframework.test.context.web.WebAppConfiguration; | |
| import java.net.URI; | |
| import static org.junit.Assert.*; | |
| @RunWith(SpringJUnit4ClassRunner.class) | |
| @SpringApplicationConfiguration(classes = CalculatorApplication.class) | |
| @WebAppConfiguration | |
| @IntegrationTest("server.port:0") | |
| public class CalculatorApplicationTest { | |
| @Autowired | |
| TProtocolFactory protocolFactory; | |
| @Autowired | |
| ThriftCodecManager thriftCodecManager; | |
| @Value("${local.server.port}") | |
| protected int port; | |
| protected TCalculatorService client; | |
| @Before | |
| public void setUp() throws Exception { | |
| HttpClientConnector connector = new HttpClientConnector(URI.create("http://localhost:" + port + "/thrift/")); | |
| ThriftClientManager clientManager = new ThriftClientManager(thriftCodecManager); | |
| client = clientManager.createClient(connector, TCalculatorService.class).get(); | |
| } | |
| @Test | |
| public void testAdd() throws Exception { | |
| assertEquals(5, client.calculate(2, 3, TOperation.ADD)); | |
| } | |
| @Test | |
| public void testSubtract() throws Exception { | |
| assertEquals(3, client.calculate(5, 2, TOperation.SUBTRACT)); | |
| } | |
| @Test | |
| public void testMultiply() throws Exception { | |
| assertEquals(10, client.calculate(5, 2, TOperation.MULTIPLY)); | |
| } | |
| @Test | |
| public void testDivide() throws Exception { | |
| assertEquals(2, client.calculate(10, 5, TOperation.DIVIDE)); | |
| } | |
| @Test(expected = TDivisionByZeroException.class) | |
| public void testDivisionByZero() throws Exception { | |
| client.calculate(10, 0, TOperation.DIVIDE); | |
| } | |
| } |
As you can see, only difference here (compared to Thrift version) is setUp method.
Diff with Thrift version
Implementation
We still have no Swift service implementation. Implementation of handler looks almost the same asprevious:
| package com.example.calculator.handler; | |
| import com.example.calculator.protocol.TCalculatorService; | |
| import com.example.calculator.protocol.TDivisionByZeroException; | |
| import com.example.calculator.protocol.TOperation; | |
| import org.springframework.stereotype.Component; | |
| import com.example.calculator.service.CalculatorService; | |
| import org.springframework.beans.factory.annotation.Autowired; | |
| @Component | |
| public class CalculatorServiceHandler implements TCalculatorService { | |
| @Autowired | |
| CalculatorService calculatorService; | |
| @Override | |
| public int calculate(int num1, int num2, TOperation op) throws TDivisionByZeroException { | |
| switch(op) { | |
| case ADD: | |
| return calculatorService.add(num1, num2); | |
| case SUBTRACT: | |
| return calculatorService.subtract(num1, num2); | |
| case MULTIPLY: | |
| return calculatorService.multiply(num1, num2); | |
| case DIVIDE: | |
| try { | |
| return calculatorService.divide(num1, num2); | |
| } catch(IllegalArgumentException e) { | |
| throw new TDivisionByZeroException(); | |
| } | |
| default: | |
| throw new IllegalArgumentException("Unknown operation " + op); | |
| } | |
| } | |
| } |
Now if you will run tests you should see all tests green.

Thrift integration
But hey, how about other non-Java consumers of service? Don't worry, Swift comes with a tool for generating *.thrift files from annotated Java classes:https://github.com/facebook/swift/tree/master/swift2thrift-generator-cli
Example output for our service will be:
| namespace java.swift com.example.calculator.protocol | |
| namespace java com.example.calculator.protocol | |
| namespace py com.example.calculator.protocol | |
| namespace as3 com.example.calculator.protocol | |
| enum TOperation { | |
| ADD, SUBTRACT, MULTIPLY, DIVIDE | |
| } | |
| exception TDivisionByZeroException { | |
| } | |
| service TCalculatorService { | |
| i32 calculate(1: i32 arg0, 2: i32 arg1, 3: TOperation arg2) throws (1: TDivisionByZeroException ex1); | |
| } |
Conclusion
Full source files for this example can be found at GitHub: https://github.com/bsideup/spring-boot-swift
Next time I will show you how to write Async Thrift services using Swift with minimal changes. Stay tuned!
Building Microservices with Spring Boot and Apache Thrift. Part 2. Swifty services的更多相关文章
- Building Microservices with Spring Boot and Apache Thrift. Part 1 with servlet
https://dzone.com/articles/building-microservices-spring In the modern world of microservices it's i ...
- Quick Guide to Microservices with Spring Boot 2.0, Eureka and Spring Cloud
https://piotrminkowski.wordpress.com/2018/04/26/quick-guide-to-microservices-with-spring-boot-2-0-eu ...
- Building microservices with Spring Cloud and Netflix OSS, part 2
In Part 1 we used core components in Spring Cloud and Netflix OSS, i.e. Eureka, Ribbon and Zuul, to ...
- Spring Boot 整合 Apache Dubbo
Apache Dubbo是一款高性能.轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现. 注意,是 Apache Dubb ...
- Spring Boot 整合 Apache Ignite
关于Ignite的介绍,这边推荐三个链接进行学习了解. https://ignite.apache.org/,首选还是官网,不过是英文版,如果阅读比较吃力可以选择下方两个链接. https://www ...
- Microservices with Spring Boot
找到一套比较不错的Spring Boot/Cloud入门教程,推荐一下. https://dzone.com/users/1041459/ranga_pec.html
- Spring boot with Apache Hive
5.29.1. Maven <dependency> <groupId>org.springframework.boot</groupId> <artif ...
- spring boot 集成 Apache CXF 调用 .NET 服务端 WebService
1. pom.xml加入 cxf 的依赖 <dependency> <groupId>org.apache.cxf</groupId> <artifactId ...
- Spring Boot Reference Guide
Spring Boot Reference Guide Authors Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch, ...
随机推荐
- Linux Centos 迁移Mysql 数据位置
Linux Centos 迁移Mysql 数据位置 由于业务量增加导致安装在系统盘(20G)磁盘空间被占满了, 现在进行数据库的迁移. Mysql 是通过 yum 安装的. Centos6.5Mysq ...
- mysql实现首字母从A-Z排序
1.常规排序ASC DESC ASC 正序 DESC倒叙 -- 此处不用多讲 2.自定义排序 自定义排序是根据自己想要的特定字符串(数字)顺序进行排序.主要是使用函数 FIELD(str,str1,s ...
- 五句话搞定JavaScript作用域(ES5)
JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走遍天下都不怕... 一.“JavaScript中无块级作用域” 在Java或C# ...
- MyBatis映射文件5
返回map Map<String,Object> getEmpByResMap(Integer id); <select id="getEmpByResMap&qu ...
- Hibernate **关于hibernate4.3版本之后org.hibernate.service.ServiceRegistryBuilder被弃用**
之前一直都是使用hibernate4.2.21的我,有一天突然没有使用本地的jar包而是让IDEA自动下载最新版本的hibernate5.2.2之后,发现有几个经常使用的方法报错了. //创建配置对象 ...
- opencv imdecode和imencode用法
主要是对内存数据自动编解码 string fname = "D:/image.jpg"; //! 以二进制流方式读取图片到内存 FILE* pFile = fopen(fname. ...
- hibernate多对多映射文件的配置
user.hbm.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate ...
- hdu-2328(暴力枚举+kmp)
题意:给你n个字符串,问你这n个串的最长公共子串 解题思路:暴力枚举任意一个字符串的所有子串,然后暴力匹配,和hdu1238差不多的思路吧,这里用string解决的: 代码: #include< ...
- bzoj1206-[HNOI2005]虚拟内存
卡读的毒瘤题== 看懂之后用map模拟.或者线段树 #include<cstdio> #include<iostream> #include<cmath> #inc ...
- BZOJ3165[Heoi2013]Segment——李超线段树
题目描述 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第i条被插入的线段的标号为i. 2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. 输入 第一行 ...