Add content type metadata support in gRPC invoke service calls (#334)

* Add content type metadata support in gRPC invoke service calls

* Add content type to serializer, change tests accordingly

* Remove content type parameter

* Update InvokeServiceRequest.java

Co-authored-by: Mukundan Sundararajan <musundar@microsoft.com>
Co-authored-by: Artur Souza <artursouza.ms@outlook.com>
This commit is contained in:
Pruthvidhar R Dhodda 2020-09-13 16:38:30 -07:00 committed by GitHub
parent fe027d0c54
commit 361a0e48a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 69 additions and 6 deletions

View File

@ -17,7 +17,7 @@
<grpc.version>1.25.0</grpc.version>
<protobuf.version>3.11.0</protobuf.version>
<protoc.version>3.10.0</protoc.version>
<dapr.proto.baseurl>https://raw.githubusercontent.com/dapr/dapr/98365b1b9ade55e7cf46cbc2313f0625318c0977/dapr/proto</dapr.proto.baseurl>
<dapr.proto.baseurl>https://raw.githubusercontent.com/dapr/dapr/13ee06cb55f1da9b7f823c42672e689a3cbb9df3/dapr/proto</dapr.proto.baseurl>
<os-maven-plugin.version>1.6.2</os-maven-plugin.version>
<maven-dependency-plugin.version>3.1.1</maven-dependency-plugin.version>
<maven-antrun-plugin.version>1.8</maven-antrun-plugin.version>

View File

@ -44,4 +44,12 @@ public class JavaSerializer implements DaprObjectSerializer {
}
}
}
/**
* {@inheritDoc}
*/
@Override
public String getContentType() {
return "application/json";
}
}

View File

@ -101,6 +101,7 @@ abstract class AbstractDaprClient implements DaprClient {
.withBody(request)
.withHttpExtension(httpExtension)
.withMetadata(metadata)
.withContentType(objectSerializer.getContentType())
.build();
return this.invokeService(req, type).map(r -> r.getObject());
@ -392,6 +393,8 @@ abstract class AbstractDaprClient implements DaprClient {
.putAllQuerystring(httpExtension.getQueryString());
requestBuilder.setHttpExtension(httpExtensionBuilder.build());
requestBuilder.setContentType(objectSerializer.getContentType());
DaprProtos.InvokeServiceRequest.Builder envelopeBuilder = DaprProtos.InvokeServiceRequest.newBuilder()
.setId(appId)
.setMessage(requestBuilder.build());

View File

@ -465,4 +465,4 @@ public interface DaprClient extends Closeable {
* @return Key-value pairs for the secret.
*/
Mono<Response<Map<String, String>>> getSecret(GetSecretRequest request);
}
}

View File

@ -61,6 +61,10 @@ public class DaprClientBuilder {
throw new IllegalArgumentException("Object serializer is required");
}
if (objectSerializer.getContentType() == null || objectSerializer.getContentType().isBlank()) {
throw new IllegalArgumentException("Content Type should not be null or blank");
}
this.objectSerializer = objectSerializer;
return this;
}

View File

