I have a proto definition with nested classes
syntax = "proto3";
option java_package = "com.spot.proto.v1.config";
package v1config;
// ClusterConfig proto is used to maintain the params required by all the services at a central place.
message ClusterConfig {
enum LogLevel {
UNKNOWN_TYPE = 0;
DEBUG = 1;
INFO = 2;
WARN = 3;
ERROR = 4;
FATAL = 5;
}
message Network {
string ip = 1;
int32 port = 2;
}
message Constants {
message SlackNotifier {
message Channel {
string name = 1;
}
string auth_token = 1;
map<string, Channel> channels = 2;
bool is_enabled = 3;
}
message Kafka {
string broker_list = 1;
}
Kafka kafka = 2;
}
message Support {
Network network = 1;
}
Support support = 1;
...
}
When I generate the java classes with option java_multiple_files = false;
it creates a single java class, ClusterConfigOuterClass.java
with all the Java classes/enums/etc generated for the top-level messages, services, and enumerations nested inside it. This is expected.
But if I use option java_multiple_files = true;
then I am seeing it is generating two additional classes ClusterConfig.java
, ClusterConfigOrBuilder.java
along with ClusterConfigOuterClass.java
. ClusteConfig.java
now contains the nested classes.
The documentation states like below:-
java_multiple_files (file option): If false, only a single .java file will be generated for this .proto file, and all the Java classes/enums/etc. generated for the top-level messages, services, and enumerations will be nested inside of an outer class (see java_outer_classname). If true, separate .java files will be generated for each of the Java classes/enums/etc. generated for the top-level messages, services, and enumerations, and the wrapper Java class generated for this .proto file won't contain any nested classes/enums/etc. This is a Boolean option that defaults to false. If not generating Java code, this option has no effect.
So should not each nested message like Kafka
, Network
, etc go into a separate java file?
With only Nested classes, the java_multiple_files
will not do anything, and this is on purpose. You are explicitly giving a context for Kafka
, Network
, etc... They are relevant only in their parent object.
Now, if you really wanted to generate multiple files, you would have to do something like:
enum LogLevel {
UNKNOWN_TYPE = 0;
DEBUG = 1;
INFO = 2;
WARN = 3;
ERROR = 4;
FATAL = 5;
}
message Channel {
string name = 1;
}
message SlackNotifier {
string auth_token = 1;
map<string, Channel> channels = 2;
bool is_enabled = 3;
}
message Kafka {
string broker_list = 1;
}
message Constants {
Kafka kafka = 2;
}
message Network {
string ip = 1;
int32 port = 2;
}
message Support {
Network network = 1;
}
message ClusterConfig {
Support support = 1;
//...
}
Then, to go further, if you wanted to give them a Context in which these objects should be used (maybe because you have team, and you don't want other developers to misuse these objects), you could put them in a package like:
package mycompany.service.cluster
and then to use your Kafka
object for example, they will need to give the fully qualified type (except if they are in the same package):
mycompany.service.cluster.Kafka