Android protobuf nano usage - java

I am trying to generate java files from below proto file using protobuf nano. I got some basic instruction on how to proceed in this SO thread.
I have this proto file, personal.proto:
package tutorial;
option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
I tried to follow the instruction from here, more specifically NANO version:
Downloaded protobuf-2.5.0.zip and compiler protoc-2.5.0-win32.zip from here.
Unzipped protobuf-2.5.0.zip to a folder and in there in src subfolder I unzipped protoc.exe.
Changed to java folder and in there issued: mvn clean package -P nano. That command ran fine and in target folder I have protobuf-java-2.5.0.jar
From here I am not sure how to proceed since in the initial documentation I have this statement:
- Link with the generated jar file
<protobuf-root>java/target/protobuf-java-2.3.0-nano.jar.
I am not sure what that means, how to link? Is there some parameter for protoc.exe that specifies the jar file to use?
I tried to issue this command: protoc --javanano_out=enum_style=java --java_out=generated personal.proto
but I get this error: --javanano_out: protoc-gen-javanano: The system cannot find the file specified.
The question would be: what am I missing/doing wrong above? I am trying to generate java files from above proto file.

I think this protoc is not compiled with javanano support.
The pre-compiled windows version 2.5.0 does not include nano support, take a look at the source code, in the "src\google\protobuf\compiler" path, includes the java generator but not the javanano generator. The latest source code at google repositories includes javanano.
You can download the latest source code and try to compile it using MinGW and msys or CygWin, take a look at this post How to build google protocol buffers in Windows for mingw?
(I will post details for the building process later)
UPDATE:
The final command line after building protoc.exe
For one proto file
protoc --javanano_out=store_unknown_fields=true:target/generated-sources personal.proto, target/generated-sources
For multiple proto files
protoc --javanano_out=store_unknown_fields=true:target/generated-sources --proto_path=inputpath input/*.proto
EDIT Nano generator replaces enum members with public static final int fields. This is a problem if a class has an optional enum member because that member will be compiled to a primitive int value and will take the default value of zero, which will be the first element from enum. To distinguish the cases when an enum value was not set, one can take advantage of optional_field_style parameter that will generate java.lang.Integer instead of a primitive int. When the proto is parsed, the caller can check if the value is null before using the value. Null means the value was not set.
The above call script can become:
protoc --javanano_out=store_unknown_fields=true,optional_field_style=reftypes:target/generated-sources --proto_path=input input/*.proto

Related

gRPC the protoc compiler creates not the expected

i start whith gRPC bulding an easy Java Chat Programm.
protc --version prints libprotoc 3.5.1
the -proto File:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "grpc";
// whihout this Option i get no service
option java_generic_services = true;
option java_outer_classname = "ChatProto";
option objc_class_prefix = "HLW";
package chat;
message ClientPost {
string name = 1;
string value = 2;
}
message ServerReply {
ClientPost back = 1;
}
// The service definition.
service Verbindung {
rpc ChatService (stream ClientPost) returns (stream ServerReply);
}
// file end
why i need to set the option java_generic_services ?
class ChatImpl extends grpc.Verbindung {
#Override
public void chatService(RpcController controller, ClientPost request, RpcCallback done) {
// why i get this kind of Service ?
}
}
//
2. why i get an other class name ? shut be VerbindungImplBase
expected Function
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { }
what must i do to get this kind of expected Service Function ?
may be an wrong protoc compiler / wrong Installation / missing Parts ?
You're likely not running the gRPC code generator. Without the full configuration of how you're running protoc I can't point out too much detail, but you are likely only generating the protobuf messages via java_generic_services=true.
You shouldn't need java_generic_services=true. Instead, you should generate the messages like you are now, but then also use the grpc-java plugin. There's documentation for when running protoc manually and our main documentation documents the preferred method, using Maven or Gradle plugins.
I have an open suse leap 42.2 System
this Version knows nothing about grpc - no Support from this side
i get the compiled protoc - it comes whithout the needed Java-gen Plugin
found https://github.com/grpc/grpc-java/blob/master/compiler/README.md
"Normally you don't need to compile the codegen by yourself, since pre-compiled binaries for common platforms are available on Maven Central."
i found only some exe files. - not useful
"Change to the compiler directory:"
i have no compiler dir. - still try to find out were i can get
NetBeans have only an Editor plugin for protofiles - so my IDE can't handel gRPC
maybe for other IDEs are the Maven Plugins for gRPC are helpful
i expected an full protoc Compiler with all needed plugins :-)
not an install the tool adventure.
a the Moment for me: gRPC - nice Idea , but i get an "install the gRPC" Adventure

How to access version of my project in build.gradle from a Java class

I'm quite new to Gradle so the answer might be simple, so I apologize if the answer is simple: I have a testing tool that needs to fetch it's version and compare it to the version of the application it is testing. However , the version of my tool is in my build.graddle as
version '1.0'
I tried different way to access it ( such as) :
task generateSources {
File outDir
outDir = file("$buildDir/classes/test/tests/Version.java")
doFirst {
outDir.exists() || outDir.mkdirs()
new File(outDir).write("public class Version { public static final String VERSION = \"$project.version\"; }")
}
}
compileJava.dependsOn generateSources
compileJava.source generateSources.outputs.files, sourceSets.main.java
I found this piece of code to output the version to another java file, but I fail to see how I'd be able to retrieve that info afterwards ( I mean, my tests are defined in src and I would need to point to a file that doesn't exist at compilation -- correct me if I'm wrong here).
Any idea on how I could accomplish this task?
First of all, you are trying to create java source file in your build/classes (it should contain compiled classes, not sources) directory, but you have to do it in your sources, otherwise it won't be compiled. And if you need this new class to be vailable not for tests, then use src/main/java, not src/test/java/
But anyway, I suppose for your case it's much easier to use some properties file for that and replace some token within it during build. That will allow you to make some static logic to get this property value and use it yet before running the build. So all you need is:
1- to have some properties file in your resources src/main/resources (for example app.properties), where should version variable be stored, with it's value like APP_VERSION_TOKEN
version=%APP_VERSION_TOKEN%
2- configure you Gradle processResources to replace tokens, something like this:
processResources {
filesMatching('**/app.properties') {
filter {
it.replace('%APP_VERSION_TOKEN%', version)
}
}
}
3- make some method to read this file and return the value of the property and use it where you need.
And that's all. For unit tests you can have another file with the same name under src/test/resource with the unchanging value you need for testing.

