Google Protocol Buffers not reading properly - java

I am just setting up a new Java project which will (maybe, not so sure now) make use of Google Protocol Buffers. I am new to this API, so I started with a very basic test. A test whose outcome, to be honest, really disappointed me. Why isn't this very straight-forward code working?
var output = new ByteArrayOutputStream();
Message.Echo.newBuilder().setMsg("MSG1?").build().writeTo(output);
System.out.println("output.length " + output.toByteArray().length);
Message.Echo.newBuilder().setMsg("MSG2!!").build().writeTo(output);
System.out.println("output.length " + output.toByteArray().length);
var input = new ByteArrayInputStream(output.toByteArray());
System.out.println("input.available " + input.available());
System.out.print(Message.Echo.parseFrom(input));
System.out.println("input.available " + input.available());
System.out.print(Message.Echo.parseFrom(input));
The above code produces the following output:
output.length 7
output.length 15
input.available 15
msg: "MSG2!!"
input.available 0
It entirely misses the first messages, or rather it seems to "overwrite" it in some way since all the 15 bytes get read. Plus it fails to block on the second call considering there are no further bytes to read.
However, changing the two reading lines into:
System.out.print(Message.Echo.parseFrom(input.readNBytes(7)));
System.out.print(Message.Echo.parseFrom(input.readNBytes(15-7)));
correctly prints the two messages. I am running Kubuntu 18.04 with JDK 11. Am I missing something really important (not mentioned in the official tutorial) or is this a bug?
This is the .proto file:
syntax = "proto3";
package ...;
option java_package = "...";
option java_outer_classname = "Message";
message Echo {
string msg = 1;
}

Ok, it seems that in order to write/read multiple message using the same set of streams requires using writeDelimitedTo and parseDelimitedFrom instead, because parseFrom reads until reaching reaches EOF.
It seems that the preferred behaviour is to use a new Socket for each message. It sounds a bit odd to me, but I am sure there are good reason behind this. It should be better explained in the official tutorial though.

Related

Why is Java AWSKMS client decryption so much slower than Python boto3?

In my Java lambda, during cold start I want to decrypt passwords from environment variables. I'm using the AWSKMS client to decrypt a string (following examples from here), and I find it takes up to 2 seconds the first time I do this. In contrast, I have some code in python using boto3 which is doing the same thing and it runs in under 100ms. So clearly there's something wrong with my Java code. Here is the Java code with comments showing the 2 calls that together add up to nearly 2 seconds:
ByteBuffer ciphertextBlob = ByteBuffer.wrap(Base64.getDecoder().decode(encrValue));
DecryptRequest req = new DecryptRequest().withCiphertextBlob(ciphertextBlob);
AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient(); // This call takes 800+ ms
ByteBuffer plainText = kmsClient.decrypt(req).getPlaintext(); // This call takes 900+ ms
String plainTextStr = StringUtils.stripToNull(StandardCharsets.UTF_8.decode(plainText).toString());
And here's the equivalent python code:
plainTextStr = boto3.client('kms').decrypt(CiphertextBlob=b64decode(encrValue))['Plaintext'].decode()
Clearly I'm doing something wrong in the Java code, but I can't find a simpler example of how to do it in Java.

How can I get a proper URI in Java, Windows

