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. [转帖]整理:Windows系统下的奇技淫巧大汇总

    整理:Windows系统下的奇技淫巧大汇总 https://blog.csdn.net/bat67/article/details/76381357 Win+home Crtl+home 还有 Win ...

  2. springmvc通过HttpServletRequest进行参数传递

    @RequestMapping("/itemEdit") public String itemEdit(HttpServletRequest request, Model mode ...

  3. springboot+ELK+logback日志分析系统demo

    之前写的有点乱,这篇整理了一下搭建了一个简单的ELK日志系统 借鉴此博客完成:https://blog.csdn.net/qq_22211217/article/details/80764568 设置 ...

  4. 在JavaEE中使用Hibernate框架

    我们必须要了解一些Hibernate基础对象,如下: 配置对象 配置对象是你在任何 Hibernate 应用程序中创造的第一个 Hibernate 对象,并且经常只在应用程序初始化期间创造.它代表了 ...

  5. xadmin快速搭建后台管理系统

    一.xadmin的特点: 1.基于Bootstrap3:Xadmin使用Bootstrap3.0框架精心打造.基于Bootstrap3,Xadmin天生就支持在多种屏幕上无缝浏览,并完全支持Boots ...

  6. Yii的数值比较验证器

    该验证器比对两个特定输入值之间的关系 是否与 operator 属性所指定的相同. compareAttribute:用于与原属性相比对的属性名称. 当该验证器被用于验证某目标属性时, 该属性会默认为 ...

  7. JavaSE从入门到精通

      1.JavaSE的安装 windows下安装完成后,配置环境变量如下: JAVA_HOME       C:\Program Files (x86)\Java\jdk1.8.0_91 CLASSP ...

  8. mybatis generator的maven插件,找不到properties的配置文件错误的解决

    第一次运行的时候,maven插件是正确运行了的 但后面对 maven 的 build节点做了一点修改,就开始报错,找不到 properties标签指定的的数据库连接配置文件了 修改部分如下: 这个操作 ...

  9. LODOP中预览界面查看打印机的可打区域具体值

    LODOP在打印预览的时候,如果选择的打印机是真实打印机,会发现可能会有虚线,不同打印机虚线的位置不同,这个虚线是打印机的可打区域,Lodop无法控制. 可打区域,顾名思义,就是打印机可以打印的区域, ...

  10. onbeforeunload事件两种写法及效果

    在符合W3C标准的浏览器里,可以使用addEventListener方法来添加事件. 当不需要为一个事件添加多个处理函数的时候,可以简单的使用onXXX=function(){}的方式来添加事件处理函 ...