2

How can I generate java interfaces instead of abstract classes for my service using protocol buffers compiler?

Right now I use a Gradle plugin which take .proto files and generates abstract classes for my services instead of interfaces. This can be problematic given that Java doesn't let you extend multiple classes.

I couldn't find a solution or a way so far after going through documentation so any help would be great.

My build.gradle looks like this

apply plugin: 'java'
apply plugin: 'com.google.protobuf'

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    // ASSUMES GRADLE 2.12 OR HIGHER. Use plugin version 0.7.5 with earlier
    // gradle versions
    classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
  }
}

repositories {
  mavenCentral()
  mavenLocal()
}

// IMPORTANT: You probably want the non-SNAPSHOT version of gRPC. Make sure you
// are looking at a tagged version of the example and not "master"!

// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
def grpcVersion = '1.0.0' // CURRENT_GRPC_VERSION

dependencies {
  compile "io.grpc:grpc-netty:${grpcVersion}"
  compile "io.grpc:grpc-protobuf:${grpcVersion}"
  compile "io.grpc:grpc-stub:${grpcVersion}"
}

protobuf {
  protoc {
    // The version of protoc must match protobuf-java. If you don't depend on
    // protobuf-java directly, you will be transitively depending on the
    // protobuf-java version that grpc depends on.
    artifact = 'com.google.protobuf:protoc:3.0.0'
  }
  plugins {
    grpc {
      artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}"
    }
  }
  generateProtoTasks {
    all()*.plugins {
      grpc {
        // To generate deprecated interfaces and static bindService method,
        // turn the enable_deprecated option to true below:
        option 'enable_deprecated=false'
      }
    }
  }
}

// Inform IntelliJ projects about the generated code.
apply plugin: 'idea'

idea {
  module {
    // Not using generatedSourceDirs because of
    // https://discuss.gradle.org/t/support-for-intellij-2016/15294/8
    sourceDirs += file("${projectDir}/build/generated/source/proto/main/java");
    sourceDirs += file("${projectDir}/build/generated/source/proto/main/grpc");
  }

I found out the reason why it is not generating interfaces it looks like it has been deprecated so I am not sure what is the way to generate interface. if you look at my build.gradle option 'enable_deprecated=false' turning this on to true will generate interfaces however the annotations say it is deprecated so I am not sure what is the new way to generate interface. I want interface not abstract classes.

user1870400
  • 6,028
  • 13
  • 54
  • 115

1 Answers1

0

From an API perspective, Java interfaces must be immutable once created to prevent breaking consumers and implementors of the interface. Since adding new methods to an existing service needs to be API-compatible, grpc-java was forced to remove the interfaces.

Using default methods in Java 8 may be an option, but grpc-java can't require Java 8 any time soon, so it would probably be a new codegen flavor.

Eric Anderson
  • 24,057
  • 5
  • 55
  • 76
  • without interfaces the code gets more uglier and cumbersome. since Java doesn't allow one to extend multiple classes and the only way to have multiple inheritance in Java is through implementing multiple interfaces. why not provide both options (abstract classes and interfaces)? you could say one must use abstract classes until Java 7 and one can also use interface if they have Java 8..That would be much more fair..on other note, many design pattern says code for an interface not a class..Interface is so important it just doesn't make sense to not support it in any way – user1870400 Aug 29 '16 at 19:33
  • It's true that design typically includes interfaces, but they must be immutable. I suggest you read the end of Effective Java, Item 18, which is summed up as "An exception to this rule is the case where ease of evolution is deemed more important than flexibility and power." gRPC services _must_ allow for evolution. – Eric Anderson Aug 31 '16 at 16:07
  • sure I don't disagree with that but why not support both abstract classes and interfaces depending on the Java version? – user1870400 Sep 01 '16 at 17:01
  • "depending on the Java version" is the bothersome part. That is not technically feasible, since the generated code for many services will be available on Maven Central. Instead, we must have two separate sets of generated code and the user would choose one. That comes with its own problems. We expect to do it eventually, but we're working on other things and would probably want it to include a JDK 8-style stub. – Eric Anderson Sep 06 '16 at 16:39