How to serialize a object in the HttpHandler class - java

I have to serialize an object and send it from a httpserver
i already know how to send a string from the server to the client,but i don't know how to send a object
So i have this code :
public class Test {
public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
server.createContext("/test", new MyHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
static class MyHandler implements HttpHandler {
public void handle(HttpExchange t) throws IOException {
String response = "This is the response";
//this part here shows how to send a string
//but i need to send an object here
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
so i tried to search google but no results,and i tried to change the code (mechanically without knowing well what im doing as im not used to HttpServer's in java)
this way :
SendResponse obj = new SendResponse();
ObjectOutputStream objOut = new ObjectOutputStream();
t.sendResponseHeaders(200, objOut);
objOut.writeObject(obj);
objOut.close();
but eclipse shows me an error which tells me that the ObjectOutputStream() constructor is not visible and that httpExchange is not applicable for the arguments (int,ObjectInputStream)
Do you have any idea how i can fix this ?
Thank you in advance for your help !

You have accesible the constructor with one OutputStream as parameter
ObjectOutputStream objOut = new ObjectOutputStream( the http or any other output stream here );
The constructor of ObjectOutputStream sends some header bytes and the constructor of ObjectInputStream expects these header bytes. You should either create a new ObjectOutputStream and a new ObjectInputStream for every object, or create only one ObjectOutputStream and ObjectInputStream for all the objects.
A more simple alternative could be google gson It´s easy to use and it converts a java class to json string and the inverse way too.

After some hours of trying different things
you have just to replace the
t.sendResponseHeaders(200, objOut);
with
t.sendResponseHeaders(200,0);
as mentioned by user cyon on this question

Related

How to implement the back-end interface to input message through the front-end in the socket?

I want to implement a full-duplex communication through java socket and can enter information through the front-end page.
After the two parties establish a connection through the socket, the front-end can call the url interface to enter the message to be sent, but now that I have implemented the socket_send method on the back-end through threads, I can only enter message in the console. If I want to implement the interface, the socket_send method requires the ObjectOutputStream type to call the writeObject method, but in the interface, I cannot get the ObjectOutputStream.
I want to know how can I enter the message I want to send in the socket_send thread through the front-end page?
class Server_send implements Runnable{
private final Socket socket;
Server_send(Socket socket){
this.socket=socket;
}
#Override
public void run() {
try {
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
while(true){
System.out.print("Please input the msg to be sent:");
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
JSONObject obj = new JSONObject();
obj.put("type","chat");
obj.put("msg",str);
oos.writeObject(obj);
oos.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
ObjectOutputStream will try to use the default Java serialization mechanism, which you don't want anywhere except Java itself. The best library for JSON serialization is Jackson if you need one.
Try to use this template:
. . .
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
// Jackson's ObjectMapper is here
bos.write(new ObjectMapper().writeValueAsBytes(msgObject));
// also you can send plain strings
bos.write("hello".getBytes());
. . .

Sending and reading string to/from PrintWriter and BufferedReader

I have a server client that sends and receives info from the server socket using a PrintWriter for outgoing messages and a BufferedReader for incoming messages. I'm trying to test the client without a server connection in JUnit by sending strings to the client through the BufferedReader and reading the returned output from the PrintWriter.
class Client{
private BufferedReader incomingMessage;
private PrintWriter outgoingMessage;
private StringWriter output;
//Constructor for testing without server connection
public Client(){
output = new StringWriter();
outgoingMessage = new PrintWriter(output);
incomingMessage = new BufferedReader(new InputStreamReader(System.in));
}
//Methods for processing incoming messages and sending responses are
//omitted
//responses are sent using outgoingMessage.println("msg");
public void sendStringToInputStream(String msg){
incomingMessage = new BufferedReader(new StringReader(msg));
}
public String getOutputAsString(){
return output.toString();
}
}
This is the test I'm running.
public class ServerMessageTest {
private Client testClient;
private String output;
#Before
public void setUp(){
testClient = new Client();
}
#Test
public void testClientOutputMessage(){
testClient.sendStringToInputStream("GAME A OVER SEND OUTCOME");
output = testClient.getOutputAsString();
String testString = "GAME A OVER PLAYER 1 0 PLAYER 2 0";
Assert.assertEquals(testString, output.toString());
}
}
The test fails showing this:
org.junit.ComparisonFailure:
Expected :GAME A OVER PLAYER 1 0 PLAYER 2 0
Actual :
So there's an issue with reading the output message or setting the input message. I'm kinda new to IO stuff, so if someone could point out what I'm doing wrong I would greatly appreciate it!
Your variable names are bizarre. A BufferedReader isn't a message, and neither is a PrintWriter.
You aren't doing any output or input in this code. You need to call println() to send the message, and readLine() to receive it. Converting the reader and writer to strings accomplishes exactly nothing.
You need to create your reader and writer once per socket, not once per message.

Sending LinkedList of Objects through ObjectInputStream throws exceptions 'NotSerializableException' and 'StreamCorruptedException' [duplicate]

This question already has an answer here:
StreamCorruptedException: invalid type code: AC
(1 answer)
Closed 7 years ago.
I'am writing a simple copy of 'Space Invaders'. I want to add network feature, and atm I have problem with Writing/Reading data.
So I have a LinkedList of (objects)Aliens and I want to send this to Client, to update thier positions.
The problem starts there:
On Server side I got exception:
'java.io.NotSerializableException: sun.awt.image.ToolkitImage'
(Class Alien implements Serializable)
On Client Side:
'StreamCorruptedException: invalid type code: AC'
Code where sending data to client:
else if(Server)
{
while(true)
{
ServerSocket server = new ServerSocket(1500);
serverSocket = server.accept();
new NetworkThreadHelp(serverSocket, board.GetAlienList()).start();
}
}
Code of NetworkThreadHelp:
public class NetworkThreadHelp extends Thread
{
private Socket socket = null;
private LinkedList<Alien> Aliens = new LinkedList<Alien>();
public NetworkThreadHelp(Socket socket, LinkedList<Alien> A)
{
super("NetworkThreadHelp");
this.socket = socket;
this.Aliens = A;
}
public void run()
{
try
{
ObjectOutputStream objectOutput = new ObjectOutputStream(socket.getOutputStream());
objectOutput.writeObject(Aliens);
objectOutput.flush();
objectOutput.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Code where data is read:
else if(Client)
{
Socket socket = new Socket("127.0.0.1",1500);
ObjectInputStream objectInput;
while (true)
{
objectInput= new ObjectInputStream(socket.getInputStream());
Object object = objectInput.readObject();//Here code doesn't initialize, everything below this won't execute
LinkedList<Alien> Aliens = (LinkedList<Alien>) object;
board.UpdateAliens(Aliens);
}
}
My question is: how to make this work, write and read properly?
Most likely your Alien class contains an instance reference to an instance of the nonserializable ToolkitImage class. You may need to refactor your code so the Alien class doesn't contain such an instance reference, for exaample by making that reference a static constant. Alternatively, you can write custom writeObject(), readObject(), and readObjectNoData() methods for the Alien class as specified in the Javadoc for Serializable.
Your client side problem may or may not be a different problem, but I'd suggest fixing the server side problem first. If you still have a client side problem, you can always post another question.

Restlet client-server streaming using interfaces

I'd like to do something similar to the example posted in restlet's site (first applicaiton) - with one difference:
I want to stream data - not use primitive types - using an interface.
I want to define some kind of an interface between the client and the server, stream data between them and let restlet handle transmit the data seamlessly.
Example of what I have in mind:
interface Streaming {
InputStream startStream(String streamId);
}
When the client invokes a call, it starts reading from the inputstream. The server receives the call and starts providing the stream by creating an inputstream (for example, a video file, or just some raw data). Restlet should be reading from the inputstream on the server side and provide the data as an inputstream on the client side.
Any idea how can I achieve this? A code sample or link to one would be great. Thanks.
Below's an example code of what I learned so far - an interface with streaming capavilities and a client-server streaming example.
I haven't yet added parameters to the interface and it's only download - no upload yet.
Interface:
public interface DownloadResource {
public ReadableRepresentation download();
}
Interface with protocol: (separation between logic and technology):
public interface DownloadResourceProtocol extends DownloadResource {
#Get
#Override
public ReadableRepresentation download();
}
Client:
ClientResource cr = new ClientResource("http://10.0.2.2:8888/download/");
cr.setRequestEntityBuffering(true);
DownloadResource downloadResource = cr.wrap(DownloadResourceProtocol.class);
// Remote invocation - seamless:
Representation representation = downloadResource.download();
// Using data:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
IOUtils.copy(representation.getStream(), byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
Log.i("Byte array: " + Arrays.toString(byteArray));
Server:
public class DownloadResourceImpl extends ServerResource implements DownloadResourceProtocol {
#Override
public ReadableRepresentation download() {
InputStreamChannel inputStreamChannel;
try {
inputStreamChannel = new InputStreamChannel(new ByteArrayInputStream(new byte[]{1,2,3,4,5,6,7,8,9,10}));
return new ReadableRepresentation(inputStreamChannel, MediaType.ALL);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
Configuration:
public class SampleApplication extends Application {
#Override
public Restlet createInboundRoot() {
Router router = new Router(getContext());
router.attach("/download/", DownloadResourceImpl.class);
return router;
}
}
Not sure this addresses your problem completely, but one approach is to create a thread that streams data back to the client using ReadableRepresentation and a Pipe.
Create a pipe:
Pipe pipe = Pipe.open();
Create a representation like this:
ReadableRepresentation r = new ReadableRepresentation(pipe.source(), mediatype);
Start a separate thread that writes batches of bytes to the pipe like this:
pipe.sink().write(ByteBuffer.wrap(someBytes));
return the representation to the client.

Unmarshalling a Socket's InputStream closes the Socket?

I have a server-client architecture where the client sends an XML to the server who reads it and generates a PDF out of it and sends that back to the client.
On the client side:
JAXBElement<Xml> xml = ...
Socket sock = ...
Marshaller marshaller = ...
marshaller.marshal(xml, sock.getOutputStream());
sock.shutdownOuput();
Meanwhile on the server side:
ServerSocket server = ...
Socket client = server.accept();
Unmarshaller unmarshaller = ...
// client.isClosed() -> false
JAXBElement<Xml> xml =
(JAXBElement<Xml>)) unmarshaller.unmarshall(client.getInputStream());
// client.isClosed() -> true
Pdf pdf = new Pdf(xml);
client.getOutputStream().write(pdf.toBytes());
// "socket is closed" IOException is thrown
If I don't unmarshall the client's InputStream (on the server side) and just send back a dummy PDF then everything's goes smoothly. So, I have to assume that the Unmarshaller closes the InputStream it is given, thus implicitly closing the client Socket ruining my day...
Any idea on solving this?
The class XMLEntityManager calls close on the InputStream.
You can use a FilterInputStream to avoid a close() call of the underlying stream.
Subclass FilterInputStream and override the close() method with an empty body:
public class MyInputStream extends FilterInputStream {
public MyInputStream(InputStream in) {
super(in);
}
#Override
public void close() {
// do nothing
}
}
Then change your unmarshall() call to
JAXBElement<Xml> xml =
(JAXBElement<Xml>)) unmarshaller.unmarshall(new MyInputStream(client.getInputStream()));
So the JAXB framework still calls close() on the stream, but it's now filtered out by your own stream instance and the socket stream remains open.
If you don't want to explicitly override an InputStream in your code like vanje suggest, Apache commons-io provide a implementation that acheive this:
take a look at :
CloseShieldInputStream

Categories

Resources