March 22, 2021

Protocol Buffers (protobuf) Compiler/Code Generator - protoc

Introduction

In Protocol Buffers (protobuf) is API described in a .proto file, next step is to generate language specific code for that API. That is done with Protocol Buffer Compiler (protoc). Here we will generate Java Code, but there are many language supported with protobuf.

Graddle

The official supported Java plugin from Google (the creator of profobuf) is gradle https://github.com/google/protobuf-gradle-plugin. But changing build tool might not suite your overall CI/DI infrastructure, so here I will show Maven plugin.

Maven

https://www.xolstice.org/protobuf-maven-plugin/

Install Protocol Buffer Compiler (protoc)

On Fedora 33 ($ cat /etc/fedora-release) it is easy to install protoc.

$ sudo dnf install protobuf-compiler

protobuf-maven-plugin

https://www.xolstice.org/protobuf-maven-plugin/

.proto files are stored in src/main/proto. Lets create a simple .proto file

syntax = "proto3";

package se.magnuskkarlsson.example_protobuf;

message SimpleMessage {
  int32 id = 1;
  bool is_simple = 2;
  string name = 3;
  repeated int32 sample_list = 4;
}

And pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>se.magnuskkarlsson</groupId>
    <artifactId>example-protobuf</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.build.outputEncoding>UTF-8</project.build.outputEncoding>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>3.15.6</version>
        </dependency>

        <!-- Test Support -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-all</artifactId>
            <version>1.10.19</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <release>11</release>
                        <showDeprecation>true</showDeprecation>
                        <showWarnings>true</showWarnings>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocExecutable>/usr/bin/protoc</protocExecutable>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project> 

Then build with maven: '$ mvn clean install'. Generated source code is stored in target/generated-sources/protobuf/java

Now lets write a simple a class to test our new generated code.

package se.magnuskkarlsson.example_protobuf;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;

import se.magnuskkarlsson.example_protobuf.Message.SimpleMessage;

public class Main {

    public static void main(String[] args) throws FileNotFoundException, IOException {
        SimpleMessage message = SimpleMessage.newBuilder() //
                .setId(42) //
                .setIsSimple(false) //
                .setName("FOO") //
                .addAllSampleList(Arrays.asList(3, 4, 5)) //
                .build();
        System.out.println(message);

        File file = File.createTempFile("message", ".bin");
        try (FileOutputStream fos = new FileOutputStream(file)) {
            message.writeTo(fos);
        }
        System.out.println("Wrote " + file.getAbsolutePath());
    }

}

No comments: