4.07.2015

Building Microservices with Spring Boot and Apache Thrift. Part 2. Swifty services

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:

Nothing special, Spring Boot with few Facebook Swift libraries.

Next we need to add Swift protocol classes:

Exception is simple Swift struct which extend Exception (See Ma no TException)

Enums are handled with Swift, so we don't need to annotate them (but we can)

Next - application main class for Spring Boot:

Test

Now we're ready to write some tests:

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 as previous:

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:


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!

8 comments:

  1. Great post, i am using protocol buffers and thrift but this is a great plus for thrift. I think of using the annotations with cxf generated code.

    ReplyDelete
  2. Thank you for a great post.
    but, i'm following your step but i used maven.
    when i run the unit test, i got an error HTTP response had non-OK status: 406 Not Acceptable, and spring says Request method 'POST' not supported.
    could you help me to fix this issue?

    here is the stacktrace :
    aused by: org.apache.thrift.transport.TTransportException: HTTP response had non-OK status: 406 Not Acceptable
    at com.facebook.nifty.client.HttpClientChannel.extractResponse(HttpClientChannel.java:70)
    at com.facebook.nifty.client.AbstractClientChannel.messageReceived(AbstractClientChannel.java:250)
    at org.jboss.netty.channel.SimpleChannelHandler.handleUpstream(SimpleChannelHandler.java:88)
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
    at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:791)
    at org.jboss.netty.handler.codec.http.HttpChunkAggregator.messageReceived(HttpChunkAggregator.java:145)
    at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70)
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
    at org.jboss.netty.channel.DefaultChannelPipeline$DefaultChannelHandlerContext.sendUpstream(DefaultChannelPipeline.java:791)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296)
    at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:459)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.callDecode(ReplayingDecoder.java:536)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.messageReceived(ReplayingDecoder.java:435)
    at org.jboss.netty.channel.SimpleChannelUpstreamHandler.handleUpstream(SimpleChannelUpstreamHandler.java:70)
    at org.jboss.netty.handler.codec.http.HttpClientCodec.handleUpstream(HttpClientCodec.java:92)
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:564)
    at org.jboss.netty.channel.DefaultChannelPipeline.sendUpstream(DefaultChannelPipeline.java:559)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:88)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.process(AbstractNioWorker.java:109)
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
    at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:90)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:178)
    at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
    at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)


    ReplyDelete
    Replies
    1. I will take a look shortly and maybe even update example with Maven as well :)

      Delete
    2. This comment has been removed by the author.

      Delete
    3. I was fixed the error by using this maven pom. http://pastebin.com/fXtQZTkw

      btw, could you give some example like this example but using TCP Connection? :D

      Delete
  3. Great article! I'm running into the same problems as Arif, any suggestions?

    ReplyDelete
  4. hey, friend:

    How about Performance ? do you compare with original thrift ?

    ReplyDelete