mirror of https://github.com/grpc/grpc-java.git
protobuf,examples: move json encoding to examples
This commit is contained in:
parent
e085a0eca0
commit
e3f8891f57
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue