Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing annotation import on gRPC service definition #844

Closed
CarlosNihelton opened this issue Jun 15, 2023 · 12 comments · Fixed by #845
Closed

Missing annotation import on gRPC service definition #844

CarlosNihelton opened this issue Jun 15, 2023 · 12 comments · Fixed by #845

Comments

@CarlosNihelton
Copy link

CarlosNihelton commented Jun 15, 2023

Release 21.0.0 of protoc_plugin generates pbgrpc.dart files in which the annotation @$pb.GrcpServiceName is used to wrap the class implementing the RPC service, but that annotation is not imported in any way, resulting in code that cannot compile.

//
//  Generated code. Do not modify.
//  source: hello.proto
//
// @dart = 2.12

// ignore_for_file: annotate_overrides, camel_case_types
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

import 'dart:async' as $async;
import 'dart:core' as $core;

import 'package:grpc/service_api.dart' as $grpc;
// missing `import 'package:protobuf/protobuf.dart';`
import 'hello.pb.dart' as $0;

export 'hello.pb.dart';

@$pb.GrpcServiceName('hello.Hello') // <- this is defined in protobuf/lib/src/protobuf/annotations.dart, but it's not imported.
class HelloClient extends $grpc.Client {
...

To reproduce the issue:

hello/
- hello.proto
- lib/
- pubspec.yaml

hello.proto

syntax = "proto3";
package hello;

message Empty {}

service Hello {
    rpc Ping(Empty) returns (Empty) {}
}

pubspec.yaml

name: hello
description: A gRPC Tutorial.
version: 0.0.1

environment:
  sdk: '>=2.19.0 <4.0.0'

dependencies:
  grpc: ^3.2.0
  protobuf: ^3.0.0
dart pub global activate protoc_plugin
cd hello/
protoc --proto_path=. --dart_out=grpc:lib/ ./hello.proto 

The output hello.pbgrpc.dart file will look like:

//
//  Generated code. Do not modify.
//  source: hello.proto
//
// @dart = 2.12

// ignore_for_file: annotate_overrides, camel_case_types
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

import 'dart:async' as $async;
import 'dart:core' as $core;

import 'package:grpc/service_api.dart' as $grpc;

import 'hello.pb.dart' as $0;

export 'hello.pb.dart';

@$pb.GrpcServiceName('hello.Hello')
class HelloClient extends $grpc.Client {
  static final _$ping = $grpc.ClientMethod<$0.Empty, $0.Empty>(
      '/hello.Hello/Ping',
      ($0.Empty value) => value.writeToBuffer(),
      ($core.List<$core.int> value) => $0.Empty.fromBuffer(value));

  HelloClient($grpc.ClientChannel channel,
      {$grpc.CallOptions? options,
      $core.Iterable<$grpc.ClientInterceptor>? interceptors})
      : super(channel, options: options,
        interceptors: interceptors);

  $grpc.ResponseFuture<$0.Empty> ping($0.Empty request, {$grpc.CallOptions? options}) {
    return $createUnaryCall(_$ping, request, options: options);
  }
}

@$pb.GrpcServiceName('hello.Hello')
abstract class HelloServiceBase extends $grpc.Service {
  $core.String get $name => 'hello.Hello';

  HelloServiceBase() {
    $addMethod($grpc.ServiceMethod<$0.Empty, $0.Empty>(
        'Ping',
        ping_Pre,
        false,
        false,
        ($core.List<$core.int> value) => $0.Empty.fromBuffer(value),
        ($0.Empty value) => value.writeToBuffer()));
  }

  $async.Future<$0.Empty> ping_Pre($grpc.ServiceCall call, $async.Future<$0.Empty> request) async {
    return ping(call, await request);
  }

