Skip to content

Commit fb8580f

Browse files
mukundansundarartursouzatcnghia
authored
Update state, secrets examples. Fix state toString. Ignore sdk-autogen in code coverage. (dapr#340)
* Update state, secrets example. Fix state toString. Ignore sdk-autogen in code coverage. * Update StateClient.java * Update README.md * Update Readme.md Co-authored-by: Nghia Tran <tcnghia@gmail.com> Co-authored-by: Artur Souza <artursouza.ms@outlook.com> Co-authored-by: Nghia Tran <tcnghia@gmail.com>
1 parent 9240ae8 commit fb8580f

File tree

11 files changed

+258
-27
lines changed

11 files changed

+258
-27
lines changed

.codecov.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
ignore:
22
- examples
33
- sdk-tests
4+
- sdk-autogen
45
comment:
56
# Delete old comment and post new one for new coverage information.
67
behavior: new

.github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
build:
1818
runs-on: ubuntu-latest
1919
env:
20-
GOVER: 1.14.0
20+
GOVER: 1.15.0
2121
GOOS: linux
2222
GOARCH: amd64
2323
GOPROXY: https://proxy.golang.org

examples/src/main/java/io/dapr/examples/secrets/README.md

+51-6
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ mvn install
4141
```
4242
### Setting Vault locally
4343

44-
Before getting into the application code, follow these steps in order to setup a local instance of Vault. This is needed for the local instances. Steps are:
44+
Before getting into the application code, follow these steps in order to set up a local instance of Vault. This is needed for the local instances. Steps are:
4545

4646
1. navigate to the [examples] with `cd examples`
4747
2. Run `docker-compose -f ./src/main/java/io/dapr/examples/secrets/docker-compose-vault.yml up -d` to run the container locally
@@ -61,18 +61,23 @@ Dapr's API for secret store only support read operations. For this sample to run
6161
vault login myroot
6262
```
6363

64-
> Note: If you get `http: server gave HTTP response to HTTPS client` make sure the local vault address is set `export VAULT_ADDR=http://127.0.0.1:8200/`
64+
> Note: If you get `http: server gave HTTP response to HTTPS client` make sure to set the local vault address as `export VAULT_ADDR=http://127.0.0.1:8200/`
6565
6666
2. Create secret (replace `[my favorite movie]` with a title of our choice):
6767
```bash
6868
vault kv put secret/dapr/movie title="[my favorite movie]"
6969
```
7070

71+
3. Create random secret:
72+
```bash
73+
vault kv put secret/dapr/randomKey testVal="value"
74+
```
75+
7176
In the command above, `secret` means the secret engine in Hashicorp's Vault.
7277
Then, `dapr` is the prefix as defined in `< repo dir >/examples/components/hashicorp_vault.yaml`.
73-
Finally, `movie` is the secret name and then a `key=value` pair.
78+
Finally, `movie` and `randomKey` are the secret names with the value set in the form of `key=value` pair.
7479

75-
A secret in dapr is a dictionary. In this sample, only one key-value pair is used but more can be added as an exercise for the reader.
80+
A secret in Dapr is a dictionary.
7681

7782
### Running the secret store sample
7883

@@ -101,6 +106,13 @@ public class SecretClient {
101106
try (DaprClient client = (new DaprClientBuilder()).build()) {
102107
Map<String, String> secret = client.getSecret(SECRET_STORE_NAME, secretKey).block();
103108
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
109+
110+
try {
111+
secret = client.getSecret(SECRET_STORE_NAME, "randomKey").block();
112+
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
113+
} catch (Exception ex) {
114+
System.out.println(ex.getMessage());
115+
}
104116
}
105117
}
106118
///...
@@ -111,7 +123,7 @@ After identifying the key to be fetched, it will retrieve it from the pre-define
111123
The secret store's name **must** match the component's name defined in `< repo dir >/examples/components/hashicorp_vault.yaml`.
112124
The Dapr client is also within a try-with-resource block to properly close the client at the end.
113125

114-
Execute the follow script in order to run the example:
126+
Execute the following script in order to run the example:
115127
```sh
116128
cd to [repo-root]/examples
117129
dapr run --components-path ./components -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.secrets.SecretClient movie
@@ -121,11 +133,44 @@ Once running, the program should print the output as follows:
121133

122134
```
123135
== APP == {"title":"[my favorite movie]"}
136+
137+
== APP == {"testVal":"value"}
124138
```
125139

126140
To close the app, press CTRL+c.
127141

128-
To cleanup and bring the vault container down, run
142+
The example's `config.yaml` is as follows:
143+
```yaml
144+
apiVersion: dapr.io/v1alpha1
145+
kind: Configuration
146+
metadata:
147+
name: daprConfig
148+
spec:
149+
secrets:
150+
scopes:
151+
- storeName: "vault"
152+
defaultAccess: "deny"
153+
allowedSecrets: ["movie",]
154+
```
155+
156+
The configuration defines, that the only allowed secret is `movie` and all other secrets are denied.
157+
158+
Execute the following script in order to run this example with additional secret scoping:
159+
```sh
160+
cd to [repo-root]/examples
161+
dapr run --components-path ./components --config ./src/main/java/io/dapr/examples/secrets/config.yaml -- java -jar target/dapr-java-sdk-examples-exec.jar io.dapr.examples.secrets.SecretClient movie
162+
```
163+
Once running, the program should print the output as follows:
164+
165+
```
166+
== APP == {"title":"[my favorite movie]"}
167+
168+
== APP == java.util.concurrent.ExecutionException: io.grpc.StatusRuntimeException: PERMISSION_DENIED: Access denied by policy to get randomKey from vault
169+
```
170+
171+
To close the app, press CTRL+c.
172+
173+
To clean up and bring the vault container down, run
129174
```sh
130175
docker-compose -f ./src/main/java/io/dapr/examples/secrets/docker-compose-vault.yml down
131176
```

examples/src/main/java/io/dapr/examples/secrets/SecretClient.java

+7
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,13 @@ public static void main(String[] args) throws Exception {
4848
try (DaprClient client = (new DaprClientBuilder()).build()) {
4949
Map<String, String> secret = client.getSecret(SECRET_STORE_NAME, secretKey).block();
5050
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
51+
52+
try {
53+
secret = client.getSecret(SECRET_STORE_NAME, "randomKey").block();
54+
System.out.println(JSON_SERIALIZER.writeValueAsString(secret));
55+
} catch (Exception ex) {
56+
System.out.println(ex.getMessage());
57+
}
5158
}
5259
}
5360
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: dapr.io/v1alpha1
2+
kind: Configuration
3+
metadata:
4+
name: daprConfig
5+
spec:
6+
secrets:
7+
scopes:
8+
- storeName: "vault"
9+
defaultAccess: "deny"
10+
allowedSecrets: ["movie",]

examples/src/main/java/io/dapr/examples/state/README.md

+54-8
Original file line numberDiff line numberDiff line change
@@ -37,27 +37,61 @@ public class StateClient {
3737
///...
3838
private static final String STATE_STORE_NAME = "statestore";
3939

40-
private static final String KEY_NAME = "mykey";
40+
private static final String FIRST_KEY_NAME = "myKey";
41+
42+
private static final String SECOND_KEY_NAME = "myKey2";
4143
///...
4244
public static void main(String[] args) throws IOException {
4345
try (DaprClient client = new DaprClientBuilder().build()) {
4446
String message = args.length == 0 ? " " : args[0];
4547

4648
MyClass myClass = new MyClass();
4749
myClass.message = message;
50+
MyClass secondState = new MyClass();
51+
secondState.message = "test message";
4852

49-
client.saveState(STATE_STORE_NAME, KEY_NAME, myClass).block();
53+
client.saveState(STATE_STORE_NAME, FIRST_KEY_NAME, myClass).block();
5054
System.out.println("Saving class with message: " + message);
5155

52-
Mono<State<MyClass>> retrievedMessageMono = client.getState(STATE_STORE_NAME, KEY_NAME, MyClass.class);
56+
Mono<State<MyClass>> retrievedMessageMono = client.getState(STATE_STORE_NAME, FIRST_KEY_NAME, MyClass.class);
5357
System.out.println("Retrieved class message from state: " + (retrievedMessageMono.block().getValue()).message);
5458

55-
System.out.println("Deleting state...");
56-
Mono<Void> mono = client.deleteState(STATE_STORE_NAME, KEY_NAME);
59+
System.out.println("Updating previous state and adding another state 'test state'... ");
60+
myClass.message = message + " updated";
61+
System.out.println("Saving updated class with message: " + myClass.message);
62+
63+
// execute transaction
64+
List<TransactionalStateOperation<?>> operationList = new ArrayList<>();
65+
operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.UPSERT,
66+
new State<>(myClass, FIRST_KEY_NAME, "")));
67+
operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.UPSERT,
68+
new State<>(secondState, SECOND_KEY_NAME, "")));
69+
70+
client.executeTransaction(STATE_STORE_NAME, operationList).block();
71+
72+
// get multiple states
73+
Mono<List<State<MyClass>>> retrievedMessagesMono = client.getStates(STATE_STORE_NAME,
74+
Arrays.asList(FIRST_KEY_NAME, SECOND_KEY_NAME), MyClass.class);
75+
System.out.println("Retrieved messages using bulk get:");
76+
retrievedMessagesMono.block().forEach(System.out::println);
77+
78+
System.out.println("Deleting states...");
79+
80+
// delete state API
81+
Mono<Void> mono = client.deleteState(STATE_STORE_NAME, FIRST_KEY_NAME);
5782
mono.block();
5883

59-
Mono<State<MyClass>> retrievedDeletedMessageMono = client.getState(STATE_STORE_NAME, KEY_NAME, MyClass.class);
60-
System.out.println("Trying to retrieve deleted state: " + retrievedDeletedMessageMono.block().getValue());
84+
// Delete operation using transaction API
85+
operationList.clear();
86+
operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.DELETE,
87+
new State<>(SECOND_KEY_NAME)));
88+
mono = client.executeTransaction(STATE_STORE_NAME, operationList);
89+
mono.block();
90+
91+
Mono<List<State<MyClass>>> retrievedDeletedMessageMono = client.getStates(STATE_STORE_NAME,
92+
Arrays.asList(FIRST_KEY_NAME, SECOND_KEY_NAME), MyClass.class);
93+
System.out.println("Trying to retrieve deleted states: ");
94+
retrievedDeletedMessageMono.block().forEach(System.out::println);
6195

6296
// This is an example, so for simplicity we are just exiting here.
6397
// Normally a dapr app would be a web service and not exit main.
@@ -66,7 +100,19 @@ public class StateClient {
66100
}
67101
}
68102
```
69-
The code uses the `DaprClient` created by the `DaprClientBuilder`. Notice that this builder uses default settings. Internally, it is using `DefaultObjectSerializer` for two properties: `objectSerializer` is for Dapr's sent and received objects, and `stateSerializer` is for objects to be persisted. This client performs three operations: `client.saveState(...)` for persisting an instance of `MyClass`, then uses the `client.getState(...)` operation in order to retrieve back the persisted state using the same key. `client.deleteState(...)` operation is used to remove the persisted state. Finally, the code tries to retrieve the deleted state, which should not be found. The Dapr client is also within a try-with-resource block to properly close the client at the end.
103+
The code uses the `DaprClient` created by the `DaprClientBuilder`. Notice that this builder uses default settings. Internally, it is using `DefaultObjectSerializer` for two properties: `objectSerializer` is for Dapr's sent and received objects, and `stateSerializer` is for objects to be persisted.
104+
105+
This example performs multiple operations:
106+
* `client.saveState(...)` for persisting an instance of `MyClass`.
107+
* `client.getState(...)` operation in order to retrieve back the persisted state using the same key.
108+
* `client.executeTransaction(...)` operation in order to update existing state and add new state.
109+
* `client.getStates(...)` operation in order to retrieve back the persisted states using the same keys.
110+
* `client.deleteState(...)` operation to remove one of the persisted states.
111+
* `client.executeTransaction(...)` operation in order to remove the other persisted state.
112+
113+
Finally, the code tries to retrieve the deleted states, which should not be found.
114+
115+
The Dapr client is also within a try-with-resource block to properly close the client at the end.
70116

71117
### Running the example
72118

examples/src/main/java/io/dapr/examples/state/StateClient.java

+50-7
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,13 @@
88
import io.dapr.client.DaprClient;
99
import io.dapr.client.DaprClientBuilder;
1010
import io.dapr.client.domain.State;
11+
import io.dapr.client.domain.TransactionalStateOperation;
1112
import reactor.core.publisher.Mono;
1213

1314
import java.io.IOException;
15+
import java.util.ArrayList;
16+
import java.util.Arrays;
17+
import java.util.List;
1418

1519
/**
1620
* 1. Build and install jars:
@@ -24,11 +28,18 @@ public class StateClient {
2428

2529
public static class MyClass {
2630
public String message;
31+
32+
@Override
33+
public String toString() {
34+
return message;
35+
}
2736
}
2837

2938
private static final String STATE_STORE_NAME = "statestore";
3039

31-
private static final String KEY_NAME = "myKey";
40+
private static final String FIRST_KEY_NAME = "myKey";
41+
42+
private static final String SECOND_KEY_NAME = "myKey2";
3243

3344
/**
3445
* Executes the sate actions.
@@ -40,19 +51,51 @@ public static void main(String[] args) throws IOException {
4051

4152
MyClass myClass = new MyClass();
4253
myClass.message = message;
54+
MyClass secondState = new MyClass();
55+
secondState.message = "test message";
4356

44-
client.saveState(STATE_STORE_NAME, KEY_NAME, myClass).block();
57+
client.saveState(STATE_STORE_NAME, FIRST_KEY_NAME, myClass).block();
4558
System.out.println("Saving class with message: " + message);
4659

47-
Mono<State<MyClass>> retrievedMessageMono = client.getState(STATE_STORE_NAME, KEY_NAME, MyClass.class);
60+
Mono<State<MyClass>> retrievedMessageMono = client.getState(STATE_STORE_NAME, FIRST_KEY_NAME, MyClass.class);
4861
System.out.println("Retrieved class message from state: " + (retrievedMessageMono.block().getValue()).message);
4962

50-
System.out.println("Deleting state...");
51-
Mono<Void> mono = client.deleteState(STATE_STORE_NAME, KEY_NAME);
63+
System.out.println("Updating previous state and adding another state 'test state'... ");
64+
myClass.message = message + " updated";
65+
System.out.println("Saving updated class with message: " + myClass.message);
66+
67+
// execute transaction
68+
List<TransactionalStateOperation<?>> operationList = new ArrayList<>();
69+
operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.UPSERT,
70+
new State<>(myClass, FIRST_KEY_NAME, "")));
71+
operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.UPSERT,
72+
new State<>(secondState, SECOND_KEY_NAME, "")));
73+
74+
client.executeTransaction(STATE_STORE_NAME, operationList).block();
75+
76+
// get multiple states
77+
Mono<List<State<MyClass>>> retrievedMessagesMono = client.getStates(STATE_STORE_NAME,
78+
Arrays.asList(FIRST_KEY_NAME, SECOND_KEY_NAME), MyClass.class);
79+
System.out.println("Retrieved messages using bulk get:");
80+
retrievedMessagesMono.block().forEach(System.out::println);
81+
82+
System.out.println("Deleting states...");
83+
84+
// delete state API
85+
Mono<Void> mono = client.deleteState(STATE_STORE_NAME, FIRST_KEY_NAME);
86+
mono.block();
87+
88+
// Delete operation using transaction API
89+
operationList.clear();
90+
operationList.add(new TransactionalStateOperation<>(TransactionalStateOperation.OperationType.DELETE,
91+
new State<>(SECOND_KEY_NAME)));
92+
mono = client.executeTransaction(STATE_STORE_NAME, operationList);
5293
mono.block();
5394

54-
Mono<State<MyClass>> retrievedDeletedMessageMono = client.getState(STATE_STORE_NAME, KEY_NAME, MyClass.class);
55-
System.out.println("Trying to retrieve deleted state: " + retrievedDeletedMessageMono.block().getValue());
95+
Mono<List<State<MyClass>>> retrievedDeletedMessageMono = client.getStates(STATE_STORE_NAME,
96+
Arrays.asList(FIRST_KEY_NAME, SECOND_KEY_NAME), MyClass.class);
97+
System.out.println("Trying to retrieve deleted states: ");
98+
retrievedDeletedMessageMono.block().forEach(System.out::println);
5699

57100
// This is an example, so for simplicity we are just exiting here.
58101
// Normally a dapr app would be a web service and not exit main.
114 KB
Loading

sdk/src/main/java/io/dapr/client/domain/State.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ public String toString() {
214214
+ "value=" + value
215215
+ ", key='" + key + "'"
216216
+ ", etag='" + etag + "'"
217-
+ ", etag='" + error + "'"
218-
+ ", options={'" + (options != null ? options.toString() : null) + "}"
217+
+ ", error='" + error + "'"
218+
+ ", options={'" + (options != null ? options.toString() : null) + "'}"
219219
+ "}";
220220
}
221221
}

sdk/src/test/java/io/dapr/client/DaprClientGrpcTest.java

+10-3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import static org.junit.Assert.assertArrayEquals;
4646
import static org.junit.Assert.assertEquals;
4747
import static org.junit.Assert.assertFalse;
48+
import static org.junit.Assert.assertNotNull;
4849
import static org.junit.Assert.assertNull;
4950
import static org.junit.Assert.assertTrue;
5051
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -662,7 +663,9 @@ public void getStateStringValueNoOptionsTest() throws IOException {
662663
State<String> keyRequest = buildStateKey(null, key, etag, null);
663664
Mono<State<String>> result = adapter.getState(STATE_STORE_NAME, keyRequest, String.class);
664665
settableFuture.set(responseEnvelope);
665-
assertEquals(expectedState, result.block());
666+
State<String> res = result.block();
667+
assertNotNull(res);
668+
assertEquals(expectedState, res);
666669
}
667670

668671
@Test
@@ -705,7 +708,9 @@ public void getStateObjectValueWithOptionsTest() throws IOException {
705708
.thenReturn(settableFuture);
706709
Mono<State<MyObject>> result = adapter.getState(STATE_STORE_NAME, keyRequest, MyObject.class);
707710
settableFuture.set(responseEnvelope);
708-
assertEquals(expectedState, result.block());
711+
State<MyObject> res = result.block();
712+
assertNotNull(res);
713+
assertEquals(expectedState, res);
709714
}
710715

711716
@Test
@@ -731,7 +736,9 @@ public void getStateObjectValueWithMetadataTest() throws IOException {
731736
.thenReturn(settableFuture);
732737
Mono<Response<State<MyObject>>> result = adapter.getState(request, TypeRef.get(MyObject.class));
733738
settableFuture.set(responseEnvelope);
734-
assertEquals(expectedState, result.block().getObject());
739+
Response<State<MyObject>> res = result.block();
740+
assertNotNull(res);
741+
assertEquals(expectedState, res.getObject());
735742
}
736743

737744
@Test

0 commit comments

Comments
 (0)