In Wikipedia, it says:
Windows
Here are some examples which may be accepted by some applications on Windows systems, referring to the same, local file c:\WINDOWS\clock.avi
file://localhost/c:/WINDOWS/clock.avi
file:///c:/WINDOWS/clock.avi
Here is the URI as understood by the Windows Shell API:[2]
file:///c:/WINDOWS/clock.avi
Suppose, I need conversion of filenames type: C:\WINDOWS\clock.avi to URIs for use in a JavaFX WebView as href for tags, css, links etc. etc.
The app intercepts clicks on the links, analyzes and performs actions, depending on the link (runs pdf, internet, music etc.)
But, I don't manage to generate the proper URI from filenames to be used in those webview pages.
These are the results that Java provides:
Code
private static void print(String s) {
System.out.println(s);
}
public static void main(String[] args) throws Exception {
String fileName = "c:\\WINDOWS\\clock.avi";
print("0 - " + new File(fileName).toString());
print("1 - " + new File(fileName).toURI().toString());
print("2 - " + new File(fileName).toURI().toURL().toString());
print("3 - " + new URL(new File(fileName).toURI().toString()).toString());
}
Results:
0 - c:\WINDOWS\clock.avi
1 - file:/c:/WINDOWS/clock.avi
2 - file:/c:/WINDOWS/clock.avi
3 - file:/c:/WINDOWS/clock.avi
So, No 1, 2 and 3 are all same, and none of them are correct - as I infer from URI rules. Is it a Java bug?
Is there a proper way to get exactly the file:///c:/WINDOWS/clock.avi uri from a file path c:\WINDOWS\clock.avi instead of the resulting file:/c:/WINDOWS/clock.avi, which is reported as wrong in various places?
The StackOverflow most popular answers is use No. 1 or No. 2, but the above shows that the results are not correct URIs.
Calling toUri() on a Path yields the URI you want. I don't see anything in the documentation that states this is guaranteed behavior, however; or if it is in the documentation, I'm just not recognizing it. So, in case this behavior is subject to change, note that I only tried this using JDK 10.0.1.
In my opinion, if you can switch your code to use the file API introduced with NIO2 (Java 7), rather than java.io that would be ideal. If you can't or don't want to for whatever reason, then you can convert a File into a Path using File.toPath() (and vice versa using Path.toFile()).
Using this code:
File file = new File("C:\\Users\\Username\\Desktop");
System.out.printf("File.toURI() = %s%nFile.toPath().toUri() = %s%n",
file.toURI(), file.toPath().toUri());
Gave me this output:
File.toURI() = file:/C:/Users/Username/Desktop/
File.toPath().toUri() = file:///C:/Users/Username/Desktop/

CommandExecuteIn Background throws a "Not an (encodable) value" error