  $async.Future<$0.Empty> ping($grpc.ServiceCall call, $0.Empty request);
}
@CarlosNihelton
Copy link
Author

The import statement is also missing in the golden file as shown in the snippet below:

//
// Generated code. Do not modify.
// source: test
//
// @dart = 2.12
// ignore_for_file: annotate_overrides, camel_case_types
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import
import 'dart:async' as $async;
import 'dart:core' as $core;
import 'package:grpc/service_api.dart' as $grpc;
import 'test.pb.dart' as $0;
export 'test.pb.dart';
@$pb.GrpcServiceName('Test')
class TestClient extends $grpc.Client {

@sigurdm
Copy link
Collaborator

sigurdm commented Jun 15, 2023

cc @osa1

@collo54
Copy link

collo54 commented Jun 16, 2023

Facing the same issue, while following observable flutter: grpc with @craiglabenz and @gianfrancopapa awesome content btw https://www.youtube.com/live/jCbclWBV32o?feature=share.

To finish coding along I commented out the problem area as shown below as I noticed that piece of code didn't show up while @gianfrancopapa was coding in the protos/lib/src/generated/todo.pbgrpc.dart file.

//  Generated code. Do not modify.
//  source: todo.proto
//
// @dart = 2.12

// ignore_for_file: annotate_overrides, camel_case_types
// ignore_for_file: constant_identifier_names, library_prefixes
// ignore_for_file: non_constant_identifier_names, prefer_final_fields
// ignore_for_file: unnecessary_import, unnecessary_this, unused_import

import 'dart:async' as $async;
import 'dart:core' as $core;

import 'package:grpc/service_api.dart' as $grpc;

import 'todo.pb.dart' as $0;

export 'todo.pb.dart';

//@$pb.GrpcServiceName('TodoService')       **<- problem area 1**
class TodoServiceClient extends $grpc.Client {
  static final _$getTodo = $grpc.ClientMethod<$0.GetTodoByIdRequest, $0.Todo>(
      '/TodoService/getTodo',
      ($0.GetTodoByIdRequest value) => value.writeToBuffer(),
      ($core.List<$core.int> value) => $0.Todo.fromBuffer(value));
  static final _$getTodoStream =
      $grpc.ClientMethod<$0.GetTodoByIdRequest, $0.Todo>(
          '/TodoService/getTodoStream',
          ($0.GetTodoByIdRequest value) => value.writeToBuffer(),
          ($core.List<$core.int> value) => $0.Todo.fromBuffer(value));

  TodoServiceClient($grpc.ClientChannel channel,
      {$grpc.CallOptions? options,
      $core.Iterable<$grpc.ClientInterceptor>? interceptors})
      : super(channel, options: options, interceptors: interceptors);

  $grpc.ResponseFuture<$0.Todo> getTodo($0.GetTodoByIdRequest request,
      {$grpc.CallOptions? options}) {
    return $createUnaryCall(_$getTodo, request, options: options);
  }

  $grpc.ResponseStream<$0.Todo> getTodoStream($0.GetTodoByIdRequest request,
      {$grpc.CallOptions? options}) {
    return $createStreamingCall(
        _$getTodoStream, $async.Stream.fromIterable([request]),
        options: options);
  }
}

//@$pb.GrpcServiceName('TodoService')    **<- problem area 2**
abstract class TodoServiceBase extends $grpc.Service {
  $core.String get $name => 'TodoService';

  TodoServiceBase() {
    $addMethod($grpc.ServiceMethod<$0.GetTodoByIdRequest, $0.Todo>(
        'getTodo',
        getTodo_Pre,
        false,
        false,
        ($core.List<$core.int> value) =>
            $0.GetTodoByIdRequest.fromBuffer(value),
        ($0.Todo value) => value.writeToBuffer()));
    $addMethod($grpc.ServiceMethod<$0.GetTodoByIdRequest, $0.Todo>(
        'getTodoStream',
        getTodoStream_Pre,
        false,
        true,
        ($core.List<$core.int> value) =>
            $0.GetTodoByIdRequest.fromBuffer(value),
        ($0.Todo value) => value.writeToBuffer()));
  }

  $async.Future<$0.Todo> getTodo_Pre($grpc.ServiceCall call,
      $async.Future<$0.GetTodoByIdRequest> request) async {
    return getTodo(call, await request);
  }

  $async.Stream<$0.Todo> getTodoStream_Pre($grpc.ServiceCall call,
      $async.Future<$0.GetTodoByIdRequest> request) async* {
    yield* getTodoStream(call, await request);
  }

