Reading binary data from HttpServletRequest - java

Using Jetty, I'm sending bytes to URL http://localhost:8080/input/ like so -
public static void sampleBytesRequest (String url)
{
try
{
HttpClient client = new HttpClient();
client.start();
client.newRequest(url)
.content(new InputStreamContentProvider(new ByteArrayInputStream("batman".getBytes())))
.send();
}
catch (Exception e) { e.printStackTrace(); }
}
My server (also Jetty) has a handler like so -
public final class JettyHandler extends AbstractHandler implements JettyConstants, LqsConstants
{
#Override
public void handle (String target,
Request baseRequest,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
response.setContentType(UTF_ENCODING);
String requestBody = null;
try { requestBody = baseRequest.getReader().readLine(); }
catch (IOException e) { e.printStackTrace(); }
System.out.println(new String(IOUtils.toByteArray(request.getInputStream())));
}
}
As you can see, I'm trying to recreate the original string from the binary data and print it to stdout.
However, if I set a break point at the print statement in the handler, when the request reaches that line, the server abruptly seems to skip over it.
What am I doing wrong? How can I get the binary data I'm sending over and recreate the string?
Thank you!

Turns out the issue was with my client.
Instead of
client.newRequest(url)
.content(new InputStreamContentProvider(new ByteArrayInputStream("batman".getBytes())))
.send();
The proper way to do this is -
client.newRequest(url)
.content(new BytesContentProvider("batman".getBytes()), "text/plain")
.send();

Related

How to close a com.google.api.client.http.HttpResponse object properly

