Cit5
Cit5

Reputation: 440

how do i marshal data for TCP streaming?

So for a homework assignment, I have a example of how to marshal data and unmarshal.

The structure they gave us was this: Event is an interface. Wireformat is a class that "inherits" an Event. WireFormatWidget is a class with the actual code that has the marshal and unmarshal.

I have separate threads that handle the sending data in byte array using TCP.

What I have an issue is that when I create a Wireformat object. I run into issue with a thread trying to marshal the data.

Exception in thread "main" java.lang.NullPointerException
    at myhw.WriteFormatWidget.getBytes(WriteFormatWidget.java:38)

The interface structure defines the data as a message, a type of message as an integer, a timestamp (of what I am assuming is Date and getTime of that date), and a tracker. I am not sure what the tracker is.

I am told this structure is the best method to sending data which is why I am trying to implement this code style.

The WriteFormatWidget consist of this:

private int type;
private long timestamp;
private String identifier;
private int tracker;

So for my wireformat, I created it as a class that extends WireFormatWidget and implements Event because that was the only way Eclipse did not spit an error or suggest changing WireFormatWidget or Event.

Now when I hardcode my specific wireformat, I instantiate it and it seems to not be able to call getBytes() with the hardcoded values I uses for the same variables.

public class MyWireFormat extends WireFormatWidget implements Event {
    private String identifier = "here is my custom wireformat";
    ....

When I print out the identifier in the getBytes in WireFormatWidget, I get null and not the expected identifier I hardcoded. So I must not be "inheriting" appropriately. What am I doing wrong?

EDIT: WireFormatWidget (given)

public class WriteFormatWidget {
private int type;
private long timestamp;
private String identifier;
private int tracker;

    public byte[] getBytes() throws IOException {
        byte[] marshalledBytes = null;
        ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
        DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(baOutputStream));

        dout.writeInt(type);
        dout.writeLong(timestamp);

        System.out.println("getBytes using identifier: " + identifier);

        byte[] identifierBytes = identifier.getBytes();
        int elementLength = identifierBytes.length;
        dout.writeInt(elementLength);
        dout.write(identifierBytes);

        dout.writeInt(tracker);

        dout.flush();
        marshalledBytes = baOutputStream.toByteArray();

        baOutputStream.close();
        dout.close();

        return marshalledBytes;
    }
}

I'll save space by not posting the unmarshalling portion. But its the same thing just in reverse.

The issue I am having is printing the data from the Client-side as proof of what I am sending beforehand.

So I will perform a simple test like print the type or print the identifier. It fails and I have null.

Upvotes: 2

Views: 180

Answers (2)

Jason
Jason

Reputation: 5246

You're not initializing WireFormatWidget#identifier. It's declared but never initialized. Add a constructor to WireFormatWidget and provide a String as the identifier.

Upvotes: 1

user1039663
user1039663

Reputation: 1335

You need to implement something that implements Serializable, or implement directly Serializable (I think is simpler).

You do not specify many things about your interface event, but probably will inherit from Serializable, at least if you are going to implement standard java serialization.

If Event implements Serializable so it is ok, otherwise if you use another serialization method you need to specify more about it.

Assuming that you implement Serializable you need to create a ByteBuffer and call to writeObject. To create the stream you can check for example Java Serializable Object to Byte Array, so joining all:

ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream stream = new ObjectOutputStream(bos);   
stream.writeObject(yourinstancetoserialize);
out.flush();
byte[] yourBytes = bos.toByteArray();
...

Probably you will need to implement the writeObject directly. In that case you use the ObjectOutputStream methods to serialize the properties, check them in https://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html for example.

private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
  stream.writeInt(this.type);
  stream.writeLong(this.timestamp);
  stream.writeBytes(this.identifier); or stream.writeChars(this.identifier);
  stream.writeInt(this.tracker);
  ...
}

Upvotes: 0

Related Questions