Java: Protocol Buffer does not generate parsing functions

I've the following .proto file:
message MediatorMessageMsg{
required double speed = 1;
required double heading = 2;
required string sender = 3;
}
and I use Eclipse Mars with Protocol Buffer 2.5.0 version. It generates the necessary file (which we are not supposed to edit) however I cannot use the important functions of
writeDelimitedTo()
parseDelimitedFrom()
newBuilder().set...
without these there is simply no point in using the entire thing. I checked the file and I can see parseDelimitedFrom() there, however I cannot call it in my own project (Yes, imported already). When I hover my mouse on the error, it gives me the following:
The method parseDelimitedFrom(ByteArrayInputStream) is undefined for the type MediatorMessage
Anyone has an idea why is this the case?
EDIT: Some more details regarding the question.
I cannot use the function below, for instance, to build my message. It raises an error.
MediatorMessage mediatorMessage = MediatorMessage.newBuilder().
or I cannot do this
ByteArrayOutputStream output = new ByteArrayOutputStream(bufferSize);
mediatorMessage.writeDelimitedTo(output);
or this
ByteArrayInputStream firstInput = new ByteArrayInputStream(buf);
mediatorMessageOne = MediatorMessage.parseDelimitedFrom(firstInput);
So these functions are not recognized for some reason.
As you still have not answered how your MediatorMessageMsg from the *.proto file becomes MediatorMessage.java find below a stripped down example. Which should point you in the right direction.
Assume following directory and file structure, protoc is assumed to be installed and in your PATH.
bin/
lib/protobuf-java-2.5.0.jar
src/Check.java
MediatorMessage.proto
src/Check.java
import com.google.protobuf.TextFormat;
import sub.optimal.MediatorMessage.MediatorMessageMsg;
class Check {
public static void main(String...args) {
MediatorMessageMsg.Builder builder = MediatorMessageMsg.newBuilder();
MediatorMessageMsg msg = builder.setSpeed(42.0)
.setHeading(0.0)
.setSender("foobar")
.build();
System.out.println(TextFormat.shortDebugString(msg));
}
}
MediatorMessage.proto
option java_package = "sub.optimal";
option java_outer_classname = "MediatorMessage";
message MediatorMessageMsg{
required double speed = 1;
required double heading = 2;
required string sender = 3;
}
generate Java source from proto file
protoc --java_out=src/ MediatorMessage.proto
this generates the Java source file src/sub/optimal/MediatorMessage.java.
compile the Java sources
javac -cp lib/protobuf-java-2.5.0.jar:src/. -d bin/ src/Check.java
this generates the files
bin/Check.class
bin/sub/optimal/MediatorMessage$1.class
bin/sub/optimal/MediatorMessage$MediatorMessageMsg$1.class
bin/sub/optimal/MediatorMessage$MediatorMessageMsg$Builder.class
bin/sub/optimal/MediatorMessage$MediatorMessageMsg.class
bin/sub/optimal/MediatorMessage$MediatorMessageMsgOrBuilder.class
bin/sub/optimal/MediatorMessage.class
run the simple check
java -cp lib/protobuf-java-2.5.0.jar:bin/ Check
output
speed: 42.0 heading: 0.0 sender: "foobar"

