http://bsideup.blogspot.com/2015/04/spring-boot-thrift-part2.html

 
 
In previous article I showed you how to use pure Apache Thrift to create protocols for your services. This time I will explain how to use Facebook Swift (not the best name for project BTW :)) to get rid of Thrift IDL files for server code.

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"
  }
view rawbuild.gradle hosted with ❤ by GitHub

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
  }
view rawTOperation.java hosted with ❤ by GitHub

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);
  }
  }
  }

Diff with Thrift version

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);
  }
view rawcalculator.thrift hosted with ❤ by GitHub

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的更多相关文章

  1. 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 ...

  2. 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 ...

  3. 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 ...

  4. Spring Boot 整合 Apache Dubbo

    Apache Dubbo是一款高性能.轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现. 注意,是 Apache Dubb ...

  5. Spring Boot 整合 Apache Ignite

    关于Ignite的介绍,这边推荐三个链接进行学习了解. https://ignite.apache.org/,首选还是官网,不过是英文版,如果阅读比较吃力可以选择下方两个链接. https://www ...

  6. Microservices with Spring Boot

    找到一套比较不错的Spring Boot/Cloud入门教程,推荐一下. https://dzone.com/users/1041459/ranga_pec.html

  7. Spring boot with Apache Hive

      5.29.1. Maven <dependency> <groupId>org.springframework.boot</groupId> <artif ...

  8. spring boot 集成 Apache CXF 调用 .NET 服务端 WebService

    1. pom.xml加入 cxf 的依赖 <dependency> <groupId>org.apache.cxf</groupId> <artifactId ...

  9. Spring Boot Reference Guide

    Spring Boot Reference Guide Authors Phillip Webb, Dave Syer, Josh Long, Stéphane Nicoll, Rob Winch,  ...

随机推荐

  1. Java 异常处理的误区和经验总结

    Java 异常处理的误区和经验总结   1 本文着重介绍了 Java 异常选择和使用中的一些误区,希望各位读者能够熟练掌握异常处理的一些注意点和原则,注意总结和归纳.只有处理好了异常,才能提升开发人员 ...

  2. JSON Support in PostgreSQL and Entity Framework

    JSON 和JSONB的区别(What's difference between JSON and JSONB data type in PosgresSQL?) When should be use ...

  3. PhpStorm本地断点调试

    一.断点调试php环境搭建 1.检测本地php环境是否安装了Xdebug 在本地输出phpinfo():搜索Xdebug;如下图  如果没有安装,安装操作Xdebug如下: 将phpinfo();的信 ...

  4. Google浏览器解决编码乱码问题

    新版google浏览器编码乱码没有设置的入口,怎么办呢?. 步骤一: 可以下载goole的插件,名为charset,下载后的文件名为Charset_v0.4.1 步骤二: google右上角-> ...

  5. 四、Mysql主从同步

    一.MySQL Replication介绍 MySQL Replication 官方文档 Replication可以实现将数据从一台数据库服务器(master)复制到一或多台数据库服务器(slave) ...

  6. 获取网络图片并显示在picturbox上,byte[]数组转换成Image:

    private void getWebPicture_Click(object sender, EventArgs e) { WebRequest request = WebRequest.Creat ...

  7. 【python练习题】程序2

    2.题目:企业发放的奖金根据利润提成.利润(I)低于或等于10万元时,奖金可提10%:利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%:20万到40 ...

  8. B-树 B+树复习总结

    一.B-树的定义 一棵m阶的B-树或为空树,或为具有以下特性的m叉树 1.树中每个结点至多有m棵子树 (m-1个关键字) 2.根结点至少有两棵子树 (至少有一个关键字) 3.除根节点的分支结点至少有f ...

  9. 保密工作与linux系统的发展

    保密工作从性质上可以分成商业方面的保密和国家安全方面的保密.由于自己从事的是IT方面的工作,工作中必然会接触涉及到计算机信息方面的相关文件.加上单位已近通过武器装备科研生产单位二级保密资格认证,今天就 ...

  10. ScheduledThreadPoolExecutor 吞异常

    线程挂掉不一定会输出日志到控制台,比如ScheduledThreadPoolExecutor,如果在执行的任务中有未捕获的异常抛出,就行停止调度,没有任何错误输出到控制台或日志文件.在项目中这会导致一 ...