  $async.Future<$0.Todo> getTodo(
      $grpc.ServiceCall call, $0.GetTodoByIdRequest request);
  $async.Stream<$0.Todo> getTodoStream(
      $grpc.ServiceCall call, $0.GetTodoByIdRequest request);
}

Below is my protos/protos/todo.proto file.

syntax = "proto3";

message Todo {
    int32 id = 1;
    string title = 2;
    bool completed = 3;
}

message GetTodoByIdRequest {
    int32 id = 1;
}

service TodoService {
    rpc getTodo(GetTodoByIdRequest) returns (Todo);
    rpc getTodoStream(GetTodoByIdRequest) returns (stream Todo);
}

Below is my protos/pubspec.yaml file.


name: proto
description: A starting point for Dart libraries or applications.
version: 1.0.0

environment:
  sdk: ^3.0.0

dependencies:
  grpc: ^3.2.0
  protobuf: ^2.1.0
  

dev_dependencies:
  lints: ^2.0.0
  test: ^1.21.0

Despite this, I was able to complete and test the rpc on windows and it works! The only issue is I couldn't access Todo parameters while implementing the rpc methods in the server/lib/todo_service.dart file below.

import 'package:proto/proto.dart';

class TodoService extends TodoServiceBase {
  @override
  Future<Todo> getTodo(ServiceCall call, GetTodoByIdRequest request) async {
    final id = request.id;
    final todo =
        Todo();           **// <- cannot access Todo required parameters id, title, and completed**
    return todo;
  }

  @override
  Stream<Todo> getTodoStream(
      ServiceCall call, GetTodoByIdRequest request) async* {
    final id = request.id;
    final todo =
        Todo();             **// <- cannot access Todo required parameters id, title, and completed**
    while (true) {
      yield todo;
    }
  }
}

@osa1
Copy link
Member

osa1 commented Jun 16, 2023

Thanks for reporting this. We've released protoc_plugin-21.0.1 with the fix.

@AndreBlumenthal
Copy link

I still do encounter that issue. I am not too deep into that topic but wasn't 21.0.1 already released? Will that then override the existing package? Or do you need to publish 21.0.2?

@osa1
Copy link
Member

osa1 commented Jun 16, 2023

I just released 21.0.1 an hour ago. If you're using 21.0.1 and the issue persists could you share your proto/grpc files so that I can take a look?

@wolframm
Copy link

I installed 21.0.1 but it doesn't help, because GrpcServiceName is nowhere to be found in the protobuf 2.1.0 package.

import 'dart:async' as $async;
import 'dart:core' as $core;

import 'package:grpc/service_api.dart' as $grpc;
import 'package:protobuf/protobuf.dart' as $pb;

import 'service.pb.dart' as $0;

export 'service.pb.dart';

@$pb.GrpcServiceName('unary.Unary')
class UnaryClient extends $grpc.Client {
  static final _$utilKnockKnock = $grpc.ClientMethod<$0.Empty, $0.Empty>(
      '/unary.Unary/utilKnockKnock',
      ($0.Empty value) => value.writeToBuffer(),
      ($core.List<$core.int> value) => $0.Empty.fromBuffer(value));

@osa1
Copy link
Member

osa1 commented Jun 16, 2023

@wolframm
Copy link

wolframm commented Jun 16, 2023

Exception: Because management_unary_server depends on grpc ^3.2.0 which depends on protobuf ^2.0.0, protobuf ^2.0.0 is required.
So, because management_unary_server depends on protobuf ^3.0.0, version solving failed.

Cannot use protobuf 3.0.0 until 'grpc' is updated.

@osa1
Copy link
Member

osa1 commented Jun 16, 2023

We will release a new grpc soon with protobuf-3.0.0 support. (cc @sigurdm)

@wolframm
Copy link

OK. By soon you mean in the next few hours (in which case I will just take a break)? Or in the next few days, weeks, ... in which case I will revert to previous versions.

@osa1
Copy link
Member

osa1 commented Jun 16, 2023

Probably in the next few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants