diff options
Diffstat (limited to 'grpc')
-rw-r--r-- | grpc/flatbuffers-java-grpc/pom.xml | 42 | ||||
-rw-r--r-- | grpc/flatbuffers-java-grpc/src/main/java/com/google/flatbuffers/grpc/FlatbuffersUtils.java | 117 | ||||
-rw-r--r-- | grpc/pom.xml | 213 | ||||
-rw-r--r-- | grpc/tests/JavaGrpcTest.java | 119 | ||||
-rwxr-xr-x | grpc/tests/java-grpc-test.sh | 4 | ||||
-rw-r--r-- | grpc/tests/pom.xml | 73 |
6 files changed, 568 insertions, 0 deletions
diff --git a/grpc/flatbuffers-java-grpc/pom.xml b/grpc/flatbuffers-java-grpc/pom.xml new file mode 100644 index 00000000..11aa0bd1 --- /dev/null +++ b/grpc/flatbuffers-java-grpc/pom.xml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.google.flatbuffers</groupId> + <artifactId>flatbuffers-parent</artifactId> + <version>1.8.0</version> + </parent> + <artifactId>flatbuffers-java-grpc</artifactId> + <name>${project.artifactId}</name> + <packaging>bundle</packaging> + <description> + Utilities supporting generated code for GRPC + </description> + <developers> + <developer> + <name>Wouter van Oortmerssen</name> + </developer> + <developer> + <name>Yuri Finkelstein</name> + <url>https://github.com/yfinkelstein</url> + </developer> + </developers> + <properties> + <gRPC.version>1.8.0</gRPC.version> + </properties> + <dependencies> + <dependency> + <groupId>com.google.flatbuffers</groupId> + <artifactId>flatbuffers-java</artifactId> + <version>${project.parent.version}</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-core</artifactId> + <version>${gRPC.version}</version> + </dependency> + </dependencies> +</project> + diff --git a/grpc/flatbuffers-java-grpc/src/main/java/com/google/flatbuffers/grpc/FlatbuffersUtils.java b/grpc/flatbuffers-java-grpc/src/main/java/com/google/flatbuffers/grpc/FlatbuffersUtils.java new file mode 100644 index 00000000..768708b1 --- /dev/null +++ b/grpc/flatbuffers-java-grpc/src/main/java/com/google/flatbuffers/grpc/FlatbuffersUtils.java @@ -0,0 +1,117 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.flatbuffers.grpc; + +import com.google.flatbuffers.Table; +import io.grpc.Drainable; +import io.grpc.KnownLength; +import io.grpc.MethodDescriptor; + +import javax.annotation.Nullable; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.ByteBuffer; + +public class FlatbuffersUtils { + abstract public static class FBExtactor <T extends Table> { + T extract (InputStream stream) throws IOException { + if (stream instanceof KnownLength) { + int size = stream.available(); + ByteBuffer buffer = ByteBuffer.allocate(size); + stream.read(buffer.array()); + return extract(buffer); + } else + throw new RuntimeException("The class " + stream.getClass().getCanonicalName() + " does not extend from KnownLength "); + } + + public abstract T extract(ByteBuffer buffer); + + } + + static class FBInputStream extends InputStream implements Drainable, KnownLength { + private final ByteBuffer buffer; + private final int size; + @Nullable private ByteArrayInputStream inputStream; + + FBInputStream(ByteBuffer buffer) { + this.buffer = buffer; + this.size = buffer.remaining(); + } + + private void makeStreamIfNotAlready() { + if (inputStream == null) + inputStream = new ByteArrayInputStream(buffer.array(), buffer.position(), size); + } + + @Override + public int drainTo(OutputStream target) throws IOException { + target.write(buffer.array(), buffer.position(), size); + return size; + } + + @Override + public int read() throws IOException { + makeStreamIfNotAlready(); + return inputStream.read(); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException { + makeStreamIfNotAlready(); + if (inputStream == null) { + if (len >= size) { + System.arraycopy(buffer.array(), buffer.position(), b, off, size); + return size; + } else { + makeStreamIfNotAlready(); + return inputStream.read(b, off, len); + } + } else + return inputStream.read(b, off, len); + } + + @Override + public int available() throws IOException { + return inputStream == null ? size : inputStream.available(); + } + + } + + public static <T extends Table> MethodDescriptor.Marshaller<T> marshaller(final Class<T> clazz, final FBExtactor<T> extractor) { + return new MethodDescriptor.ReflectableMarshaller<T>() { + @Override + public Class<T> getMessageClass() { + return clazz; + } + + @Override + public InputStream stream(T value) { + return new FBInputStream (value.getByteBuffer()); + } + + @Override + public T parse(InputStream stream) { + try { + return extractor.extract(stream); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }; + } +} diff --git a/grpc/pom.xml b/grpc/pom.xml new file mode 100644 index 00000000..b43369e3 --- /dev/null +++ b/grpc/pom.xml @@ -0,0 +1,213 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>com.google.flatbuffers</groupId> + <artifactId>flatbuffers-parent</artifactId> + <packaging>pom</packaging> + <version>1.8.0</version> + <name>flatbuffers-parent</name> + <description>parent pom for flatbuffers java artifacts</description> + <properties> + <scm.url>https://github.com/google/flatbuffers</scm.url> + <scm.connection>scm:git:${scm.url}.git</scm.connection> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <licenses> + <license> + <name>The Apache Software License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <issueManagement> + <system>GitHub</system> + <url>https://github.com/google/flatbuffers/issues</url> + </issueManagement> + + <developers> + <developer> + <name>Wouter van Oortmerssen</name> + </developer> + </developers> + + <url>${scm.url}</url> + + <scm> + <connection>${scm.connection}</connection> + <developerConnection>${scm.connection}</developerConnection> + <url>${scm.url}</url> + <tag>HEAD</tag> + </scm> + + <distributionManagement> + <snapshotRepository> + <id>ossrh</id> + <url>https://oss.sonatype.org/content/repositories/snapshots</url> + </snapshotRepository> + </distributionManagement> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + + </dependencies> + <build> + <extensions> + <extension> + <!-- + os-maven-plugin is a Maven extension/plugin that generates various useful platform-dependent + project properties normalized from ${os.detected.name} and ${os.detected.arch}. + --> + <groupId>kr.motd.maven</groupId> + <artifactId>os-maven-plugin</artifactId> + <version>1.5.0.Final</version> + </extension> + </extensions> + <pluginManagement> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.6.1</version> + </plugin> + <plugin> + <artifactId>maven-jar-plugin</artifactId> + <version>3.0.2</version> + </plugin> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <version>3.0.1</version> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <version>2.19.1</version> + </plugin> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + <version>2.10.4</version> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.12</version> + </plugin> + <plugin> + <artifactId>maven-dependency-plugin</artifactId> + <version>2.8</version> + </plugin> + <plugin> + <artifactId>maven-deploy-plugin</artifactId> + <version>2.7</version> + </plugin> + <plugin> + <artifactId>maven-gpg-plugin</artifactId> + <version>1.5</version> + </plugin> + <plugin> + <artifactId>maven-release-plugin</artifactId> + <version>2.5.3</version> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>exec-maven-plugin</artifactId> + <version>1.5.0</version> + </plugin> + </plugins> + </pluginManagement> + + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.6</source> + <target>1.6</target> + </configuration> + </plugin> + <plugin> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <includes> + <include>**/*Test.java</include> + </includes> + </configuration> + </plugin> + <plugin> + <artifactId>maven-source-plugin</artifactId> + <executions> + <execution> + <id>attach-sources</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + <executions> + <execution> + <id>attach-javadocs</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <version>3.0.1</version> + <extensions>true</extensions> + </plugin> + <plugin> + <groupId>org.sonatype.plugins</groupId> + <artifactId>nexus-staging-maven-plugin</artifactId> + <version>1.6.7</version> + <extensions>true</extensions> + <configuration> + <serverId>ossrh</serverId> + <nexusUrl>https://oss.sonatype.org/</nexusUrl> + <autoReleaseAfterClose>true</autoReleaseAfterClose> + </configuration> + </plugin> + <plugin> + <artifactId>maven-gpg-plugin</artifactId> + <executions> + <execution> + <id>sign-artifacts</id> + <phase>verify</phase> + <goals> + <goal>sign</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-release-plugin</artifactId> + <configuration> + <autoVersionSubmodules>true</autoVersionSubmodules> + <useReleaseProfile>false</useReleaseProfile> + <releaseProfiles>release</releaseProfiles> + <goals>deploy</goals> + </configuration> + </plugin> + </plugins> + </build> + + <modules> +<!-- consider the benefits of publishing all maven artifacts in this project + + <module>flatbuffers-compiler</module> + <module>flatbuffers-java</module> + +--> + <module>flatbuffers-java-grpc</module> + </modules> + +</project> diff --git a/grpc/tests/JavaGrpcTest.java b/grpc/tests/JavaGrpcTest.java new file mode 100644 index 00000000..6ae6995b --- /dev/null +++ b/grpc/tests/JavaGrpcTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 2014 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import MyGame.Example.Monster; +import MyGame.Example.MonsterStorageGrpc; +import MyGame.Example.Stat; +import com.google.flatbuffers.FlatBufferBuilder; +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.Server; +import io.grpc.ServerBuilder; +import org.junit.Assert; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Iterator; + + +/** + * Demonstrates basic client-server interaction using grpc-java over netty. + */ +public class JavaGrpcTest { + static final String BIG_MONSTER_NAME = "big-monster"; + static final short nestedMonsterHp = 600; + static final short nestedMonsterMana = 1024; + static final int numStreamedMsgs = 10; + + static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase { + @Override + public void store(Monster request, io.grpc.stub.StreamObserver<Stat> responseObserver) { + Assert.assertEquals(request.name(), BIG_MONSTER_NAME); + Assert.assertEquals(request.hp(), nestedMonsterHp); + Assert.assertEquals(request.mana(), nestedMonsterMana); + System.out.println("Received store request from " + request.name()); + // Create a response from the incoming request name. + FlatBufferBuilder builder = new FlatBufferBuilder(); + int statOffset = Stat.createStat(builder, builder.createString("Hello " + request.name()), 100, 10); + builder.finish(statOffset); + Stat stat = Stat.getRootAsStat(builder.dataBuffer()); + responseObserver.onNext(stat); + responseObserver.onCompleted(); + } + + @Override + public void retrieve(Stat request, io.grpc.stub.StreamObserver<Monster> responseObserver) { + // Create 10 monsters for streaming response. + for (int i=0; i<numStreamedMsgs; i++) { + FlatBufferBuilder builder = new FlatBufferBuilder(); + int i1 = builder.createString(request.id() + " No." + i); + Monster.startMonster(builder); + Monster.addName(builder, i1); + int i2 = Monster.endMonster(builder); + Monster.finishMonsterBuffer(builder, i2); + Monster monster = Monster.getRootAsMonster(builder.dataBuffer()); + responseObserver.onNext(monster); + } + responseObserver.onCompleted(); + } + } + + + private static int startServer() throws IOException { + Server server = ServerBuilder.forPort(0).addService(new MyService()).build().start(); + return server.getPort(); + } + + @org.junit.Test + public void testMonster() throws IOException { + int port = startServer(); + ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", port) + // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid + // needing certificates. + .usePlaintext(true) + .directExecutor() + .build(); + + MonsterStorageGrpc.MonsterStorageBlockingStub stub = MonsterStorageGrpc.newBlockingStub(channel); + + FlatBufferBuilder builder = new FlatBufferBuilder(); + + int o_string = builder.createString(BIG_MONSTER_NAME); + Monster.startMonster(builder); + Monster.addName(builder, o_string); + Monster.addHp(builder, nestedMonsterHp); + Monster.addMana(builder, nestedMonsterMana); + int monster1 = Monster.endMonster(builder); + Monster.finishMonsterBuffer(builder, monster1); + + ByteBuffer buffer = builder.dataBuffer(); + Monster monsterRequest = Monster.getRootAsMonster(buffer); + Stat stat = stub.store(monsterRequest); + Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME); + System.out.println("Received stat response from service: " + stat.id()); + + + Iterator<Monster> iterator = stub.retrieve(stat); + int counter = 0; + while(iterator.hasNext()) { + Monster m = iterator.next(); + System.out.println("Received monster " + m.name()); + counter ++; + } + Assert.assertEquals(counter, numStreamedMsgs); + System.out.println("FlatBuffers GRPC client/server test: completed successfully"); + } +} diff --git a/grpc/tests/java-grpc-test.sh b/grpc/tests/java-grpc-test.sh new file mode 100755 index 00000000..ec429605 --- /dev/null +++ b/grpc/tests/java-grpc-test.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +# NOTE: make sure `mvn install` in /gprc is executed before running this test +mvn test diff --git a/grpc/tests/pom.xml b/grpc/tests/pom.xml new file mode 100644 index 00000000..cfd908b5 --- /dev/null +++ b/grpc/tests/pom.xml @@ -0,0 +1,73 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>com.google.flatbuffers</groupId> + <artifactId>flatbuffers-parent</artifactId> + <version>1.8.0</version> + </parent> + <artifactId>grpc-test</artifactId> + <description>Example/Test project demonstrating usage of flatbuffers with GRPC-Java instead of protobufs + </description> + <properties> + <gRPC.version>1.8.0</gRPC.version> + </properties> + <dependencies> + <dependency> + <groupId>com.google.flatbuffers</groupId> + <artifactId>flatbuffers-java</artifactId> + <version>${project.parent.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.flatbuffers</groupId> + <artifactId>flatbuffers-java-grpc</artifactId> + <version>${project.parent.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-stub</artifactId> + <version>${gRPC.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-netty</artifactId> + <version>${gRPC.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>add-source</id> + <phase>generate-sources</phase> + <goals> + <goal>add-test-source</goal> + </goals> + <configuration> + <sources> + <source>${project.basedir}</source> + <source>${project.basedir}/../../tests</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + <!--<testSourceDirectory>${project.basedir}</testSourceDirectory>--> + </build> +</project> + |