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, ...
随机推荐
- Oracle 表分区(Partition)
表分区功能能够改善应用程序性能,提高数据库可管理性和可用性,是数据库管理非常关键的技术.数据库通过使用分区提高查询性能,简化日常管理维护工作. 1 分区优点 1) 减少维护工作量,独立管理每个表分区比 ...
- [转帖]pfSense软路由系统的使用
图解pfSense软路由系统的使用(NAT功能) http://seanlook.com/2015/04/23/pfsense-usage/ 发表于 2015-04-23 | 更新于: 2015- ...
- CMake--模块的使用和自定义模块
1.链接外部库 如果程序中使用了外部库,事先并不知道它的头文件和链接库的位置,就要给出头文件和链接库的查找方法,并将他们链接到程序中. FIND_PACKAGE(<name> [major ...
- Sublime Text3配置
{ "default_encoding": "UTF-8", "font_size": 16.0, "tab_size" ...
- 如何在Mac系统安装MySQL
方法一: (1)使用brew install mysql (2)使用mysql -uroot连接时报错: Authentication plugin 'caching_sha2_password' c ...
- JS--dom对象:document object model文档对象模型
dom对象:document object model文档对象模型 文档:超文本标记文档 html xml 对象:提供了属性和方法 模型:使用属性和方法操作超文本标记性文档 可以使用js里面的DOM提 ...
- JQuery跳出each循环的方法(包含数组遍历)
0. 前言 也许我们通过 jquery 的循环方法进行数组遍历,但是当不符合条件时,怎么跳出当前循环?(即用each方法内,当不满足条件时想break跳出循环体,想continue继续执行下一个循环遍 ...
- THEPYTHONCHALLENG闯关记录
由于是自己看视频学python,总觉得不写几行代码就什么都没有学到. 找了一个写代码的网站其实只是因为这个看起来好玩. 闯关地址http://www.pythonchallenge.com/index ...
- Bash 5.0 发布及其新功能
导读 邮件列表证实最近发布了 Bash-5.0.而且,令人兴奋的是它还有新的功能和变量.如果你一直在使用 Bash 4.4.XX,那么你一定会喜欢 Bash 的第五个主要版本. 第五个版本侧重于新的 ...
- 小程序——Tab切换
<view class="body"> <view class="nav bc_white"> <view class=" ...