{"id":16782620,"url":"https://github.com/jufab/graphql-grpc-helidon","last_synced_at":"2026-05-03T11:36:54.873Z","repository":{"id":107346136,"uuid":"346143075","full_name":"jufab/graphql-grpc-helidon","owner":"jufab","description":"Lab around GraphQL and gRPC with Helidon","archived":false,"fork":false,"pushed_at":"2021-03-22T23:14:13.000Z","size":648,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-11T08:21:02.409Z","etag":null,"topics":["graphql","graphql-java","grpc","grpc-java","helidon","helidon-se","java"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jufab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-03-09T21:00:59.000Z","updated_at":"2024-10-06T23:22:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"c0da1095-63ec-444e-b005-d5c5b524c135","html_url":"https://github.com/jufab/graphql-grpc-helidon","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jufab/graphql-grpc-helidon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jufab%2Fgraphql-grpc-helidon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jufab%2Fgraphql-grpc-helidon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jufab%2Fgraphql-grpc-helidon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jufab%2Fgraphql-grpc-helidon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jufab","download_url":"https://codeload.github.com/jufab/graphql-grpc-helidon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jufab%2Fgraphql-grpc-helidon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32567738,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","graphql-java","grpc","grpc-java","helidon","helidon-se","java"],"created_at":"2024-10-13T07:46:49.244Z","updated_at":"2026-05-03T11:36:54.863Z","avatar_url":"https://github.com/jufab.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GraphQL or gRPC in Java\n\nThis article presents GraphQL and gRPC implemented with Java.\n\nWith the same use case, I'm going to show you how to expose and to implement these protocols.\n\nI use a simple use case but not just a one table use case...Ok, just a 2 tables with a relation one-to-one.\n\nTo make this article, I use [Helidon](https://helidon.io/).\n\n_Why Helidon?_ **Why not!** ...seriously, because this framework offers the possibility to implement these protocols ( _and of course, for me, to discover this framework ;-)_ )\n\n## Table of contents\n\n- [About Helidon](#about-helidon)\n- [Use case](#use-case)\n  + [Definition](#definition)\n  + [Helidon DB Client](#helidon-db-client)\n- [Init Project](#init-project)\n- [GraphQL](#graphql)\n  + [Schema](#schema)\n  + [Maven](#maven)\n  + [Implementation](#implementation)\n    - [Server](#server)\n    - [DataFetcher](#datafetcher)\n  + [Test](#test)\n- [gRPC](#grpc)\n  + [Protocol buffers](#protocol-buffers)\n  + [Maven](#maven-1)\n  + [Implementation](#implementation-1)\n    - [Server](#server-1)\n    - [Service](#service)\n  + [Test](#test-1)\n- [Conclusion](#conclusion)\n\n## About Helidon\n\n[Helidon](https://helidon.io/) is a java framework with 2 versions : \n\n- Helidon SE : A Reactive Microframework.\n    - Tiny Footprint\n    - Functional Style  \n    - Simple and Transparent\n    - GraalVM Native Image\n    - [More information here](https://helidon.io/docs/latest/#/about/02_introduction)\n- Helidon MP : A MicroProfile implementation.\n    - Support MP 3.3\n    - Small Footprint \n    - Declarative Style\n    - Dependency Injection \n    - CDI, JAX-RS, JSON-P/B\n    - [More information here](https://helidon.io/docs/latest/#/mp/guides/02_quickstart)\n\nIn these 2 versions, Helidon offers a lot of facilities around GraphQL or gRPC implementations (that's a good reason to use it for this article)\n\nThere is a lot of other possibilities like reactive streams, reactive messaging or predefined health-check or metrics...\n\nAnd gives facility to build it with docker or GraalVM and to deploy it with Kubernetes.\n\n_So, try it for fun and why not for your project ;-)_\n\n## Use case\n\n### Definition\n\nJust a simple use case : A person with an address =\u003e Address is in a separate table for this article.\n\nSo we have : \n\n![schema](assets/ddl.png)\n\n### Helidon DB Client\n\nFor the database and my use case, I used an H2 in-memory Database and [Helidon DB-Client](https://helidon.io/docs/latest/#/se/dbclient/01_introduction).\n\nHelidon DB Client is a reactive API for access database. You can access with JDBC Driver (H2, Oracle, MySQL...) or directly with MongoDB.\n\nFor this article, I used a JDBC. So I added these dependencies : \n\n```xml\n     \u003cdependency\u003e\n         \u003cgroupId\u003eio.helidon.dbclient\u003c/groupId\u003e \n         \u003cartifactId\u003ehelidon-dbclient\u003c/artifactId\u003e\n     \u003c/dependency\u003e\n     \u003cdependency\u003e\n         \u003cgroupId\u003eio.helidon.dbclient\u003c/groupId\u003e \n         \u003cartifactId\u003ehelidon-dbclient-jdbc\u003c/artifactId\u003e\n     \u003c/dependency\u003e\n```\nAll the database implementation is [here in this maven module](/db-helidon)\n\nIt contains 2 important files in [resources](/db-helidon/src/main/resources/) : \n- [db.yaml](/db-helidon/src/main/resources/db.yaml) : contains configuration for h2 Database\n- [statements.yaml](/db-helidon/src/main/resources/statements.yaml) : contains all statements like tables creation or sequences...\n\n## Init Project\n\nUse archetype from [documentation](https://helidon.io/docs/latest/#/se/guides/02_quickstart)\n\n```shell\nmvn -U archetype:generate -DinteractiveMode=false \\\n    -DarchetypeGroupId=io.helidon.archetypes \\\n    -DarchetypeArtifactId=helidon-quickstart-se \\\n    -DarchetypeVersion=2.2.1 \\\n    -DgroupId=fr.jufab \\\n    -DartifactId=graphql-helidon \\\n    -Dpackage=fr.jufab.graphql\n```\n\nand \n\n```shell\nmvn -U archetype:generate -DinteractiveMode=false \\\n    -DarchetypeGroupId=io.helidon.archetypes \\\n    -DarchetypeArtifactId=helidon-quickstart-se \\\n    -DarchetypeVersion=2.2.1 \\\n    -DgroupId=fr.jufab \\\n    -DartifactId=grpc-helidon \\\n    -Dpackage=fr.jufab.grpc\n```\n\n_I transformed projects into 3 maven modules and deleted all the GraalVM or Docker builder for reused database in graphQL or gRPC module._\n\nOr, you can use helidon cli to manage your project.\nhttps://helidon.io/docs/latest/#/about/05_cli\n\n\n## GraphQL\n\nSo now, let's talk about GraphQL.\n\nGraphQL is a query language and operates on a single endpoint. it talks with JSON language. It defines with a schema, describes valid attributes, operations, etc...\nAnd GraphQL is a [specification](https://spec.graphql.org/)\n\n### Schema\n\nTo define GraphQL, we need to use a schema with this information : \n- Object : composition of an object response\n- Query : query to request objects or array's object.\n- Mutation : to save/modify objects.\n- Subscription : to establish a bi-directional communication channel using WebSocket\n\nWith the use case, the schema, [available here](graphql-helidon/src/main/resources/person.graphqls), is : \n\n```graphql\n# Objects\ntype Person {\n    id: ID!\n    firstname: String!\n    lastname: String!\n    age: Int\n    gender: Gender!\n    address: Address\n}\n\nenum Gender {\n    WOMAN,\n    MAN\n}\n\ntype Address {\n    id: ID!\n    street: String!\n    zipCode: String!\n    city: String!\n}\n# Query\ntype Query {\n    personById(id: ID!): Person\n    personsByFirstName(firstname: String!): [Person]\n    persons:[Person]\n}\n# Mutation\ntype Mutation {\n    createPersonWithAddress(firstname: String!, lastname: String!, age: Int, gender: Gender, street: String!, zipCode: String!, city: String!):Person\n    createPerson(firstname: String!, lastname: String!, age: Int, gender: Gender, idAddress: ID!):Person\n    createAddress(street: String!, zipCode: String!, city: String!): Address\n}\n```\n\n### Maven\n\nIn helidon SE, there is a facility to use GraphQL with a helidon GraphQL library.\n\n[_More information about this integration in the documentation_](https://helidon.io/docs/latest/#/se/graphql/01_introduction)\n\n**For the moment, this feature is experimental...but it works for this project :)**\n\nTo insert GraphQL in the project, I added the dependency in the [pom.xml](graphql-helidon/pom.xml) file\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eio.helidon.graphql\u003c/groupId\u003e\n  \u003cartifactId\u003ehelidon-graphql-server\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\n\nThis dependency uses [GraphQL java version 15.0](https://www.graphql-java.com/).\n\n### Implementation\n\n#### Server\n\nGraphQL must be registered to the webserver. \n\nIn the [Main class](graphql-helidon/src/main/java/fr/jufab/graphql/Main.java), it was registered here : \n\n```java\nWebServer server = WebServer.builder()\n        .routing(Routing.builder()\n            .register(health)                   // Health at \"/health\"\n            .register(MetricsSupport.create())  // Metrics at \"/metrics\"\n            .register(GraphQlSupport.create(buildSchema(dbClient)))\n            .build())\n        .config(config.get(\"server\"))\n        .build();\n```\n\nExactly the line : \n\n```java\nregister(GraphQlSupport.create(buildSchema(dbClient)))\n```\n\nThe GraphQlSupport class takes a GraphQLSchema. Method buildSchema() creates a configured GraphQLSchema.\n\n```java\nprivate static GraphQLSchema buildSchema(DbClient dbClient) {\n    SchemaParser schemaParser = new SchemaParser();\n    Resource schemaResource = Resource.create(PERSON_GRAPHQLS);\n    TypeDefinitionRegistry typeDefinitionRegistry =\n        schemaParser.parse(schemaResource.string(StandardCharsets.UTF_8));\n    SchemaGenerator schemaGenerator = new SchemaGenerator();\n    return schemaGenerator.makeExecutableSchema(typeDefinitionRegistry,\n        buildRuntimeWiring(dbClient));\n  }\n```\nit requires:\n\n* schema : person.graphqls\n* parser : to instantiate a typeDefinitionRegistry\n* RuntimeWiring : to connect data with datafetcher\n\nMethod buildRuntimeWiring connects Object (Person, Address) with datafetcher.\n\n```java\nprivate static RuntimeWiring buildRuntimeWiring(DbClient dbClient) {\n  AddressRepository addressRepository = new AddressRepository(dbClient);\n  AddressDataFetcher addressDataFetcher = new AddressDataFetcher(addressRepository);\n  PersonRepository personRepository = new PersonRepository(dbClient);\n  PersonDataFetcher personDataFetcher = new PersonDataFetcher(personRepository);\n  return RuntimeWiring.newRuntimeWiring()\n    .type(TypeRuntimeWiring.newTypeWiring(\"Query\")\n      .dataFetcher(\"persons\", personDataFetcher.getPersons()))\n    .type(TypeRuntimeWiring.newTypeWiring(\"Query\")\n      .dataFetcher(\"personById\", personDataFetcher.getPersonById()))\n    .type(TypeRuntimeWiring.newTypeWiring(\"Query\")\n     .dataFetcher(\"personsByFirstName\", personDataFetcher.getPersonsByFirstName()))\n    .type(TypeRuntimeWiring.newTypeWiring(\"Person\")\n     .dataFetcher(\"address\", addressDataFetcher.getAddressById()))\n    .type(TypeRuntimeWiring.newTypeWiring(\"Mutation\")\n     .dataFetcher(\"createPersonWithAddress\", personDataFetcher.createPersonWithAddress()))\n    .type(TypeRuntimeWiring.newTypeWiring(\"Mutation\").dataFetcher(\"createAddress\",\n      addressDataFetcher.createAddress()))\n    .build();\n}\n```\n\nThere are all Query or Mutation in this method and all of them are link with a DataFetcher\n\n#### DataFetcher\n\nAll Objects will be associated to a _DataFetcher_ object. DataFetcher has the responsibility to load objects for Query or to save objects for Mutation.\n\nHow it works : \n\nYou define a _DataFetcher_ with a _DataFetchingEnvironment_ object. This object contains all arguments or fields to be fetched.\n\nlike this ([PersonDataFetcher](/graphql-helidon/src/main/java/fr/jufab/graphql/datafetcher/PersonDataFetcher.java)): \n\n```java\n// To get all Persons... no arguments\npublic DataFetcher\u003cList\u003cPerson\u003e\u003e getPersons() {\n    return environment -\u003e personRepository.getPersons().collectList().get();\n}\n//To get all by FirstName\npublic DataFetcher\u003cList\u003cPerson\u003e\u003e getPersonsByFirstName() {\n    return environment -\u003e personRepository.getPersonsByFirstName(environment.getArgument(\"firstname\")).collectList().get();\n}\n// Or to create a person\npublic DataFetcher\u003cPerson\u003e createPersonWithAddress() {\n    return environment -\u003e this.personRepository.createPerson(\n        new Person(environment.getArgument(\"firstname\"), environment.getArgument(\"lastname\"),\n          environment.getArgument(\"age\"),\n          new Address(environment.getArgument(\"street\"), environment.getArgument(\"zipCode\"),\n            environment.getArgument(\"city\")),\n          Gender.valueOf(environment.getArgument(\"gender\")))).get();\n}\n```\n\n_More information about DataFetching =\u003e https://www.graphql-java.com/documentation/v16/data-fetching/_\n\n### Test\n\nFor testing resources, I use [insomnia](https://insomnia.rest/). \n\nYou can access GraphQL requests like that,\n\n![schema](assets/graphql/insomnia-graphql.png)\n\nview schema information,\n\n![schema](assets/graphql/insomnia-graphql-schema.png)\n\nand do some requests.\n\n![schema](assets/graphql/insomnia-graphql-request.png)\n\n\nAnd that's it for GraphQL...\n\n## gRPC\n\ngRPC helps you to build web services. It's cross-language but this project is a Java project so... :)\n\nTo define and describe service, gRPC uses a simple definition file and uses protocol buffers format.\n\n_For more informations : https://grpc.io/_\n\n### Protocol buffers\n\ngRPC uses protocol buffers : https://developers.google.com/protocol-buffers\n\nProtocol buffers is a language for serializing structured data.\n\nYou can define some options for every language:  \"package\" for java or \"objc_class_prefix\" for Objective-C to prefix generated classes.\n\nFor this lab, I used the syntax version \"proto3\"\n\nProtobuf file contains : \n\n- message : Object Data\n- enum : define enumeration\n- service : Service to query, modify or save data\n\n\nWith the use cases, proto file [available here](grpc-helidon/src/main/proto/person.proto) has this definition\n\n```protobuf\nsyntax = \"proto3\";\noption java_package = \"fr.jufab.grpc.proto\";\noption java_multiple_files = true;\noption java_generic_services = true;\noption java_outer_classname = \"Helidon\";\n\nenum Gender {\n  WOMAN = 0;\n  MAN = 1;\n}\n\nmessage Person {\n  int32 id = 1;\n  string firstname = 2;\n  string lastname = 3;\n  int32 age = 4;\n  Gender gender = 5;\n  Address address = 6;\n}\n\nmessage Address {\n  int32 id = 1;\n  string street = 2;\n  string zipCode = 3;\n  string city = 4;\n}\n\nmessage Persons {\n  repeated Person persons=1;\n}\n\nmessage QueryPerson {\n  int32 id=1;\n  string firstname=2;\n}\n\nmessage PersonWithAddressToSave {\n  string firstname = 1;\n  string lastname = 2;\n  int32 age = 3;\n  Gender gender = 4;\n  string street = 5;\n  string zipCode = 6;\n  string city = 7;\n}\n\nmessage PersonToSave{\n  string firstname = 1;\n  string lastname = 2;\n  int32 age = 3;\n  Gender gender = 4;\n  int32 idAddress = 5;\n}\n\nmessage AddressToSave{\n  string street = 1;\n  string zipCode = 2;\n  string city = 3;\n}\n\nmessage QueryAddress {\n  int32 id = 1;\n}\n\nservice PersonService {\n  rpc persons(QueryPerson) returns (Persons);\n  rpc personById(QueryPerson) returns (Person);\n  rpc personsByFirstName(QueryPerson) returns (Persons);\n\n  rpc createPersonWithAddress(PersonWithAddressToSave) returns (Person);\n  rpc createPerson(PersonToSave) returns (Person);\n}\n\nservice AddressService {\n  rpc createAddress(AddressToSave) returns (Address);\n  rpc addressById(QueryAddress) returns (Address);\n}\n\n```\n\n### Maven\n\nHelidon SE offers a maven dependency to deploy gRPC server.\n\n[_More information about this integration in the documentation_](https://helidon.io/docs/latest/#/se/grpc/01_introduction)\n\n**Like GraphQL, gRPC feature is experimental for the moment...but it works for this project :)**\n\nTo insert gRPC in the project, I added the dependency in the [pom.xml](grpc-helidon/pom.xml)\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.helidon.grpc\u003c/groupId\u003e\n    \u003cartifactId\u003ehelidon-grpc-server\u003c/artifactId\u003e\n\u003c/dependency\u003e\n```\n\nBut to use gRPC and specially protobuf, that's not enough...\n\nYou must generate data from protobuf file with a special maven plugin. This plugin use Protocol Buffer Compiler.\n\nIn this project, to generate classes, there is this maven definition in [pom.xml](grpc-helidon/pom.xml).\n\n```xml\n\u003cplugin\u003e\n    \u003cgroupId\u003eorg.xolstice.maven.plugins\u003c/groupId\u003e\n    \u003cartifactId\u003eprotobuf-maven-plugin\u003c/artifactId\u003e\n    \u003cversion\u003e0.6.1\u003c/version\u003e\n    \u003cconfiguration\u003e\n        \u003cprotocArtifact\u003ecom.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}\u003c/protocArtifact\u003e\n        \u003cpluginId\u003egrpc-java\u003c/pluginId\u003e\n        \u003cpluginArtifact\u003eio.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}\u003c/pluginArtifact\u003e\n    \u003c/configuration\u003e\n    \u003cexecutions\u003e\n        \u003cexecution\u003e\n            \u003cgoals\u003e\n                \u003cgoal\u003ecompile\u003c/goal\u003e\n                \u003cgoal\u003ecompile-custom\u003c/goal\u003e\n            \u003c/goals\u003e\n        \u003c/execution\u003e\n    \u003c/executions\u003e\n\u003c/plugin\u003e\n```\n_more info about this plugin here https://www.xolstice.org/protobuf-maven-plugin/_\n\nAll classes are generated in \"generated-sources\".\n\n### Implementation\n#### Server\n\nTo start gRPC server, Helidon offers a specific server on this purpose.\n\nYou need to start a GrpcServer like this\n\n```java\nGrpcServer grpcServer = GrpcServer\n        .create(GrpcServerConfiguration.create(config.get(\"grpcserver\")),GrpcRouting.builder()\n            .register(buildPersonServiceGrpc(dbClient)) //See after for this\n            .register(buildAddressServiceGrpc(dbClient)) //See after for this\n            .build())\n        .start()\n        .toCompletableFuture()\n        .get(10, TimeUnit.SECONDS);\n```\n\nBy default, port is on 1408 but you can redefine it in your yaml like this : \n\n```yaml\ngrpcserver:\n  port: 3333\n```\n\n_[You can see example here](grpc-helidon/src/main/resources/server.yaml)_\n\n#### Service\n\nYou can see in server, the service registered \"PersonServiceGrpc\" or \"AddressServiceGrpc\".\n\nThese 2 services available [here](grpc-helidon/src/main/java/fr/jufab/grpc/service/PersonGrpcService.java) and [here](grpc-helidon/src/main/java/fr/jufab/grpc/service/AddressGrpcService.java)\n\nThese services implement service supplied by Protobuf generated classes. So, in \"PersonGrpcService\", this class implements \"PersonServiceGrpc.PersonServiceImplBase\".\n\nBy default, you can't see this class \"PersonServiceGrpc\" because you need to generate class with the protobuf file. Why my package is in \"fr.jufab.grpc.proto\"? Because I used an option in protobuf :\n\n```protobuf\noption java_package = \"fr.jufab.grpc.proto\";\n```\n\nFor example, PersonServiceGrpc gives me all methods define in protobuf. \n\nRemember service in protbuf : \n\n```protobuf\nservice PersonService {\n  rpc persons(QueryPerson) returns (Persons);\n  rpc personById(QueryPerson) returns (Person);\n  rpc personsByFirstName(QueryPerson) returns (Persons);\n\n  rpc createPersonWithAddress(PersonWithAddressToSave) returns (Person);\n  rpc createPerson(PersonToSave) returns (Person);\n}\n```\n\nand PersonServiceGrpc gives you : \n\n```java\npublic static abstract class PersonServiceImplBase implements io.grpc.BindableService {\n\n  /**\n   */\n  public void persons(fr.jufab.grpc.proto.QueryPerson request,\n          io.grpc.stub.StreamObserver\u003cfr.jufab.grpc.proto.Persons\u003e responseObserver) {\n    asyncUnimplementedUnaryCall(METHOD_PERSONS, responseObserver);\n  }\n\n  /**\n   */\n  public void personById(fr.jufab.grpc.proto.QueryPerson request,\n          io.grpc.stub.StreamObserver\u003cfr.jufab.grpc.proto.Person\u003e responseObserver) {\n    asyncUnimplementedUnaryCall(METHOD_PERSON_BY_ID, responseObserver);\n  }\n\n  /**\n   */\n  public void personsByFirstName(fr.jufab.grpc.proto.QueryPerson request,\n          io.grpc.stub.StreamObserver\u003cfr.jufab.grpc.proto.Persons\u003e responseObserver) {\n    asyncUnimplementedUnaryCall(METHOD_PERSONS_BY_FIRST_NAME, responseObserver);\n  }\n\n  /**\n   */\n  public void createPersonWithAddress(fr.jufab.grpc.proto.PersonWithAddressToSave request,\n          io.grpc.stub.StreamObserver\u003cfr.jufab.grpc.proto.Person\u003e responseObserver) {\n    asyncUnimplementedUnaryCall(METHOD_CREATE_PERSON_WITH_ADDRESS, responseObserver);\n  }\n\n  /**\n   */\n  public void createPerson(fr.jufab.grpc.proto.PersonToSave request,\n          io.grpc.stub.StreamObserver\u003cfr.jufab.grpc.proto.Person\u003e responseObserver) {\n    asyncUnimplementedUnaryCall(METHOD_CREATE_PERSON, responseObserver);\n  }\n}\n```\n\nNow, just implements these methods with your repository or DB access.\n\nFor method \"persons\" in [PersonGrpcService](grpc-helidon/src/main/java/fr/jufab/grpc/service/PersonGrpcService.java), I implemented it like that : \n\n```java\n@Override public void persons(QueryPerson request,\n      StreamObserver\u003cfr.jufab.grpc.proto.Persons\u003e responseObserver) {\n    try {\n      complete(responseObserver, buildPersonsGrpc(personRepository.getPersons()\n          .collectList()\n          .get()));\n    } catch (InterruptedException e) {\n      LOGGER.log(Level.SEVERE, \"Error\", e);\n    } catch (ExecutionException e) {\n      LOGGER.log(Level.SEVERE, \"Error\", e);\n    }\n  }\n```\nYou can see all implementation in [PersonGrpcService](grpc-helidon/src/main/java/fr/jufab/grpc/service/PersonGrpcService.java) and [AddressGrpcService](grpc-helidon/src/main/java/fr/jufab/grpc/service/AddressGrpcService.java)\n\n### Test\n\nFor testing gRPC services, I use [insomnia](https://insomnia.rest/) too.\n\nYou can access gRPC services like that,\n\n![schema](assets/grpc/insomnia-grpc.png)\n\nload protobuf file,\n\n![schema](assets/grpc/insomnia-grpc-proto.png)\n\nselect your service to test after adding url,\n\n![schema](assets/grpc/insomnia-grpc-service.png)\n\nand use it.\n\n![schema](assets/grpc/insomnia-grpc-create.png)\n\nThat's it for gRPC.\n\n## Conclusion\n\nGraphQL and gRPC offer a same approach : to use a schema and to generate resources from description. \n\nGraphQL is an HTTP protocol with schema definition. So you can access to this resource with any language who accepts HTTP request.\n\ngRPC communicates over his protocol (HTTP/2) and you need to generate your service from the protobuf.\n\nIn my opinion : \n\n- GraphQL may be better for external exposition like for mobile, open API, surely other case.\n- gRPC may be better for internal communication like in cloud, with defined client, in K8s Cluster, in information system...\n\nOf course, it can depend on your use. Maybe this article can help you to choose.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjufab%2Fgraphql-grpc-helidon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjufab%2Fgraphql-grpc-helidon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjufab%2Fgraphql-grpc-helidon/lists"}