I am currently trying to implement file exports in background so that the user can do some actions while the file is downloading.
I used the apache isis CommandExexuteIn:Background action attribute. However, I got an error
"Not an (encodable) value", this is an error thrown by the ScalarValueRenderer class.
This is how my method looks like:
#Action(semantics = SemanticsOf.SAFE,
command = CommandReification.ENABLED)
commandExecuteIn = CommandExecuteIn.BACKGROUND)
public Blob exportViewAsPdf() {
final Contact contact = this;
final String filename = this.businessName + " Contact Details";
final Map<String, Object> parameters = new HashMap<>();
parameters.put("contact", contact);
final String template = templateLoader.buildFromTemplate(Contact.class, "ContactViewTemplate", parameters);
return pdfExporter.exportAsPdf(filename, template);
}
I think the error has something to do with the command not actually invoking the action but returns the persisted background command.
This implementation actually worked on the method where there is no return type. Did I miss something? Or is there a way to implement background command and get the expected results?
interesting use case, but it's not one I anticipated when that part of the framework was implemented, so I'm not surprised it doesn't work. Obviously the error message you are getting here is pretty obscure, so I've raised a
JIRA ticket to see if we could at least improve that.
I'm interested to know in what user experience you think the framework should provide here?
In the Estatio application that we work on (that has driven out many of the features added to the framework over the last few years) we have a somewhat similar requirement to obtain PDFs from a reporting server (which takes 5 to 10 seconds) and then download them. This is for all the tenants in a shopping centre, so there could be 5 to 50 of these to generate in a single go. The design we went with was to move the rendering into a background command (similar to the templateLoader.buildFromTemplate(...) and pdfExporter.exportAsPdf(...) method calls in your code fragment, and to capture the output as a Document, via the document module. We then use the pdfbox addon to stitch all the document PDFs together as a single downloadable PDF for printing.
Hopefully that gives you some ideas of a different way to support your use case
Thx
Dan

Testing HLS using JMeter

I am using JMeter to test HLS playback from a Streaming Server. So, the first HTTP request is for a master manifest file(m3u8). Say,
http://myserver/application1/subpath1/file1.m3u8
The reply to this will result in a playlist something like,
subsubFolder/360p/file1.m3u8
subsubFolder/480p/file1.m3u8
subsubFolder/720p/file1.m3u8
So, next set of URLs become
http://myserver/application1/subpath1/subsubFolder/360p/file1.m3u8
http://myserver/application1/subpath1/subsubFolder/480p/file1.m3u8
http://myserver/application1/subpath1/subsubFolder/720p/file1.m3u8
Now, individual reply to these further will be an index of chunks, like
0/file1.ts
1/file1.ts
2/file2.ts
3/file3.ts
Again, we have next set of URLs as
http://myserver/application1/subpath1/subsubFolder/360p/0/file1.ts
http://myserver/application1/subpath1/subsubFolder/360p/1/file1.ts
http://myserver/application1/subpath1/subsubFolder/360p/2/file1.ts
http://myserver/application1/subpath1/subsubFolder/360p/3/file1.ts
This is just the case of one set(360p). There will be 2 more sets like these(for 480p, 720p).
I hope the requirement statement is clear uptill this.
Now, the problem statement.
Using http://myserver/application1 as static part, regex(.+?).m3u8 is applied at 1st reply which gives subpath1/subsubFolder/360p/file1. This, is then added to the static part again, to get http://myserver/application1/subpath1/subsubFolder/360p/file1 + .m3u8
The problem comes at the next stage. As, you can see, with parts extracted previously, all I'm getting is
http://myserver/application1/subpath1/subsubFolder/360p/file1/0/file1.ts
The problem is obvious, an extra file1, 360p/file1 in place of 360p/0.
Any suggestions, inputs or alternate approaches appreciated.
If I understood the problem correctly, all you need is the file name as the other URLs can be constructed with it. Rather than using http://myserver/application1 as static part of your regex, I would try to get the filename directly:
([^\/.]+)\.m3u8$
# match one or more characters that are not a forward slash or a period
# followed by a period
# followed by the file extension (m3u8)
# anchor the whole match to the end
Now consider your urls, e.g. http://myserver/application1/subpath1/subsubFolder/360p/file1.m3u8, the above regex will capture file1, see a working demo here. Now you can construct the other URLs, e.g. (pseudo code):
http://myserver/application1/subpath1/subsubFolder/360p/ + filename + .m3u8
http://myserver/application1/subpath1/subsubFolder/360p/ + filename + /0/ + filename + .ts
Is this what you were after?
Make sure you use:
(.*?) - as Regular Expression (change plus to asterisk in your regex)
-1 - as Match No.
$1$- as template
See How to Load Test HTTP Live Media Streaming (HLS) with JMeter article for detailed instructions.
If you are ready to pay for a commercial plugin, then there is an easy and much more realistic solution which is a plugin for Apache JMeter provided by UbikLoadPack:
Besides doing this job for you, it will simulate the way a player would read the file. It will also scale much better than any custom script or player solution.
It supports VOD and Live which are quite difficult to script.
See:
http://www.ubik-ingenierie.com/blog/easy-and-realistic-load-testing-of-http-live-streaming-hls-with-apache-jmeter/
http://www.ubik-ingenierie.com/blog/ubikloadpack-http-live-streaming-plugin-jmeter-videostreaming-mpegdash/
Disclaimer, we are the providers of this solution

Start a lightweight web-server using Swift to receive OAuth1.0 callback in iOS App

I'm a newbie in Swift (and iPhone dev). I'm working on a project where I need to build an iOS (using swift) mobile client to demonstrate OAuth1.0 (3-legged flow).
I'm not finding any concrete solution to start a server using swift. I need to pass a call-back endpoint to the request_token url so that my program can receive the oauth_verifierId.
I found the following close solutions (libs) from net, but either lack of examples/docs or due to my less exp on swift, things are not in place yet.
https://github.com/swisspol/GCDWebServer - No/less concrete example (not sure how to import this in swift project)
https://github.com/robbiehanson/CocoaHTTPServer - Looks good but not
getting any e2e solution. I want to avoid Obj-C lib in my Swift project.
https://github.com/glock45/swifter
Actually, I don't need a wrapper like above. It would be best if I could write a Java equivalent like following.
ServerSocket s = new ServerSocket(7000);
Socket remote = s.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(
remote.getInputStream()));
PrintWriter out = new PrintWriter(remote.getOutputStream());
String str = null;
while (!str.equals("")){
str = in.readLine();
if(str.startsWith("GET")){
String[] splitStr = str.split("&");
for(String s1 : splitStr){
if(s1.startsWith("oauth_verifier")){
String verifierId = s1.split("=")[1];
System.out.println("VerifierId - " + verifierId);
}
}
break;
}
}
I think my answer would a little bit late, just put a sign here for later comers.
If you are about to use GCDWebServer:
pod "GCDWebServer", "~> 3.0" in your Podfile, then pod install, pod update.
Put a file named APP_NAME-Bridging-Header.h in SOME_PATH, put these lines below the #define statement:
#import "GCDWebServer.h"
#import "GCDWebServerDataResponse.h"
Go Project Name -> Build Settings -> Search for bridging -> update Objective-C Bridging Header to $(SRCROOT)/SOME_PATH/APP_NAME-Bridging-Header.h.
Now the Objective-C library is globally imported, you could use it everywhere.
Use this line of code to instantiate a GCDWebServer instance:
let webServer = GCDWebServer()
Now play it with yourself :)

Categories

Resources