4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Protocol Buffers v26.0 の破壊的変更

Posted at

protobuf v26.0 と protobuf-java v4.26.0

protobuf v26.0 が 2024/03/14 にリリースされましたが、Java, PHP, C++, Ruby, Python には破壊的変更が含まれています。

他の言語は詳しく分かりませんが、Java ではかなり大きな変更が入っており、protobuf-java のメジャーバージョンが上がっていて v4.x となっています。(マイナーバージョンは、protobuf のバージョンと同期しています)

大きな問題点は、protoc v26 以降でコンパイルされたファイルは、protobuf-java v3.25 以下ではコンパイル・動作できず、v4.26 以降を利用する必要がある点です。

速報的に、Java でどう対処すれば良いかを書いておきます。

コンパイル時のエラー

コンパイル時にこんなエラーが出たら、それは protoc に対して protobuf-java のバージョンが古いからです。

エラー: パッケージcom.google.protobuf.RuntimeVersionは存在しません
      com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC,
エラー: シンボルを見つけられません
    com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion(
                       ^
  シンボル:   クラス RuntimeVersion
  場所: パッケージ com.google.protobuf
エラー: シンボルを見つけられません
    if (!com.google.protobuf.GeneratedMessage.isStringEmpty(referenceId_)) {
                                             ^
  シンボル:   メソッド isStringEmpty(Object)
  場所: クラス GeneratedMessage

エラー: クラス com.google.protobuf.GeneratedMessage.Builder<BuilderType>のメソッド parseUnknownFieldは指定された型に適用できません。
              if (!super.parseUnknownField(input, extensionRegistry, tag)) {
                        ^
  期待値: CodedInputStream,com.google.protobuf.UnknownFieldSet.Builder,ExtensionRegistryLite,int
  検出値:    CodedInputStream,ExtensionRegistryLite,int
  理由: 実引数リストと仮引数リストの長さが異なります
  BuilderTypeが型変数の場合:
    クラス com.google.protobuf.GeneratedMessage.Builderで宣言されているBuilderType extends com.google.protobuf.GeneratedMessage.Builder<BuilderType>

対処方法

.proto をコンパイルする protoc と、protobuf-java のバージョンが違うことにより発生する問題なので、両方のバージョンを互換性のあるバージョンに合わせれば問題ありません。

ツールによっては、protoc を常に最新版で利用するようになっていたり、brew upgrade した途端にローカルの protoc が上がってしまったとか、のような状況で問題が発生することでしょう。

基本的には、以下のどちらかの方法を取ることになります。

protoc のバージョンを固定する

当面の間は、ライブラリの依存関係等もあるので protoc を v25 系以下で動かしたいところです。

どのように protoc を利用しているかによりますが、protobuf-gradle-plugin では以下のようにバージョンが固定できます。

protobuf {
  ...
  // Configure the protoc executable
  protoc {
    // Download from repositories
    artifact = 'com.google.protobuf:protoc:3.25.1'
  }
  ...
}

buf を使っている場合でも、buf.gen.yaml に以下のようにバージョンを指定することができます。

version: v1
plugins:
  - plugin: buf.build/protocolbuffers/java:v25.1
    out: java
  - plugin: buf.build/protocolbuffers/kotlin:v25.1
    out: kotlin

protobuf-java バージョンを上げる

protobuf-java (com.google.protobuf:protobuf-java) を v4.26 以降に上げれば、protoc も v26.0 以降を使うことができます。

ただし、リリース直後の現在では protobuf に依存する他のライブラリも v4.26 以降に対応していない可能性があるので、注意。

将来的には、両方 v26 以降を利用できる環境を構築するべきでしょう。

まとめ

gRPC とかで、コンパイル済みのクライアントライブラリを jar にして共有 or maven publish しているとかの場合、protobuf に今回のような破壊的変更が加わると大変そう。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?