Missing annotation import on gRPC service definition
CarlosNihelton opened this issue · 12 comments
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);
}
The import statement is also missing in the golden file as shown in the snippet below:
protobuf.dart/protoc_plugin/test/goldens/grpc_service.pbgrpc
Lines 1 to 22 in a9bf79f
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;
}
}
}
Thanks for reporting this. We've released protoc_plugin-21.0.1 with the fix.
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
?
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?
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));
You need protobuf-3.0.0 or newer for GrpcServiceName
. It's defined here: https://github.com/google/protobuf.dart/blob/master/protobuf/lib/src/protobuf/annotations.dart#L20 (on pub.dev: https://pub.dev/documentation/protobuf/latest/protobuf/GrpcServiceName-class.html)
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.
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.
Probably in the next few days.