diff --git a/.gitignore b/.gitignore index 323dad2409..474c650f34 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,5 @@ hs_err_pid* # Some other generated folders/files **/components/redis.yaml **/components/redis_messagebus.yaml +/proto/dapr +/proto/daprclient diff --git a/pom.xml b/pom.xml index fba7e3506b..eeae23bf6b 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,8 @@ 1.25.0 3.11.0 3.10.0 + https://raw.githubusercontent.com/dapr/dapr/master/pkg/proto/dapr/dapr.proto + https://raw.githubusercontent.com/dapr/dapr/master/pkg/proto/daprclient/daprclient.proto 1.6.2 3.1.1 1.8 diff --git a/proto/dapr/dapr.proto b/proto/dapr/dapr.proto deleted file mode 100644 index b87d0f4fc9..0000000000 --- a/proto/dapr/dapr.proto +++ /dev/null @@ -1,106 +0,0 @@ -syntax = "proto3"; - -package dapr; - -import "google/protobuf/any.proto"; -import "google/protobuf/empty.proto"; -import "google/protobuf/duration.proto"; - -option java_outer_classname = "DaprProtos"; -option java_package = "io.dapr"; - -option csharp_namespace = "Dapr.Client.Grpc"; - - -// Dapr definitions -service Dapr { - rpc PublishEvent(PublishEventEnvelope) returns (google.protobuf.Empty) {} - rpc InvokeService(InvokeServiceEnvelope) returns (InvokeServiceResponseEnvelope) {} - rpc InvokeBinding(InvokeBindingEnvelope) returns (google.protobuf.Empty) {} - rpc GetState(GetStateEnvelope) returns (GetStateResponseEnvelope) {} - rpc SaveState(SaveStateEnvelope) returns (google.protobuf.Empty) {} - rpc DeleteState(DeleteStateEnvelope) returns (google.protobuf.Empty) {} -} - -message InvokeServiceResponseEnvelope { - google.protobuf.Any data = 1; - map metadata = 2; -} - -message DeleteStateEnvelope { - string key = 1; - string etag = 2; - StateOptions options = 3; -} - -message SaveStateEnvelope { - repeated StateRequest requests = 1; -} - -message GetStateEnvelope { - string key = 1; - string consistency = 2; -} - -message GetStateResponseEnvelope { - google.protobuf.Any data = 1; - string etag = 2; -} - -message InvokeBindingEnvelope { - string name = 1; - google.protobuf.Any data = 2; - map metadata = 3; -} - -message InvokeServiceEnvelope { - string id = 1; - string method = 2; - google.protobuf.Any data = 3; - map metadata = 4; -} - -message PublishEventEnvelope { - string topic = 1; - google.protobuf.Any data = 2; -} - -message State { - string key = 1; - google.protobuf.Any value = 2; - string etag = 3; - map metadata = 4; - StateOptions options = 5; -} - -message StateOptions { - string concurrency = 1; - string consistency = 2; - RetryPolicy retryPolicy = 3; -} - -message RetryPolicy { - int32 threshold = 1; - string pattern = 2; - google.protobuf.Duration interval = 3; -} - -message StateRequest { - string key = 1; - google.protobuf.Any value = 2; - string etag = 3; - map metadata = 4; - StateRequestOptions options = 5; -} - -message StateRequestOptions { - string concurrency = 1; - string consistency = 2; - StateRetryPolicy retryPolicy = 3; -} - -message StateRetryPolicy { - int32 threshold = 1; - string pattern = 2; - google.protobuf.Duration interval = 3; -} diff --git a/proto/daprclient/daprclient.proto b/proto/daprclient/daprclient.proto deleted file mode 100644 index a383ba16c5..0000000000 --- a/proto/daprclient/daprclient.proto +++ /dev/null @@ -1,76 +0,0 @@ -syntax = "proto3"; - -package daprclient; - -import "google/protobuf/any.proto"; -import "google/protobuf/empty.proto"; -import "google/protobuf/duration.proto"; - -option java_outer_classname = "DaprClientProtos"; -option java_package = "io.dapr"; - -// User Code definitions -service DaprClient { - rpc OnInvoke (InvokeEnvelope) returns (google.protobuf.Any) {} - rpc GetTopicSubscriptions(google.protobuf.Empty) returns (GetTopicSubscriptionsEnvelope) {} - rpc GetBindingsSubscriptions(google.protobuf.Empty) returns (GetBindingsSubscriptionsEnvelope) {} - rpc OnBindingEvent(BindingEventEnvelope) returns (BindingResponseEnvelope) {} - rpc OnTopicEvent(CloudEventEnvelope) returns (google.protobuf.Empty) {} -} - -message CloudEventEnvelope { - string id = 1; - string source = 2; - string type = 3; - string specVersion = 4; - string dataContentType = 5; - string topic = 6; - google.protobuf.Any data = 7; -} - -message BindingEventEnvelope { - string name = 1; - google.protobuf.Any data = 2; - map metadata = 3; -} - -message BindingResponseEnvelope { - google.protobuf.Any data = 1; - repeated string to = 2; - repeated State state = 3; - string concurrency = 4; -} - -message InvokeEnvelope { - string method = 1; - google.protobuf.Any data = 2; - map metadata = 3; -} - -message GetTopicSubscriptionsEnvelope { - repeated string topics = 1; -} - -message GetBindingsSubscriptionsEnvelope { - repeated string bindings = 1; -} - -message State { - string key = 1; - google.protobuf.Any value = 2; - string etag = 3; - map metadata = 4; - StateOptions options = 5; -} - -message StateOptions { - string concurrency = 1; - string consistency = 2; - RetryPolicy retryPolicy = 3; -} - -message RetryPolicy { - int32 threshold = 1; - string pattern = 2; - google.protobuf.Duration interval = 3; -} diff --git a/sdk-autogen/pom.xml b/sdk-autogen/pom.xml index 6d9bfe4355..56fbf91f2a 100644 --- a/sdk-autogen/pom.xml +++ b/sdk-autogen/pom.xml @@ -56,6 +56,41 @@ + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.3.0 + + + getDaprProto + + initialize + + wget + + + ${dapr.proto.url} + dapr.proto + + ${protobuf.input.directory}/dapr + + + + getDaprClientProto + + initialize + + wget + + + ${dapr.client.proto.url} + daprclient.proto + + ${protobuf.input.directory}/daprclient + + + + com.github.os72 protoc-jar-maven-plugin diff --git a/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeController.java b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeController.java new file mode 100644 index 0000000000..8f1a676ee5 --- /dev/null +++ b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeController.java @@ -0,0 +1,72 @@ +package io.dapr.it.methodinvoke.http; + +import org.springframework.web.bind.annotation.*; + +import java.util.*; + +/** + * SpringBoot Controller to handle input binding. + */ +@RestController +public class MethodInvokeController { + + private static final Map messagesReceived = new HashMap<>(); + private static final List persons= new ArrayList<>(); + + @PostMapping("/messages") + public void postMessages(@RequestBody String message){ + System.out.println("Controller got message: " + message); + final Optional maxKey = messagesReceived.keySet().stream().max(Integer::compareTo); + final Integer key = maxKey.orElse(-1)+1; + messagesReceived.put(key,message); + System.out.println("Controller save the message: " + message); + } + + @PutMapping(path = "/messages/{messageId}") + public void putMessages(@PathVariable Integer messageId, @RequestBody String message){ + messagesReceived.put(messageId,message); + } + + @DeleteMapping(path = "/messages/{messageId}") + public void deleteMessages(@PathVariable Integer messageId){ + messagesReceived.remove(messageId); + } + + @GetMapping(path = "/messages") + public Map getMessages() { + return messagesReceived; + } + + @PostMapping("/persons") + public void postPerson(@RequestBody Person person){ + System.out.println("Controller get person: " + person); + final Optional max = persons.stream().map(person1 -> person1.getId()).max(Integer::compareTo); + final Integer key = max.orElse(-1)+1; + person.setId(key); + persons.add(person); + System.out.println("Controller save the person: " + person); + } + + @PutMapping(path = "/persons/{personId}") + public void putPerson(@PathVariable Integer personId, @RequestBody Person person){ + final Optional auxPerson = persons.stream().filter(person1 -> person1.getId() == personId).findFirst(); + if(auxPerson.isPresent()){ + auxPerson.get().setName(person.getName()); + auxPerson.get().setLastName(person.getLastName()); + auxPerson.get().setBirthDate(person.getBirthDate()); + } + } + + @DeleteMapping(path = "/persons/{personId}") + public void deletePerson(@PathVariable Integer personId){ + final Optional auxPerson = persons.stream().filter(person1 -> person1.getId() == personId).findFirst(); + if(auxPerson.isPresent()) { + persons.remove(auxPerson.get()); + } + } + + @GetMapping(path = "/persons") + public List getPersons() { + return persons; + } +} diff --git a/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeIT.java b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeIT.java new file mode 100644 index 0000000000..67ab3d16ca --- /dev/null +++ b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeIT.java @@ -0,0 +1,94 @@ +package io.dapr.it.methodinvoke.http; + +import io.dapr.client.DaprClient; +import io.dapr.client.DaprClientBuilder; +import io.dapr.client.domain.Verb; +import io.dapr.it.BaseIT; +import io.dapr.it.DaprRun; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class MethodInvokeIT extends BaseIT { + + //Number of messages to be sent: 10 + private static final int NUM_MESSAGES = 10; + private static DaprRun daprRun=null; + + @BeforeClass + public static void init() throws Exception { + System.out.println("Working Directory = " + System.getProperty("user.dir")); + + daprRun = startDaprApp( + MethodInvokeIT.class.getSimpleName(), + MethodInvokeService.SUCCESS_MESSAGE, + MethodInvokeService.class, + true, + 60000); + } + + @Test + public void testInvoke() { + + // At this point, it is guaranteed that the service above is running and all ports being listened to. + + DaprClient client = new DaprClientBuilder().build(); + for (int i = 0; i < NUM_MESSAGES; i++) { + String message = String.format("This is message #%d", i); + //Publishing messages + client.invokeService(Verb.POST, daprRun.getAppName(), "messages", message).block(); + System.out.println("Invoke method messages : " + message); + } + + Map messages = client.invokeService(Verb.GET, daprRun.getAppName(), "messages", null, Map.class).block(); + assertEquals(10, messages.size()); + + client.invokeService(Verb.DELETE,daprRun.getAppName(),"messages/1",null).block(); + + messages = client.invokeService(Verb.GET, daprRun.getAppName(), "messages", null, Map.class).block(); + assertEquals(9, messages.size()); + + client.invokeService(Verb.PUT, daprRun.getAppName(), "messages/2", "updated message").block(); + messages = client.invokeService(Verb.GET, daprRun.getAppName(), "messages", null, Map.class).block(); + assertEquals("updated message", messages.get("2")); + + } + + @Test + public void testInvokeWithObjects() { + DaprClient client = new DaprClientBuilder().build(); + + for (int i = 0; i < NUM_MESSAGES; i++) { + Person person= new Person(); + person.setName(String.format("Name %d", i)); + person.setLastName(String.format("Last Name %d", i)); + person.setBirthDate(new Date()); + //Publishing messages + client.invokeService(Verb.POST, daprRun.getAppName(), "persons", person).block(); + System.out.println("Invoke method persons with parameter : " + person); + } + + List persons = Arrays.asList(client.invokeService(Verb.GET, daprRun.getAppName(), "persons", null, Person[].class).block()); + assertEquals(10, persons.size()); + + client.invokeService(Verb.DELETE,daprRun.getAppName(),"persons/1",null).block(); + + persons = Arrays.asList(client.invokeService(Verb.GET, daprRun.getAppName(), "persons", null, Person[].class).block()); + assertEquals(9, persons.size()); + + Person person= new Person(); + person.setName("John"); + person.setLastName("Smith"); + person.setBirthDate(Calendar.getInstance().getTime()); + + client.invokeService(Verb.PUT, daprRun.getAppName(), "persons/2", person).block(); + + persons = Arrays.asList(client.invokeService(Verb.GET, daprRun.getAppName(), "persons", null, Person[].class).block()); + Person resultPerson= persons.get(1); + assertEquals("John", resultPerson.getName()); + assertEquals("Smith", resultPerson.getLastName()); + } +} diff --git a/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeService.java b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeService.java new file mode 100644 index 0000000000..f2dd6f6df4 --- /dev/null +++ b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/MethodInvokeService.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + */ + +package io.dapr.it.methodinvoke.http; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + + +/** + * Service for subscriber. + */ +@SpringBootApplication(scanBasePackages = {"io.dapr.it.methodinvoke.http"}) +public class MethodInvokeService { + + public static final String SUCCESS_MESSAGE = "dapr initialized. Status: Running. Init Elapsed"; + + public static void main(String[] args) { + int port = Integer.parseInt(args[0]); + + System.out.printf("Service starting on port %d ...\n", port); + + // Start Dapr's callback endpoint. + start(port); + } + + /** + * Starts Dapr's callback in a given port. + * + * @param port Port to listen to. + */ + private static void start(int port) { + SpringApplication app = new SpringApplication(MethodInvokeService.class); + app.run(String.format("--server.port=%d", port)); + } + +} \ No newline at end of file diff --git a/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/Person.java b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/Person.java new file mode 100644 index 0000000000..4e9eec69d7 --- /dev/null +++ b/sdk-tests/src/test/java/io/dapr/it/methodinvoke/http/Person.java @@ -0,0 +1,53 @@ +package io.dapr.it.methodinvoke.http; + +import java.util.Date; + +public class Person { + + private int id; + private String name; + private String lastName; + private Date birthDate; + + @Override + public String toString() { + return "Person{" + + "id=" + id + + ", name='" + name + '\'' + + ", lastName='" + lastName + '\'' + + ", birthDate=" + birthDate + + '}'; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } +}