I'm trying to send JSON from a Python client to a Java server
The JSON data type is bytes (in Python) and when I deserialize it (in Python) and print it, it looks perfect. The server works fine when a Java client connects and when I deserialize the JSON and print it in Java it looks exactly the same as in Python and the actual JSON files. The JSON all looks good, but the data isn't accepted by the Java server.
data = open(file_path, 'r').read() # reading JSON object as string
serialized_data = pickle.dumps(data)
s.send(serialized_data)
When I send a JSON file the Java server acknowledges the connection but the JSON data for whatever reason isn't accepted.
Java Client
String sentence = new String(readFile());
if(!sentence.equals("fileNotFound")) {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(sentence);
}
Java Server
ObjectInputStream inFromClient = new ObjectInputStream(socket.getInputStream());
String clientString = null;
try {
clientString = (String) inFromClient.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
inFromClient.close();
You appear to be doing this:
Read JSON from file as a String
Pickle the string
Send the pickle to Java.
That won't work. A pickle is a Python-specific serialization format. Java doesn't understand it.
The data you are reading from the file is already serialized .... as JSON.
Solution: send the string containing the JSON without pickling it.
On the other hand, if the Java server expects to receive something that has been serialized using ObjectOutputStream, then you have a bigger problem. The Java Object Serialization protocol is Java specific. Python doesn't support it. But if you are actually sending JSON to the server you should need to do that. Change the server to accept JSON, and get rid of the ObjectInputStream / ObjectOutputStream code on both sides.
On the third hand, if you can't get rid of the ObjectInputStream / ObjectOutputStream stuff, then maybe you need to modify the server side to either provide a separate API for python to call, or get the server to check the request's "content-type" header and handle either form of data serialization (JSON and Object Serialization protocol)
Related
I'm trying to build a HTTP server in Java out of curiosity.
I know that HTTP uses sockets underneath(correct me if i'm wrong). So started programming initially using ServerSocket class.
public class Server
{
public static void main(String[] args) throws IOException
{
System.out.println("Listening.....");
ServerSocket ss = new ServerSocket(80);
while(true)
{
Socket s = ss.accept();
Scanner sc = new Scanner(s.getInputStream());
while(sc.hasNextLine())
{
String line = sc.nextLine();
if(line.equals(""))
break;
else
System.out.println(line);
}
System.out.println("-------------------------------");
PrintStream ps = new PrintStream(s.getOutputStream());
ps.println("Hello from Server");
s.close();
ps.close();
sc.close();
}
}
}
(I'm using Thread in my actual code to serve multiple users. I've just provided the basic code.)
I'm getting all the headers from the web browser. But how can I send the files and images?
For, simple HTML I can read the file and use PrintStream to print it on the web browser.
But how can I send JavaScript, Images etc to the browser?
HTTP has a protocol to it, you need to follow that protocol. The HTTP 1.1 protocol spec still in wide use is RFC 2616 (though it has officially been replaced with newer RFCs 7230, 7231, 7232, 7233, 7234, and 7235).
In my answer to another question, I show the correct way to read an inbound HTTP request from a Java Socket directly.
When sending a reply back, you can use a PrintStream or PrintWriter to send the response HTTP headers. However, the body content is sent as raw bytes, based on the format specified by the Content-Type and Transfer-Encoding response headers. Typically, you would just send the raw bytes directly to the socket's OutputStream, or at least to a BufferedOutputStream attached to it. If you are sending a pre-existing file from disk, regardless of its type, you could just open an InputStream for the file and then copy its data directly to the socket's OutputStream. If you are generating data dynamically, then you would send the data to the socket's OutputStream using whatever intermediate classes are appropriate. Print... classes are only appropriate for textual data, not binary data, like images.
That being said, Java has its own HttpServer and HttpsServer classes. You should consider using them.
Basically the same way. You should "print" the raw bytes to the socket's OutputStream.
However, for the browser to be able to understand it, you need to shape your response according to the HTTP/1.1 protocol. Specifying a Content-Type header will tell the browser what it is receiving from you. Specifying a Content-Length header will tell the browser how many bytes it is receiving from you. Etc.
I have a TCP socket connected to a server communicating via JSON. Since it's a stream the packets often merge into one larger through the inputstream, and I've been trying to parse it correctly but haven't found a successful way to read the input.
The input looks something like this
+#$3{"data1":"datahere","moredata":25}2*${"data1":"differentdata","otherdata":001}
This I have parsed to be
{"data1":"datahere","moredata":25}{"data1":"differentdata","otherdata":001}
Using a reader only returns the first json object when it is set to lenient, otherwise it throws an exception. The JSON comes from a socket, and is a result of packet merging. What can be done in a JSON library to parse these separately?
I'm using Netty Socket IO to send socket.io content from Java (well, actually Scala.) I've tried several ways of sending a JSON object to the client:
hardcoded String
standard Java json library
Gson library
Each time, when the data gets to the client, it's just a string that looks like a JSON object. I'm currently sending it with:
case class Data(message:String) and gson.toJson(new Data("what up")). The object looks like this on the client: "{"message":"what up"}", although it's just a String and not a JSON object.
Any ideas on how to get an actual JSON object on the other side?
Thanks
This works (JQuery):
$.parseJSON(string)
I am developing an Android application which suppose to call Axis2 Web Service (already implemented and running) where the previous developer made in such a way that Byte[] is the common form of passing Object around. Suppose there is a need to invoke web service in the Axis2 which should return List, the web service will convert the instance into Byte[] and return the Byte[], where the client will convert it back.
Here is the snippet from the service:
public byte[] getMyPersonList() throws Exception {
java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(baos);
oos.writeObject(new List<Person>());
return (baos.toByteArray());
}
In the client (not my android application but the existing desktop application which are developed by the same people making the web service)
byte[] buffer = (byte[]) serviceClient.invokeBlocking(methodName,
new Object[] {}, new Class[] { byte[].class })[0];
java.io.ObjectInputStream ois = new java.io.ObjectInputStream(
new java.io.ByteArrayInputStream(buffer));
return (List<Person>) ois.readObject();
The invokeBlocking() method seems to automatically convert the returned value from the service automatically back to byte[], but I am having trouble doing the same thing in my application.
This is what the return value looks like when I invoke the service manually over browser:
<return>
rO0ABXNyABNqYXZhLnV0aWwuQXJyYXlMaXN0eIHSHZnHYZ0DAAFJAARzaXpleHAAAAAJdwQAAAAKc3IAJ3dvcmtmbG9.......................
</return>
And what I have done so far is to directly get the return as string and use getBytes():
byte [] soapReturnBytes = resultsRequestSOAP.getPropertyAsString("return").getBytes();
ObjectInputStream ois = new ObjectInputStream(bais);
myPersonList= (List<Person>) ois.readObject();
But I received stream corrupted error which could mean that it simply not the same content when I convert it back.
So my question is:
When returning Byte[], what does Axis2 engine do to convert the values to fit it into the SOAP return
What are the methods of converting this 'stringified' value back to Byte[], in case I can't do anything about the web service (no modification on the web service)
Any suggestion is greatly appreciated.
EDIT:
As suggested, I am using a decoder to get the result, however still no luck:
String result = resultsRequestSOAP.getPropertyAsString("return");
byte[] soapReturnBytes = Base64.decode(result, Base64.DEFAULT);
ByteArrayInputStream bais = new ByteArrayInputStream(soapReturnBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
orgs = (List<Person>) ois.readObject();
I still received the same error:
java.io.StreamCorruptedException: Wrong format: 0
Any suggestion? getting frustrated
EDIT 2:
I created another service which returns String as byte[], and in my Android application I received the byte[] and convert it back to the original String. So perhaps it has something to do with the way I am using the Stream to convert my Object <=> byte [].
When returning Byte[], what does Axis2 engine do to convert the values to fit it into the SOAP return
The Java type byte[] is mapped to the XML Schema type xsd:base64Binary. The transformation is called Base64 encoding.
What are the methods of converting this 'stringified' value back to Byte[], in case I can't do anything about the web service (no modification on the web service)
You need to use a Base64 decoder. There are numerous Java implementations available, e.g. Commons Codec.
I have a GWT page where user enter data (start date, end date, etc.), then this data goes to the server via RPC call. On the server I want to generate Excel report with POI and let user save that file on their local machine.
This is my test code to stream file back to the client but for some reason I think it does not know how to stream file to the client when I'm using RPC:
public class ReportsServiceImpl extends RemoteServiceServlet implements ReportsService {
public String myMethod(String s) {
File f = new File("/excelTestFile.xls");
String filename = f.getName();
int length = 0;
try {
HttpServletResponse resp = getThreadLocalResponse();
ServletOutputStream op = resp.getOutputStream();
ServletContext context = getServletConfig().getServletContext();
resp.setContentType("application/octet-stream");
resp.setContentLength((int) f.length());
resp.setHeader("Content-Disposition", "attachment; filename*=\"utf-8''" + filename + "");
byte[] bbuf = new byte[1024];
DataInputStream in = new DataInputStream(new FileInputStream(f));
while ((in != null) && ((length = in.read(bbuf)) != -1)) {
op.write(bbuf, 0, length);
}
in.close();
op.flush();
op.close();
}
catch (Exception ex) {
ex.printStackTrace();
}
return "Server says: " + filename;
}
}
I've read somewhere on internet that you can't do file stream with RPC and I have to use Servlet for that. Is there any example of how to use Servlet and how to call that servlet from ReportsServiceImpl. Do I really need to make a servlet or it is possible to stream it back with my RPC?
You have to make a regular Servlet, you cannot stream binary data from ReportsServiceImpl. Also, there is no way to call the servlet from ReportsServiceImpl - your client code has to directly invoke the servlet.
On the client side, you'd have to create a normal anchor link with the parameters passed via the query string. Something like <a href="http://myserver.com/myservlet?parm1=value1&.."</a>.
On the server side, move your code to a standard Servlet, one that does NOT inherit from RemoteServiceServlet. Read the parameters from the request object, create the excel and send it back to the client. The browser will automatically popup the file download dialog box.
You can do that just using GWT RPC and Data URIs:
In your example, make your myMethod return the file content.
On the client side, format a Data URI with the file content received.
Use Window.open to open a file save dialog passing the formatted DataURI.
Take a look at this reference, to understand the Data URI usage:
Export to csv in jQuery
It's possible to get the binary data you want back through the RPC channel in a number of ways... uuencode, for instance. However, you would still have to get the browser to handle the file as a download.
And, based on your code, it appears that you are trying to trigger the standard browser mechanism for handling the given mime-type by modifying the response in the server so the browser will recognize it as a download... open a save dialog, for instance. To do that, you need to get the browser to make the request for you and you need the servlet there to handle the request. It can be done with rest urls, but ultimately you will need a serviet to do even that.
You need, in effect, to set a browser window URL to the URL that sends back the modified response object.
So this question (about streaming) is not really compatible with the code sample. One or the other (communication protocols or server-modified response object) approach has to be adjusted.
The easiest one to adjust is the communication method.