@ -155,10 +155,12 @@ public class DaprClientGrpc extends AbstractDaprClient {
String method = invokeServiceRequest.getMethod();
Object request = invokeServiceRequest.getBody();
HttpExtension httpExtension = invokeServiceRequest.getHttpExtension();
// TODO(artursouza): handle metadata once available in GRPC proto.
// Map<String, String> metadata = invokeServiceRequest.getMetadata();
Context context = invokeServiceRequest.getContext();
DaprProtos.InvokeServiceRequest envelope = buildInvokeServiceRequest(httpExtension, appId, method, request);
DaprProtos.InvokeServiceRequest envelope = buildInvokeServiceRequest(
httpExtension,
appId,
method,
request);
return Mono.fromCallable(wrap(context, () -> {
ListenableFuture<CommonProtos.InvokeResponse> futureResponse =
client.invokeService(envelope);
@ -391,7 +393,10 @@ public class DaprClientGrpc extends AbstractDaprClient {
* @throws IOException If there's an issue serializing the request.
*/
private <K> DaprProtos.InvokeServiceRequest buildInvokeServiceRequest(
HttpExtension httpExtension, String appId, String method, K request) throws IOException {
HttpExtension httpExtension,
String appId,
String method,
K request) throws IOException {
if (httpExtension == null) {
throw new IllegalArgumentException("HttpExtension cannot be null. Use HttpExtension.NONE instead.");
}
@ -409,6 +414,8 @@ public class DaprClientGrpc extends AbstractDaprClient {
.putAllQuerystring(httpExtension.getQueryString());
requestBuilder.setHttpExtension(httpExtensionBuilder.build());
requestBuilder.setContentType(objectSerializer.getContentType());
DaprProtos.InvokeServiceRequest.Builder envelopeBuilder = DaprProtos.InvokeServiceRequest.newBuilder()
.setId(appId)
.setMessage(requestBuilder.build());

View File

@ -26,6 +26,8 @@ public class InvokeServiceRequest {
private Context context;
private String contentType;
public String getAppId() {
return appId;
}
@ -73,4 +75,12 @@ public class InvokeServiceRequest {
void setContext(Context context) {
this.context = context;
}
public String getContentType() {
return contentType;
}
void setContentType(String contentType) {
this.contentType = contentType;
}
}

View File

@ -20,6 +20,8 @@ public class InvokeServiceRequestBuilder {
private final String method;
private String contentType;
private Object body;
private Map<String, String> metadata = new HashMap<>();
@ -33,6 +35,11 @@ public class InvokeServiceRequestBuilder {
this.method = method;
}
public InvokeServiceRequestBuilder withContentType(String contentType) {
this.contentType = contentType;
return this;
}
public InvokeServiceRequestBuilder withBody(Object body) {
this.body = body;
return this;
@ -60,6 +67,7 @@ public class InvokeServiceRequestBuilder {
public InvokeServiceRequest build() {
InvokeServiceRequest request = new InvokeServiceRequest();
request.setAppId(this.appId);
request.setContentType(contentType);
request.setMethod(this.method);
request.setBody(this.body);
request.setHttpExtension(this.httpExtension);

View File

@ -33,4 +33,11 @@ public interface DaprObjectSerializer {
* @throws IOException If cannot deserialize object.
*/
<T> T deserialize(byte[] data, TypeRef<T> type) throws IOException;
/**
* Returns the content type of the request.
*
* @return content type of the request
*/
String getContentType();
}

View File

@ -30,4 +30,12 @@ public class DefaultObjectSerializer extends ObjectSerializer implements DaprObj
public <T> T deserialize(byte[] data, TypeRef<T> type) throws IOException {
return super.deserialize(data, type);
}
/**
* {@inheritDoc}
*/
@Override
public String getContentType() {
return "application/json";
}
}

View File

@ -10,12 +10,14 @@ import org.junit.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class DaprClientBuilderTest {
@Test
public void build() {
DaprObjectSerializer objectSerializer = mock(DaprObjectSerializer.class);
when(objectSerializer.getContentType()).thenReturn("application/json");
DaprObjectSerializer stateSerializer = mock(DaprObjectSerializer.class);
DaprClientBuilder daprClientBuilder = new DaprClientBuilder();
daprClientBuilder.withObjectSerializer(objectSerializer);
@ -29,6 +31,11 @@ public class DaprClientBuilderTest {
new DaprClientBuilder().withObjectSerializer(null);
}
@Test(expected = IllegalArgumentException.class)
public void blankContentTypeInObjectSerializer() {
new DaprClientBuilder().withObjectSerializer(mock(DaprObjectSerializer.class));
}
@Test(expected = IllegalArgumentException.class)
public void noStateSerializer() {
new DaprClientBuilder().withStateSerializer(null);

View File

@ -364,6 +364,7 @@ public class DaprClientGrpcTest {
CommonProtos.InvokeRequest message = CommonProtos.InvokeRequest.newBuilder()
.setMethod("method")
.setData(getAny("request"))
.setContentType("application/json")
.setHttpExtension(CommonProtos.HTTPExtension.newBuilder()
.setVerb(CommonProtos.HTTPExtension.Verb.GET)
.putQuerystring("test", "1").build())