protobuf,examples: move json encoding to examples

This commit is contained in:
Carl Mastrangelo 2018-05-17 15:48:45 -07:00 committed by GitHub
parent e085a0eca0
commit e3f8891f57
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 123 additions and 163 deletions

View File

@ -30,6 +30,8 @@ repositories {
// updating the version in our release process.
def grpcVersion = '1.13.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def nettyTcNativeVersion = '2.0.7.Final'
def protobufVersion = '3.5.1'
def protocVersion = '3.5.1-1'
dependencies {
compile "com.google.api.grpc:proto-google-common-protos:1.0.0"
@ -42,6 +44,8 @@ dependencies {
// Used for TLS in HelloWorldServerTls
compile "io.netty:netty-tcnative-boringssl-static:${nettyTcNativeVersion}"
compile "com.google.protobuf:protobuf-java-util:${protobufVersion}"
testCompile "io.grpc:grpc-testing:${grpcVersion}"
testCompile "junit:junit:4.12"
testCompile "org.mockito:mockito-core:1.9.5"
@ -49,7 +53,7 @@ dependencies {
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:3.5.1-1'
artifact = "com.google.protobuf:protoc:${protocVersion}"
}
plugins {
grpc {

View File

@ -12,6 +12,8 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.13.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protobuf.version>3.5.1</protobuf.version>
<protoc.version>3.5.1-1</protoc.version>
<netty.tcnative.version>2.0.7.Final</netty.tcnative.version>
</properties>
<dependencies>
@ -51,6 +53,11 @@
<artifactId>proto-google-common-protos</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>${protobuf.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@ -78,7 +85,7 @@
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.5.1-1:exe:${os.detected.classifier}</protocArtifact>
<protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
</configuration>

View File

@ -28,7 +28,6 @@ import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.examples.helloworld.HelloWorldClient;
import io.grpc.protobuf.ProtoUtils;
import io.grpc.stub.AbstractStub;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
@ -98,8 +97,8 @@ public final class HelloJsonClient {
static final MethodDescriptor<HelloRequest, HelloReply> METHOD_SAY_HELLO =
GreeterGrpc.getSayHelloMethod()
.toBuilder(
ProtoUtils.jsonMarshaller(HelloRequest.getDefaultInstance()),
ProtoUtils.jsonMarshaller(HelloReply.getDefaultInstance()))
JsonMarshaller.jsonMarshaller(HelloRequest.getDefaultInstance()),
JsonMarshaller.jsonMarshaller(HelloReply.getDefaultInstance()))
.build();
protected HelloJsonStub(Channel channel) {

View File

@ -0,0 +1,99 @@
/*
* Copyright 2018 The gRPC Authors
*
* 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 io.grpc.examples.advanced;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.Message.Builder;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.Parser;
import com.google.protobuf.util.JsonFormat.Printer;
import io.grpc.ExperimentalApi;
import io.grpc.MethodDescriptor.Marshaller;
import io.grpc.Status;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
/**
* A {@link Marshaller} for JSON. This marshals in the Protobuf 3 format described here:
* https://developers.google.com/protocol-buffers/docs/proto3#json
*/
final class JsonMarshaller {
private JsonMarshaller() {}
/**
* Create a {@code Marshaller} for json protos of the same type as {@code defaultInstance}.
*
* <p>This is an unstable API and has not been optimized yet for performance.
*/
public static <T extends Message> Marshaller<T> jsonMarshaller(final T defaultInstance) {
final Parser parser = JsonFormat.parser();
final Printer printer = JsonFormat.printer();
return jsonMarshaller(defaultInstance, parser, printer);
}
/**
* Create a {@code Marshaller} for json protos of the same type as {@code defaultInstance}.
*
* <p>This is an unstable API and has not been optimized yet for performance.
*/
public static <T extends Message> Marshaller<T> jsonMarshaller(
final T defaultInstance, final Parser parser, final Printer printer) {
final Charset charset = Charset.forName("UTF-8");
return new Marshaller<T>() {
@Override
public InputStream stream(T value) {
try {
return new ByteArrayInputStream(printer.print(value).getBytes(charset));
} catch (InvalidProtocolBufferException e) {
throw Status.INTERNAL
.withCause(e)
.withDescription("Unable to print json proto")
.asRuntimeException();
}
}
@SuppressWarnings("unchecked")
@Override
public T parse(InputStream stream) {
Builder builder = defaultInstance.newBuilderForType();
Reader reader = new InputStreamReader(stream, charset);
T proto;
try {
parser.merge(reader, builder);
proto = (T) builder.build();
reader.close();
} catch (InvalidProtocolBufferException e) {
throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
.withCause(e).asRuntimeException();
} catch (IOException e) {
// Same for now, might be unavailable
throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
.withCause(e).asRuntimeException();
}
return proto;
}
};
}
}

View File

@ -17,6 +17,10 @@ dependencies {
project(':grpc-protobuf'),
project(':grpc-stub'),
libraries.protobuf
compile (libraries.protobuf_util) {
// prefer 20.0 from libraries instead of 19.0
exclude group: 'com.google.guava', module: 'guava'
}
compileOnly libraries.javax_annotation
testCompile libraries.truth,
project(':grpc-core').sourceSets.test.output

View File

@ -17,11 +17,6 @@ dependencies {
libraries.protobuf,
libraries.guava
compile (libraries.protobuf_util) {
// prefer 20.0 from libraries instead of 19.0
exclude group: 'com.google.guava', module: 'guava'
}
compile (libraries.google_api_protos) {
// 'com.google.api:api-common' transitively depends on auto-value, which breaks our
// annotations.

View File

@ -16,23 +16,10 @@
package io.grpc.protobuf;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.Message.Builder;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.Parser;
import com.google.protobuf.util.JsonFormat.Printer;
import io.grpc.ExperimentalApi;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor.Marshaller;
import io.grpc.Status;
import io.grpc.protobuf.lite.ProtoLiteUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
/**
* Utility methods for using protobuf with grpc.
@ -44,65 +31,6 @@ public class ProtoUtils {
return ProtoLiteUtils.marshaller(defaultInstance);
}
/**
* Create a {@code Marshaller} for json protos of the same type as {@code defaultInstance}.
*
* <p>This is an unstable API and has not been optimized yet for performance.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1786")
public static <T extends Message> Marshaller<T> jsonMarshaller(final T defaultInstance) {
final Parser parser = JsonFormat.parser();
final Printer printer = JsonFormat.printer();
return jsonMarshaller(defaultInstance, parser, printer);
}
/**
* Create a {@code Marshaller} for json protos of the same type as {@code defaultInstance}.
*
* <p>This is an unstable API and has not been optimized yet for performance.
*/
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1786")
public static <T extends Message> Marshaller<T> jsonMarshaller(
final T defaultInstance, final Parser parser, final Printer printer) {
final Charset charset = Charset.forName("UTF-8");
return new Marshaller<T>() {
@Override
public InputStream stream(T value) {
try {
return new ByteArrayInputStream(printer.print(value).getBytes(charset));
} catch (InvalidProtocolBufferException e) {
throw Status.INTERNAL
.withCause(e)
.withDescription("Unable to print json proto")
.asRuntimeException();
}
}
@SuppressWarnings("unchecked")
@Override
public T parse(InputStream stream) {
Builder builder = defaultInstance.newBuilderForType();
Reader reader = new InputStreamReader(stream, charset);
T proto;
try {
parser.merge(reader, builder);
proto = (T) builder.build();
reader.close();
} catch (InvalidProtocolBufferException e) {
throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
.withCause(e).asRuntimeException();
} catch (IOException e) {
// Same for now, might be unavailable
throw Status.INTERNAL.withDescription("Invalid protobuf byte sequence")
.withCause(e).asRuntimeException();
}
return proto;
}
};
}
/**
* Produce a metadata key for a generated protobuf type.
*/

View File

@ -17,20 +17,12 @@
package io.grpc.protobuf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import com.google.common.io.ByteStreams;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import com.google.protobuf.Type;
import io.grpc.MethodDescriptor.Marshaller;
import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@ -53,77 +45,4 @@ public class ProtoUtilsTest {
assertEquals("google.protobuf.Type-bin",
ProtoUtils.keyForProto(Type.getDefaultInstance()).originalName());
}
@Test
public void testJsonRoundtrip() throws Exception {
Marshaller<Type> marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
InputStream is = marshaller.stream(proto);
is = new ByteArrayInputStream(ByteStreams.toByteArray(is));
assertEquals(proto, marshaller.parse(is));
}
@Test
public void testJsonMarshallerFailToPrint() {
Marshaller<Any> marshaller = ProtoUtils.jsonMarshaller(Any.getDefaultInstance());
try {
marshaller.stream(
Any.newBuilder().setValue(ByteString.copyFromUtf8("invalid (no type url)")).build());
fail("Expected exception");
} catch (StatusRuntimeException e) {
assertNotNull(e.getCause());
assertNotNull(e.getMessage());
assertEquals(Status.Code.INTERNAL, e.getStatus().getCode());
}
}
@Test
public void testJsonRepresentation() throws Exception {
Marshaller<Type> marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
InputStream is = marshaller.stream(proto);
String s = new String(ByteStreams.toByteArray(is), "UTF-8");
assertEquals("{\"name\":\"value\"}", s.replaceAll("\\s", ""));
}
@Ignore("https://github.com/google/protobuf/issues/1470")
@Test
public void testJsonInvalid() throws Exception {
Marshaller<Type> marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
try {
marshaller.parse(new ByteArrayInputStream("{]".getBytes("UTF-8")));
fail("Expected exception");
} catch (StatusRuntimeException ex) {
assertEquals(Status.Code.INTERNAL, ex.getStatus().getCode());
assertNotNull(ex.getCause());
}
}
@Test
public void testJsonInvalidProto() throws Exception {
Marshaller<Type> marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
try {
marshaller.parse(new ByteArrayInputStream("{\"\":3}".getBytes("UTF-8")));
fail("Expected exception");
} catch (StatusRuntimeException ex) {
assertEquals(Status.Code.INTERNAL, ex.getStatus().getCode());
assertNotNull(ex.getCause());
}
}
@Test
public void testJsonIoException() throws Exception {
Marshaller<Type> marshaller = ProtoUtils.jsonMarshaller(Type.getDefaultInstance());
final IOException ioe = new IOException();
try {
marshaller.parse(new ByteArrayInputStream("{}".getBytes("UTF-8")) {
@Override
public void close() throws IOException {
throw ioe;
}
});
fail("Exception expected");
} catch (StatusRuntimeException ex) {
assertEquals(Status.Code.INTERNAL, ex.getStatus().getCode());
assertEquals(ioe, ex.getCause());
}
}
}

View File

@ -16,6 +16,11 @@ description = "gRPC: Services"
dependencies {
compile project(':grpc-protobuf'),
project(':grpc-stub')
compile (libraries.protobuf_util) {
// prefer 20.0 from libraries instead of 19.0
exclude group: 'com.google.guava', module: 'guava'
}
compileOnly libraries.javax_annotation
testCompile project(':grpc-testing'),
libraries.netty_epoll // for DomainSocketAddress