I am trying to close a com.google.api.client.http.HttpResponse object, but I get the Eclipse error
Unhandled exception type IOException
on the line response.disconnect();
Here's a code example:
HttpRequest request = null;
HttpResponse response = null;
try {
request = this.buildJsonApiRequest(apiUrl);
response = this.execute(request);
return response.parseAs(MyClass.class);
} catch (final IOException e) {
throw new DaoException(e);
} finally {
if (response != null) {
response.disconnect();
}
}
The code works without the finally block, but I am concerned about many response objects being opened and not closed. What is the proper way to do this?
You need to put the disconnect call within a try-catch block because according to Google API documentation that method could throw an IOException:
public void disconnect() throws IOException
Follow this link to learn more about it:
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/http/HttpResponse#disconnect()
This is in response to Eleazar Enrique answer that the disconnect needs to be within a try block. This is an example of how to possibly write it more elegantly and make it reusable.
You could create a handler class that implements autoCloseable then use try-with-resource
public class HttpResponseHandler implements AutoCloseable {
private HttpResponse response;
public HttpResponseHandler(HttpResponse response) {
this.response = response;
}
}
public <T> T parseAs(Class<T> clazz) throws IOException {
return response.parseAs(clazz);
}
#Override
public void close() {
if (response != null) {
try {
response.disconnect();
} catch (IOException ex) {}
}
}
then in your code it would be something like this
HttpRequest request = this.buildJsonApiRequest(apiUrl);
try (HttpResponseHandler handler = new HttpResponseHandler(this.execute(request)) {
return handler.parseAs(MyClass.class);
} catch (final IOException e) {
throw new DaoException(e);
}
The AutoCloseable will close the connection for you, so you wouldn't have to handle it in the finally block.

Android Okhttp asynchronous calls

I am attempting to use the Okhttp library to connect my android app to my server via API.
My API call is happening on a button click and I am receiving the following android.os.NetworkOnMainThreadException. I understand that this is due the fact I am attempting network calls on the main thread but I am also struggling to find a clean solution on Android as to how make this code use another thread (async calls).
#Override
public void onClick(View v) {
switch (v.getId()){
//if login button is clicked
case R.id.btLogin:
try {
String getResponse = doGetRequest("http://myurl/api/");
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
String doGetRequest(String url) throws IOException{
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
Above is my code, and the exception is being thrown on the line
Response response = client.newCall(request).execute();
I've also read that Okhhtp supports Async requests but I really can't find a clean solution for Android as most seem to use a new class that uses AsyncTask<>?
To send an asynchronous request, use this:
void doGetRequest(String url) throws IOException{
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request)
.enqueue(new Callback() {
#Override
public void onFailure(final Call call, IOException e) {
// Error
runOnUiThread(new Runnable() {
#Override
public void run() {
// For the example, you can show an error dialog or a toast
// on the main UI thread
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
String res = response.body().string();
// Do something with the response
}
});
}
& call it this way:
case R.id.btLogin:
try {
doGetRequest("http://myurl/api/");
} catch (IOException e) {
e.printStackTrace();
}
break;

Java Communication netty server - Socket client

For a chat server project I use netty as server, with the following code in my handler :
public class PacketHandler extends ChannelInboundHandlerAdapter{
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg;
try {
AbstractClientPacket packet = ClientPacketHandler.handle(in);
if(packet != null && packet.read()){
packet.run();
ctx.write(msg+"\r\n");
}
} finally {
ReferenceCountUtil.release(msg);
}
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
So, my packet is correctly handled and it works fine, but then, i do ctx.write(msg+"\r\n"); to send back the message to my client, acting like an echo server.
Here is the Client's code :
public class ChatClient {
static Socket socket;
static DataOutputStream out;
static BufferedReader in;
public static void main(String[] args){
try {
initSocket();
String test = "Salut 1";
TestPacket packet = new TestPacket(0x18,test.getBytes());
sendPacket(packet);
while(true){
try {
String message = in.readLine();
System.out.println(message);
} catch (IOException e) {
e.printStackTrace();
}
}
//TEST
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static void initSocket(){
try {
socket = new Socket("localhost",58008);
out = new DataOutputStream(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader((socket.getInputStream())));
} catch (IOException e) {
e.printStackTrace();
}
}
private static void sendPacket(TestPacket p) throws IOException{
out.write(p.getRawData());
out.flush();
}
}
The packet is correctly sent, but i get nothing as reply, and when i stop my server, the client is spamming null because of my while(true), but i don't get my message back, nothing is displayed and i really don't know why.
I can't use netty for the client because this one is just for test purpose, the final client will be written in C# (Unity Engine), so i can't use netty in this one, I have to do it with native socket handling.
EDIT:
According to wireshark, The packet from client is sent but the server answer is not, i don't see the packet From server containing "Salut 1".
You did:
ctx.write(msg+"\r\n");
msg is not a String but a ByteBuf. If you want to append \r\n to the received message, you should do the following:
in.writeByte('\r');
in.writeByte('\n');
ctx.write(in);
Also, because you reused the received message (in) as a response, you should not release it:
// Do NOT call this.
ReferenceCountUtil.release(in);
If you really intended to call ctx.write(msg + "\r\n"), please make sure that your pipeline has StringEncoder.

When response is delivered to client in asynchronous Servlets?

I'm having problems understanding how asynchronous servlets work, and in general how servlets deliver their response to the client.
What I'm trying to do is upload a video to a servlet via ajax. I thought that using an async servlet, I would obtain the response immediately in my browser and then the long task would be done in another thread.
I post my initial code here, before any code is written for file process, just an initial servlet to test asynchronism.
#WebServlet(name = "VideoUploader", urlPatterns = {"/VideoUploader"},
asyncSupported = true)
#MultipartConfig
public class VideoUploader extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final PrintWriter pw = response.getWriter();
final AsyncContext ac = request.startAsync();
ac.setTimeout(80000);
ac.addListener(new AsyncListener() {
#Override
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("On complete");
}
#Override
public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("On timeout");
}
#Override
public void onError(AsyncEvent event) throws IOException {
System.out.println("On error");
}
#Override
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("On start async");
}
});
ac.start(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 10; i++) {
System.out.println("Async task: "
+ Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
ac.complete();
}
});
pw.write("end");
pw.close();
}
}
Then, the client part is:
<form id="formVideo">
<label for="videoFile">VĂ­deo:</label>
<input id="videoFile" name="videoFile" type="file" /> <br/>
<input id="uploadVideoBtn" type="button" value="Subir" onClick="uploadVideo();"/>
</form>
<div id="notificaciones"/>
<script type="text/javascript">
function uploadVideo() {
var file = document.getElementById("videoFile").files[0];
var formdata = new FormData();
formdata.append("file", file);
var xhr = new XMLHttpRequest();
xhr.open("POST","/webapp/VideoUploader", true);
xhr.send(formdata);
xhr.onload = function(e) {
if (this.status == 200) {
alert(this.responseText);
}
};
}
</script>
When I didn't attach a video to the file input, the process is done as I expected, the response is immediately received in the browser. But when I attached a file of any size, my browser doesn't receive the response until the other thread is over.
I was researching on non blocking IO, but I'm not sure if it has something to do with this behaviour or not.
I'm still not sure how I want to implement this, although I'll listen to any advice, but what I would like is to understand the behaviour of this asynchronous servlets.
it is obivious, your browser will wait until the other thread completes. The following steps involved
Client Sent Request to Server
Server allocates Thread (Servlet Container) from ThreadPool
Servlet container creates Servlet instance / reuse existisng Servlet instance and invoke Servcie method in (Servlet Thread)
With in Service method by calling startAsync() will start new thread and pass the request,response instances to the new Thread to process the request note** New Thread is not blocking the http connection , it is just a thread in the jvm which is not bliocking any IO at this moment
Servlet Thread exists service method and returned to thread pool Note** here Response not yet sent to Client / Browser
Once the Process started in step 4 completed that thread will request Servlet Container to allocate to new Servlet thread to send the respond back to Client.
Only the at Step 6 the response will return back to Client. So there is no difference between the normal request and with "asyncSupported = true" from client point of view. Servlet 3.0 supports Threads per request by using "asyncSupported = true" instead of Thread per connection. Thread per connection will cause Thread Starvation.
#WebServlet(name = "VideoUploader", urlPatterns = { "/VideoUploader" }, asyncSupported = true)
#MultipartConfig
public class VideoUploader extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
#Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
final AsyncContext ac = request.startAsync();
ac.setTimeout(80000);
ac.addListener(new AsyncListener() {
public void onComplete(AsyncEvent event) throws IOException {
System.out.println("On complete");
}
public void onTimeout(AsyncEvent event) throws IOException {
System.out.println("On timeout");
}
public void onError(AsyncEvent event) throws IOException {
System.out.println("On error");
}
public void onStartAsync(AsyncEvent event) throws IOException {
System.out.println("On start async");
}
});
ac.start(new Runnable() {
public void run() {
System.out.println("Async task: "
+ Thread.currentThread().getName());
try {
for (Part part : ((HttpServletRequest) ac.getRequest())
.getParts()) {
System.out.println("File received"); // You Should write
// file here
// like
// part.write("fileName");
}
} catch (IOException e1) {
e1.printStackTrace();
} catch (ServletException e1) {
e1.printStackTrace();
}
ac.complete();
PrintWriter pw = null;
try {
pw = ac.getResponse().getWriter();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
pw.write("end");
pw.close();
}
});
}
}
Asynchronous servlet hands over the long running server side job to a different server thread. Non-Blocking IO, a new feature in servlet 3.1, deals with situation when incoming data is blocking or streamed slower than the server can read. Both are solutions to avoid servlet thread starvation. They are not about returning response to client immediately.
Since you are using Ajax, not a regular browser file upload, it should be easily implemented at the Ajax side with even a synchronous servlet, if you do not care about servlet thread starvation. Ajax is asynchronous in nature. Here is an example tutorial
http://www.javabeat.net/asynchronous-file-upload-using-ajax-jquery-progress-bar-and-java/

Render a pdf stream on a jsp using struts2

I am using struts2 in my web application. I want to render a pdf stream on a jsp. i am currently doing this:
public String renderPDF() throws Exception
{
myService.rederPDF(getServletResponse().getServletOutputStream());
return SUCCESS;
}
The rederPDF method of myService gets a pdf stream and writes to the servlet response output stream. But this throws an exception that "The response has already been committed".
This exception occurs when you already sent some thing to client before you forward.
I am using Servlets for downloading files. Have a look.
public class FileDownloadServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
byte[] b = null;
ServletOutputStream sop = null;
try {
response.setContentType("application/pdf");
response.setHeader("Content-Disposition","attachment; filename=yourFileName.pdf");
sop = response.getOutputStream();
b = myService.getFileData(); /* your code */
sop.write(b);
return;
} catch (Exception e) {
/* some code*/
}
finally{
/* some code*/
}
}
}

Categories