Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions sdk/src/main/java/io/dapr/client/DaprClientGrpcAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ public <T, K> Mono<T> invokeService(String verb, String appId, String method, K

/**
* Operation not supported for GRPC
*
* TODO: Implement this since this IS supported.
* @throws UnsupportedOperationException every time is called.
*/
public <T> Mono<Void> invokeService(String verb, String appId, String method, T request) {
Expand Down Expand Up @@ -198,6 +200,9 @@ public <T> Mono<Void> saveStates(List<StateKeyValue<T>> states, StateOptions opt
}
}

/**
* {@inheritDoc}
*/
@Override
public <T> Mono<Void> saveState(String key, String etag, T value, StateOptions options) {
StateKeyValue<T> state = new StateKeyValue<>(value, key, etag);
Expand Down Expand Up @@ -238,38 +243,70 @@ public Mono<String> invokeActorMethod(String actorType, String actorId, String m
return Mono.error(new UnsupportedOperationException("Operation not supported for GRPC"));
}

/**
* Operation not supported for GRPC
* @throws UnsupportedOperationException every time is called.
*/
@Override
public Mono<String> getActorState(String actorType, String actorId, String keyName) {
return Mono.error(new UnsupportedOperationException("Operation not supported for GRPC"));
}

/**
* Operation not supported for GRPC
* @throws UnsupportedOperationException every time is called.
*/
@Override
public Mono<Void> saveActorStateTransactionally(String actorType, String actorId, String data) {
return Mono.error(new UnsupportedOperationException("Operation not supported for GRPC"));
}

/**
* Operation not supported for GRPC
* @throws UnsupportedOperationException every time is called.
*/
@Override
public Mono<Void> registerActorReminder(String actorType, String actorId, String reminderName, String data) {
return Mono.error(new UnsupportedOperationException("Operation not supported for GRPC"));
}

/**
* Operation not supported for GRPC
* @throws UnsupportedOperationException every time is called.
*/
@Override
public Mono<Void> unregisterActorReminder(String actorType, String actorId, String reminderName) {
return Mono.error(new UnsupportedOperationException("Operation not supported for GRPC"));
}

/**
* Operation not supported for GRPC
* @throws UnsupportedOperationException every time is called.
*/
@Override
public Mono<Void> registerActorTimer(String actorType, String actorId, String timerName, String data) {
return Mono.error(new UnsupportedOperationException("Operation not supported for GRPC"));
}

/**
* Operation not supported for GRPC
* @throws UnsupportedOperationException every time is called.
*/
@Override
public Mono<Void> unregisterActorTimer(String actorType, String actorId, String timerName) {
return Mono.error(new UnsupportedOperationException("Operation not supported for GRPC"));
}

/**
* Converts state options to map.
*
* TODO: Move this logic to StateOptions.
* @param options Instance to have is methods converted into map.
* @return Map for the state options.
* @throws IllegalAccessException Cannot extract params.
*/
private Map<String, Object> transformStateOptionsToMap(StateOptions options)
throws IllegalAccessException, IllegalArgumentException {
throws IllegalAccessException {
Map<String, Object> mapOptions = null;
if (options != null) {
mapOptions = new HashMap<>();
Expand All @@ -283,8 +320,17 @@ private Map<String, Object> transformStateOptionsToMap(StateOptions options)
return mapOptions;
}

/**
* Creates an map for the given key-value operation.
*
* // TODO: Move this logic into StateKeyValue.
* @param state Key value for the state change.
* @param mapOptions Options to be applied to this operation.
* @return Map for the key-value operation.
* @throws IllegalAccessException Cannot identify key-value attributes.
*/
private Map<String, Object> transformStateKeyValueToMap(StateKeyValue state, Map<String, Object> mapOptions)
throws IllegalAccessException, IllegalArgumentException {
throws IllegalAccessException {
Map<String, Object> mapState = new HashMap<>();
for (Field field : state.getClass().getFields()) {
mapState.put(field.getName(), field.get(state));
Expand Down
77 changes: 58 additions & 19 deletions sdk/src/main/java/io/dapr/client/DaprClientHttpAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,11 @@
import io.dapr.utils.ObjectSerializer;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
* An adapter for the GRPC Client.
Expand Down Expand Up @@ -67,7 +65,7 @@ public <T> Mono<Void> publishEvent(String topic, T event, Map<String, String> me
byte[] serializedEvent = objectSerializer.serialize(event);
StringBuilder url = new StringBuilder(Constants.PUBLISH_PATH).append("/").append(topic);
return this.client.invokeAPI(
Constants.defaultHttpMethodSupported.POST.name(), url.toString(), serializedEvent, metadata).then();
DaprHttp.HttpMethods.POST.name(), url.toString(), serializedEvent, metadata).then();
} catch (Exception ex) {
return Mono.error(ex);
}
Expand All @@ -82,7 +80,7 @@ public <T, K> Mono<T> invokeService(String verb, String appId, String method, K
if (verb == null || verb.trim().isEmpty()) {
throw new DaprException("500", "App Id cannot be null or empty.");
}
Constants.defaultHttpMethodSupported httMethod = Constants.defaultHttpMethodSupported.valueOf(verb.toUpperCase());
DaprHttp.HttpMethods httMethod = DaprHttp.HttpMethods.valueOf(verb.toUpperCase());
if (httMethod == null) {
throw new DaprException("405", "HTTP Method not allowed.");
}
Expand Down Expand Up @@ -116,7 +114,7 @@ public <T> Mono<Void> invokeService(String verb, String appId, String method, T
if (verb == null || verb.trim().isEmpty()) {
throw new DaprException("500", "App Id cannot be null or empty.");
}
Constants.defaultHttpMethodSupported httMethod = Constants.defaultHttpMethodSupported.valueOf(verb.toUpperCase());
DaprHttp.HttpMethods httMethod = DaprHttp.HttpMethods.valueOf(verb.toUpperCase());
if (httMethod == null) {
throw new DaprException("405", "HTTP Method not allowed.");
}
Expand Down Expand Up @@ -151,7 +149,7 @@ public <T> Mono<Void> invokeBinding(String name, T request) {
StringBuilder url = new StringBuilder(Constants.BINDING_PATH).append("/").append(name);
return this.client
.invokeAPI(
Constants.defaultHttpMethodSupported.POST.name(),
DaprHttp.HttpMethods.POST.name(),
url.toString(),
objectSerializer.serialize(jsonMap),
null)
Expand Down Expand Up @@ -180,7 +178,7 @@ public <T, K> Mono<T> getState(StateKeyValue<K> state, StateOptions options, Cla
.append(state.getKey())
.append(getOptionsAsQueryParameter(options));
return this.client
.invokeAPI(Constants.defaultHttpMethodSupported.GET.name(), url.toString(), headers)
.invokeAPI(DaprHttp.HttpMethods.GET.name(), url.toString(), headers)
.flatMap(s -> {
try {
return Mono.just(objectSerializer.deserialize(s, clazz));
Expand Down Expand Up @@ -211,12 +209,15 @@ public <T> Mono<Void> saveStates(List<StateKeyValue<T>> states, StateOptions opt
String url = Constants.STATE_PATH + getOptionsAsQueryParameter(options);;
byte[] serializedStateBody = objectSerializer.serialize(states);
return this.client.invokeAPI(
Constants.defaultHttpMethodSupported.POST.name(), url, serializedStateBody, headers).then();
DaprHttp.HttpMethods.POST.name(), url, serializedStateBody, headers).then();
} catch (Exception ex) {
return Mono.error(ex);
}
}

/**
* {@inheritDoc}
*/
@Override
public <T> Mono<Void> saveState(String key, String etag, T value, StateOptions options) {
StateKeyValue<T> state = new StateKeyValue<>(value, key, etag);
Expand All @@ -237,70 +238,108 @@ public <T> Mono<Void> deleteState(StateKeyValue<T> state, StateOptions options)
headers.put(Constants.HEADER_HTTP_ETAG_ID, state.getEtag());
}
String url = Constants.STATE_PATH + "/" + state.getKey() + getOptionsAsQueryParameter(options);
return this.client.invokeAPI(Constants.defaultHttpMethodSupported.DELETE.name(), url, headers).then();
return this.client.invokeAPI(DaprHttp.HttpMethods.DELETE.name(), url, headers).then();
} catch (Exception ex) {
return Mono.error(ex);
}
}

/**
* {@inheritDoc}
*/
@Override
public Mono<String> invokeActorMethod(String actorType, String actorId, String methodName, String jsonPayload) {
String url = String.format(Constants.ACTOR_METHOD_RELATIVE_URL_FORMAT, actorType, actorId, methodName);
return this.client.invokeAPI(Constants.defaultHttpMethodSupported.POST.name(), url, jsonPayload, null);
return this.client.invokeAPI(DaprHttp.HttpMethods.POST.name(), url, jsonPayload, null);
}

/**
* {@inheritDoc}
*/
@Override
public Mono<String> getActorState(String actorType, String actorId, String keyName) {
String url = String.format(Constants.ACTOR_STATE_KEY_RELATIVE_URL_FORMAT, actorType, actorId, keyName);
return this.client.invokeAPI(Constants.defaultHttpMethodSupported.GET.name(), url, "", null);
return this.client.invokeAPI(DaprHttp.HttpMethods.GET.name(), url, "", null);
}

/**
* {@inheritDoc}
*/
@Override
public Mono<Void> saveActorStateTransactionally(String actorType, String actorId, String data) {
String url = String.format(Constants.ACTOR_STATE_RELATIVE_URL_FORMAT, actorType, actorId);
return this.client.invokeAPI(Constants.defaultHttpMethodSupported.PUT.name(), url, data, null).then();
return this.client.invokeAPI(DaprHttp.HttpMethods.PUT.name(), url, data, null).then();
}

/**
* {@inheritDoc}
*/
@Override
public Mono<Void> registerActorReminder(String actorType, String actorId, String reminderName, String data) {
String url = String.format(Constants.ACTOR_REMINDER_RELATIVE_URL_FORMAT, actorType, actorId, reminderName);
return this.client.invokeAPI(Constants.defaultHttpMethodSupported.PUT.name(), url, data, null).then();
return this.client.invokeAPI(DaprHttp.HttpMethods.PUT.name(), url, data, null).then();
}

/**
* {@inheritDoc}
*/
@Override
public Mono<Void> unregisterActorReminder(String actorType, String actorId, String reminderName) {
String url = String.format(Constants.ACTOR_REMINDER_RELATIVE_URL_FORMAT, actorType, actorId, reminderName);
return this.client.invokeAPI(Constants.defaultHttpMethodSupported.DELETE.name(), url, null).then();
return this.client.invokeAPI(DaprHttp.HttpMethods.DELETE.name(), url, null).then();
}

/**
* {@inheritDoc}
*/
@Override
public Mono<Void> registerActorTimer(String actorType, String actorId, String timerName, String data) {
String url = String.format(Constants.ACTOR_TIMER_RELATIVE_URL_FORMAT, actorType, actorId, timerName);
return this.client.invokeAPI(Constants.defaultHttpMethodSupported.PUT.name(), url, data, null).then();
return this.client.invokeAPI(DaprHttp.HttpMethods.PUT.name(), url, data, null).then();
}

/**
* {@inheritDoc}
*/
@Override
public Mono<Void> unregisterActorTimer(String actorType, String actorId, String timerName) {
String url = String.format(Constants.ACTOR_TIMER_RELATIVE_URL_FORMAT, actorType, actorId, timerName);
return this.client.invokeAPI(Constants.defaultHttpMethodSupported.DELETE.name(), url, null).then();
return this.client.invokeAPI(DaprHttp.HttpMethods.DELETE.name(), url, null).then();
}

/**
* Gets the string with params for a given URL.
*
* TODO: Move this logic down the stack to use okhttp's builder instead:
* https://square.github.io/okhttp/4.x/okhttp/okhttp3/-http-url/-builder/add-query-parameter/
* @param options State options to be converted.
* @return String with query params.
* @throws IllegalAccessException Cannot extract params.
*/
private String getOptionsAsQueryParameter(StateOptions options)
throws IllegalAccessException, IllegalArgumentException, IOException {
throws IllegalAccessException {
StringBuilder sb = new StringBuilder();
Map<String, Object> mapOptions = transformStateOptionsToMap(options);
if (mapOptions != null && !mapOptions.isEmpty()) {
sb.append("?");
for (Map.Entry<String, Object> option : mapOptions.entrySet()) {
sb.append(option.getKey()).append("=").append(objectSerializer.serialize(option.getValue())).append("&");
sb.append(option.getKey()).append("=").append(option.getValue()).append("&");
}
sb.deleteCharAt(sb.length()-1);
}
return sb.toString();
}

/**
* Converts state options to map.
*
* TODO: Move this logic to StateOptions.
* @param options Instance to have is methods converted into map.
* @return Map for the state options.
* @throws IllegalAccessException Cannot extract params.
*/
private Map<String, Object> transformStateOptionsToMap(StateOptions options)
throws IllegalAccessException, IllegalArgumentException {
throws IllegalAccessException {
Map<String, Object> mapOptions = null;
if (options != null) {
mapOptions = new HashMap<>();
Expand Down
15 changes: 10 additions & 5 deletions sdk/src/main/java/io/dapr/client/DaprHttp.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@

class DaprHttp {

/**
* HTTP Methods supported.
*/
enum HttpMethods { GET, PUT, POST, DELETE; }

/**
* Defines the standard application/json type for HTTP calls in Dapr.
*/
Expand Down Expand Up @@ -83,7 +88,7 @@ class DaprHttp {
* @param urlString url as String.
* @return Asynchronous text
*/
public final Mono<String> invokeAPI(String method, String urlString, Map<String, String> headers) {
public Mono<String> invokeAPI(String method, String urlString, Map<String, String> headers) {
return this.invokeAPI(method, urlString, (byte[])null, headers);
}

Expand All @@ -95,7 +100,7 @@ public final Mono<String> invokeAPI(String method, String urlString, Map<String,
* @param content payload to be posted.
* @return Asynchronous text
*/
public final Mono<String> invokeAPI(String method, String urlString, String content, Map<String, String> headers) {
public Mono<String> invokeAPI(String method, String urlString, String content, Map<String, String> headers) {
return this.invokeAPI(method, urlString, content == null ? EMPTY_BYTES : content.getBytes(StandardCharsets.UTF_8), headers);
}

Expand All @@ -107,7 +112,7 @@ public final Mono<String> invokeAPI(String method, String urlString, String cont
* @param content payload to be posted.
* @return Asynchronous text
*/
public final Mono<String> invokeAPI(String method, String urlString, byte[] content, Map<String, String> headers) {
public Mono<String> invokeAPI(String method, String urlString, byte[] content, Map<String, String> headers) {
return Mono.fromFuture(CompletableFuture.supplyAsync(
() -> {
try {
Expand All @@ -126,9 +131,9 @@ public final Mono<String> invokeAPI(String method, String urlString, byte[] cont
Request.Builder requestBuilder = new Request.Builder()
.url(new URL(this.baseUrl + urlString))
.addHeader(Constants.HEADER_DAPR_REQUEST_ID, requestId);
if (Constants.defaultHttpMethodSupported.GET.name().equals(method)) {
if (HttpMethods.GET.name().equals(method)) {
requestBuilder.get();
} else if (Constants.defaultHttpMethodSupported.DELETE.name().equals(method)) {
} else if (HttpMethods.DELETE.name().equals(method)) {
requestBuilder.delete();
} else {
requestBuilder.method(method, body);
Expand Down
1 change: 1 addition & 0 deletions sdk/src/main/java/io/dapr/client/domain/StateOptions.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.dapr.client.domain;

public class StateOptions {

private final String consistency;

public StateOptions(String consistency) {
Expand Down
Loading