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, ...
随机推荐
- [转帖]学习关于TTL
自己简单试了一下在家里与在公司里面服务器的连接: C:\Users\Administrator>tracert oms.inspur.com 通过最多 个跃点跟踪 到 oms.inspur.co ...
- MySQL 字段内容区分大小写
数据由Oracle 迁入MySQL ,由于之前Oracle区分大小写,MySQL的配置使用了默认配置,导致一些数据导入失败,有的唯一键报错,冲突. 将测试过程记录在下面. 数据库版本:MySQL 5. ...
- python pip安装找不到指定包的时候怎么解决
在该网址上下载对应版本的包然后安装即可. https://www.lfd.uci.edu/~gohlke/pythonlibs/
- hive条件函数
case相当于if,when相当于=:then是条件满足的结论.否则实行else后语句,一end结束
- CSS自定义属性expression_r
CSS的出现使网页制作者在对网页元素的控制方便许多,当然,有利必有弊,CSS只能对颜色.大小.距离等静态样式有效,对于要实现某些html元素的动态样式就显得有些力不从心.有了CSS的自定义属性expr ...
- Yii2的使用
yii2的下载安装 使用下载好的文件配置高级模板,在配置文件配置好数据库和gii 在common模板配置db: 在backend模板配置gii: 配置nginx服务器访问backend和fronten ...
- dbExpress操作中用TDBGrid显示数据
由于一些数据感知组件如TDBGrid等是需要用到数据缓存的,这和dbExpress组件的存取机制是矛盾的.所以当打开数据集时会出现如下内容的警告框:“Operation not allowed on ...
- How to write to an event log by using Visual C#
using System; using System.Diagnostics; namespace WriteToAnEventLog_csharp { /// Summary description ...
- 使用cmd命令行窗口操作SqlServer
本文主要介绍使用windows下的使用cmd命令行窗口操作Sqlserver, 首先我们可以运行 osql ?/ ,这样就把所有可以通过CMD命令行操作sqlserver的命令显示出来 (有图有 ...
- poj-2513(字典树+欧拉通路)
题意:给你n个火柴棍,每个火柴棍头和尾两种颜色,问你是否存在能够把这些火柴棍摆成一行的情况,两个相连的火柴棍的颜色需要一样: 解题思路:最初的思路是用map标记颜色,然后把每种颜色看作点,每根火柴棍看 ...