Generation of C# files with Google Protocol Fails

I am working on a project that uses Java, C# and also C++ applications. To communicate between them I am trying to use Google protocol buffer. I am using following .proto file, which was taken from examples:
package tutorial;
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
I am referring to following tutorial:
https://developers.google.com/protocol-buffers/docs/csharptutorial
Tutorials for other languages are also there.
I tried following command line arguments for each language:
Java:
C:\ProtoBuf\protoc -I=C:\trash --java_out=C:\trash C:\trash/addressbook.proto
C++:
C:\ProtoBuf\protoc -I=C:\trash --cpp_out=C:\trash C:\trash/addressbook.proto
C#:
C:\ProtoBuf\protoc -I=C:\trash --csharp_out=C:\trash C:\trash/addressbook.proto
Java and C++ compilations work properly even with some warning in case of Java. But I get following output with C# :
--csharp_out: protoc-gen-csharp: The system cannot find the file specified.
I am using this compiler: https://github.com/google/protobuf/releases/download/v2.6.1/protoc-2.6.1-win32.zip
What am I doing wrong here? do I need any other files for C# compilation?
You are trying to generate C# files using the old version of the protoc
protoc-2.6.1-win32.zip
C# code generator for both proto2 and proto3 was introduced only in Version 3.0.0-alpha-3
Introduced two new language implementations (Objective-C, C#) to
proto3.
So, download protoc Version 3.0.0-alpha-3, install it and call:
protoc -I=$SRC_DIR --csharp_out=$DST_DIR $SRC_DIR/your.proto
Beware that started from Version 3.0.0-beta-1 C# code generator only supports generating proto3:
Proto3 semantics supported; proto2 files are prohibited for C# codegen
I know how to gen proto files in c#
open visual studio, open nuget command line, type : Install-Package Google.ProtocolBuffers , link : Google.ProtocolBuffers 2.4.1.555
find Package/Google.ProtocolBuffers.2.4.1.555/tools/ProtoGen.exe
use command line, type : ProtoGen.exe addressbook.proto -output_directory=C:\trash
I write a python script to gen proto files, gen.py
import os, subprocess, threading
def main():
with open("conf.txt") as file:
exe = os.path.join(os.getcwd(), "..\\Package\\Google.ProtocolBuffers.2.4.1.555\\tools\\ProtoGen.exe")
out = "-output_directory=%s" % (os.path.join(os.getcwd(), "..\\Common\\libs\\protos"))
def gen(proto):
subprocess.check_call([exe, os.path.join("protos", proto), out])
list = []
for proto in file.read().split(','):
t = threading.Thread(target = gen, args = (proto, ))
t.start()
list.append(t)
for t in list:
t.join()
if __name__ == '__main__':
main()
conf.txt
base.proto,test.proto,addressbook.proto
I solved all my problems using / (slash) intead of \ (anti-slash) in all the path.
protoc.exe -I=D:/dev/xyz/projects --csharp_out=d:/temp D:/dev/xyz/projects/messages.proto

Get version of a .pkg file?

I have a Java application for MAC OSX that I have coded and made a .pkg of it. While creating the .pkg I gave it a version number also. Now I need to get the version number of this application in my java code so that i can check for updates when the application runs. When I right-click on my app file it doesn't show me the version I entered while creating the package.
Do I need to set the version of my app file that I created using the jar bundler for building the pkg???
Please suggest me how I could accomplish this.
The version number you set while creating the package (in the PackageMaker Project) is the version of the installer, not the version of your .app-File. It is needed, so that another installer can see if he downgrades the current installation or not. The installer will never ever look at the contents it is installing to the system.
To set the version of your your .app-Bundle, right-click your .app-file and select "Show Package Contents" from the appearing menu. Open the folder "Contents", there you will find a file called "Info.plist". You have to edit this file and have to set your version-info for your application there. You can do this by using Property List Editor (included in the Apple Developer Tools) or another tool like BBEdit for example.
To read from your .plist in your application, you need a special library. I recommend the Java property list library from Daniel Dreibrodt (more information about the .plist-Format you'll find in this post on my blog).
Generelly, you should set the version-info of your app-bundle, anyway you use it for updating-purposes or not. If it is not set, the user has no chance to get information about the version he has installed without launching your software.
What you need is not the version of your .pkg file, you need the version of your .app-Bundle. Anyway - the version of your .pkg-file is handled the same way as your .app-file. There is also the Info.plist, where you find the informations. It can also be parsed with the same library.
The pkg is a zip file containing a.o. a file called PackageInfo. PackageInfo is an XML file looking like this:
<pkg-info format-version="2" identifier="com.mycompany.pkg.MyApp" version="1.2.0" overwrite-permissions="false" install-location="/" auth="root">
<payload installKBytes="4717" numberOfFiles="146"/>
<scripts>
<preinstall file="./preinstall"/>
<postinstall file="./postinstall"/>
</scripts>
<bundle-version>
<bundle path="./Applications/MyApp.app" CFBundleShortVersionString="1.2.0" CFBundleVersion="166" id="com.mycompany.MyApp" CFBundleIdentifier="com.mycompany.MyApp">
<bundle path="./Contents/Library/LoginItems/HelperApp.app" CFBundleShortVersionString="1.0" CFBundleVersion="1" id="com.mycompany.HelperApp" CFBundleIdentifier="com.mycompany.HelperApp"/>
</bundle>
</bundle-version>
</pkg-info>
To get the package version, you could use the following XPath:
pkg-info/#version
To get the application version:
pkg-info/bundle-version/bundle/#CFBundleShortVersionString
And the build number is here:
pkg-info/bundle-version/bundle/#CFBundleVersion
I know it is a quite old question but the answers are not satisfying. Here is my solution:
A MacOS .pkg file is an archive in XAR format. So any XAR archive reader can read its contents. I found an XAR reader for Java from Sprylab here. This library has Apache 2.0 license so it is free to use also for commercial products. It is quite old but it works. The file "Distribution" in the archive is in XML format and gives details about the installer bundle, e.g. the version ;)
I am using JSON so I did not want to add an XML reader for reading just one value. So the following code uses the XAR library and a custom XML reader to extract the version of the bundle in the .pkg installer.
public static void main(String [ ] args) throws XarException {
XarSource xar = new FileXarSource(new File("PathToPkgFile/PkgFilename.pkg"));
XarEntry entry = xar.getEntry("Distribution");
String distributionStr = new String(entry.getBytes());
String bundleVersionXml = getSubstringByStr(distributionStr, "<bundle-version>", "</bundle-version>");
String bundleAttrStr = getSubstringByStr(bundleVersionXml, "<bundle", "/>");
String version = getAttributeValue(bundleAttrStr, "CFBundleVersion");
System.out.println(bundleVersionXml);
System.out.println(bundleAttrStr);
System.out.println(version);
}
private static String getSubstringByStr(String xmlString, String start, String end) {
int startIdx = xmlString.indexOf(start);
int endIdx = xmlString.indexOf(end);
return xmlString.substring(startIdx + start.length(), endIdx);
}
private static String getAttributeValue(String tagContentString, String attribute) {
int startIdx = tagContentString.indexOf(attribute) + attribute.length() + "=\"".length();
int endIdx = startIdx + tagContentString.substring(startIdx).indexOf("\"");
return tagContentString.substring(startIdx, endIdx);
}

Categories

Resources