Quarkus gRPC项目引入proto-google-common-protos后无法使用datetime.proto
我有一个基于Quarkus的gRPC项目,需返回从PostgreSQL数据库获取的数据,其中部分列是timestamp without time zone类型,对应Java中的LocalDateTime。
数据库表结构如下:
create table users ( id uuid not null default gen_random_uuid(), ... created_on timestamp without time zone not null default localtimestamp(6), modified_on timestamp without time zone not null default localtimestamp(6), primary key (id) );
编写的proto文件如下:
syntax = "proto3"; import "google/type/datetime.proto"; <- 无法生效 :/ ... message GetUserResponse { optional string id = 1; ... optional google.type.DateTime created_on = 5; optional google.type.DateTime modified_on = 6; }
Java实体类定义:
public class User { private UUID id; ... private LocalDateTime createdOn; private LocalDateTime modifiedOn; }
我已引入com.google.api.grpc:proto-google-common-protos:2.33.0依赖,但该类型仍无法被识别,执行构建命令时出现如下错误:
$ ./gradlew clean quarkusBuild > Task :clean > Task :processResources google/type/datetime.proto: File not found. user.proto:12:1: Import "google/type/datetime.proto" was not found or had errors. user.proto:43:12: "google.type.DateTime" is not defined. user.proto:44:12: "google.type.DateTime" is not defined.
说明: 我可以改用Java中的
OffsetDateTime,因为google/protobuf/timestamp.proto可被识别,且我全程使用UTC时区,两种类型都能满足存储需求,但我更希望解决当前问题,避免修改过多代码引发其他问题。
是否有办法注册来自com.google.api.grpc:proto-google-common-protos的类型?我原本以为只需引入该依赖即可使用。
更新
Quarkus有一份gRPC代码生成指南,我认为这可能解决问题,但尝试配置quarkus.generate-code.grpc.scan-for-imports、quarkus.generate-code.grpc.scan-for-proto或quarkus.generate-code.grpc.scan-for-proto-include后仍无效果。
1. 补充Quarkus配置
在application.properties中添加以下配置,明确告诉gRPC代码生成器扫描依赖中的proto文件:
quarkus.generate-code.grpc.scan-for-proto=true quarkus.generate-code.grpc.scan-for-proto-include=com.google.api.grpc:proto-google-common-protos
2. 调整Gradle构建脚本
仅靠Quarkus配置可能无法让Gradle正确识别依赖中的proto文件,需在build.gradle中补充protobuf插件的配置:
plugins { id 'io.quarkus' id 'com.google.protobuf' version '0.9.4' } protobuf { protoc { artifact = "com.google.protobuf:protoc:3.25.3" } plugins { grpc { artifact = "io.grpc:protoc-gen-grpc-java:1.59.0" } } generateProtoTasks { all()*.plugins { grpc {} } all().each { task -> task.builtins { java {} } // 让proto编译器能读取依赖中的proto文件 task.dependsOn configurations.protobuf } } } dependencies { implementation 'io.quarkus:quarkus-grpc' implementation 'com.google.api.grpc:proto-google-common-protos:2.33.0' // 引入protobuf工具类依赖,用于类型转换 implementation 'com.google.protobuf:protobuf-java-util:3.25.3' }
3. 实现类型转换逻辑
编译通过后,需要处理LocalDateTime与google.type.DateTime的双向转换,示例如下:
// 从User实体转换为GetUserResponse public GetUserResponse toResponse(User user) { GetUserResponse.Builder builder = GetUserResponse.newBuilder(); if (user.getId() != null) { builder.setId(user.getId().toString()); } if (user.getCreatedOn() != null) { LocalDateTime ldt = user.getCreatedOn(); google.type.DateTime dt = google.type.DateTime.newBuilder() .setYear(ldt.getYear()) .setMonth(ldt.getMonthValue()) .setDay(ldt.getDayOfMonth()) .setHours(ldt.getHour()) .setMinutes(ldt.getMinute()) .setSeconds(ldt.getSecond()) .setNanos(ldt.getNano()) .build(); builder.setCreatedOn(dt); } // modified_on字段转换逻辑与created_on一致 return builder.build(); }
4. 排查验证步骤
- 检查依赖版本兼容性:确保
protoc、grpc-java与proto-google-common-protos的版本匹配 - 清理缓存后重新构建:执行
./gradlew clean build --refresh-dependencies - 确认依赖包中存在目标proto:解压
com.google.api.grpc:proto-google-common-protos:2.33.0的JAR包,验证META-INF/protobuf/google/type/datetime.proto是否存在
内容的提问来源于stack exchange,提问作者user4695271

