Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Binary event #6

Closed
2 tasks done
flowersinthesand opened this issue Mar 3, 2016 · 2 comments
Closed
2 tasks done

Binary event #6

flowersinthesand opened this issue Mar 3, 2016 · 2 comments
Assignees
Milestone

Comments

@flowersinthesand
Copy link
Member

Derived from cettia/cettia-protocol#9

With this feature, you will be able to exchange events whose data is binary without binary-to-text conversion.

  • Find MessagePack Java implementation
  • Implement the default behavior of send method
@flowersinthesand flowersinthesand added this to the 1.0.0-Alpha3 milestone Mar 3, 2016
@flowersinthesand
Copy link
Member Author

As for MessagePack Java Implementation, msgpack-java looks the best. It also provides Jackson extension, msgpack-jackson.

Map<String, Object> obj = new LinkedHashMap<>();
obj.put("text", "Donghwan Kim");
obj.put("binary", "Donghwan Kim".getBytes());

ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
byte[] bytes = objectMapper.writeValueAsBytes(obj);
System.out.println(Arrays.toString(bytes));
System.out.println(objectMapper.readValue(bytes, Map.class));
[-126, -92, 116, 101, 120, 116, -84, 68, 111, 110, 103, 104, 119, 97, 110, 32, 75, 105, 109, -90, 98, 105, 110, 97, 114, 121, -60, 12, 68, 111, 110, 103, 104, 119, 97, 110, 32, 75, 105, 109]
{text=Donghwan Kim, binary=[B@38fc30b8}

@flowersinthesand
Copy link
Member Author

The second task is about how a given object should be serialized into either text message (JSON) or binary message (MessagePack).

First ObjectMapper's convertValue doesn't touch byte arrays and ByteBuffer instances.

public static class TestBean {
  // Getters and setters are skipped
  public String string = "100";
  public int number = 100;
  public Map<String, Object> object = new LinkedHashMap();
  public byte[] byteArray = new byte[]{-126, -92, 116, 101, 120, 116, -84, 68, 111, 110, 103, 104,
    119, 97, 110, 32, 75, 105, 109, -90, 98, 105, 110, 97, 114, 121, -60, 12, 68, 111, 110,
    103, 104, 119, 97, 110, 32, 75, 105, 109};
  public ByteBuffer byteBuffer = ByteBuffer.wrap("small".getBytes());

  {
    {
      object.put("integer", 300);
      object.put("bytes", ByteBuffer.wrap("big".getBytes()));
    }
  }
}

ObjectMapper mapper = new ObjectMapper();
Map map = mapper.convertValue(new TestBean(), Map.class);
System.out.println(map);
{string=100, number=100, object={integer=300, bytes=[B@2a37783b}, byteArray=[B@1fb67f24, byteBuffer=[B@65524c0}

Second to determine if a given object contains binary (if so, it should be encoded to binary), it's required to traverse the given object. Using SimpleModule's addSerializer, ByteArraySerializer and ByteBufferSerializer, we don't need to visit every property of the given object manually considering stuff like circular structure.

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
// Of course thread safety is not required here
final AtomicBoolean containsBinary = new AtomicBoolean();
module.addSerializer(byte[].class, new ByteArraySerializer() {
  @Override
  public void serialize(byte[] bytes, JsonGenerator gen, SerializerProvider provider) throws
    IOException {
    containsBinary.set(true);
    super.serialize(bytes, gen, provider);
  }
});
module.addSerializer(ByteBuffer.class, new ByteBufferSerializer() {
  @Override
  public void serialize(ByteBuffer bytes, JsonGenerator gen, SerializerProvider provider)
    throws IOException {
    containsBinary.set(true);
    super.serialize(bytes, gen, provider);
  }
});
mapper.registerModule(module);

Map map = mapper.convertValue(new TestBean(), Map.class);
System.out.println(map);
System.out.println(containsBinary);
{string=100, number=100, object={integer=300, bytes=[B@65524c0}, byteArray=[B@3fdfbc7f, byteBuffer=[B@79d0569b}
true

If it turns out that it has binary, new ObjectMapper(new MessagePackFactory()) and writeValueAsBytes should be used to encode it to MessagePack and if not new ObjectMapper() and writeValueAsString should be used to encode it to JSON.

flowersinthesand added a commit that referenced this issue Apr 10, 2016
…n format

msgpack-lite that is one of dependencies of cettia-javascript-client encodes typed arrays to ext format. But in Java they should be decoded as bin format.

Refs #6
@flowersinthesand flowersinthesand self-assigned this Feb 11, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant