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

Why message body is of type string? #27

Open
strider2038 opened this issue Mar 12, 2019 · 12 comments
Open

Why message body is of type string? #27

strider2038 opened this issue Mar 12, 2019 · 12 comments

Comments

@strider2038
Copy link

Why message body is of type string https://github.com/queue-interop/queue-interop/blob/master/src/Message.php#L19? How can I send objects inside of message body? I need to double encode it? It is weird.

Java specification definitily says that body can be an object, a stream and so on https://docs.oracle.com/javaee/7/api/javax/jms/Message.html

@makasim
Copy link
Member

makasim commented Mar 12, 2019

You should serialize it, for example into json or xml. There is no way you can send a php object as is.

@strider2038
Copy link
Author

But it will be serialized twicely to send it via transport (redis, kafka, rabbitmq) - first time message body to string and second time message with serialized body into string. I think this is unnecessary overhead.

@Sevavietl
Copy link

I also don't see why to restrict body to string only.

There is no way you can send a php object as is.

I guess this is not true. The body can be JsonSerializable or an array and as the whole message will be encoded the body will be encoded too.

Using string for body results in double encoding and leads to much pain:)

There is no problem with ommiting return typehint of Message::getBody() in the interface and type-narrow it in the realisation.

@makasim
Copy link
Member

makasim commented Apr 12, 2019

Why double?

Your code encodes a data to JSON so it becomes a string, then send it as the message body. In turn, on a consumer side, you get a string which your cod decode to your data structure.

The idea behind this decision is to keep encoding\decoding logic out of the scope of the Queue Interop.

@Sevavietl
Copy link

@makasim thank you for the prompt answer.

Why double?

Because when you call json_encode on $body you get a JSON string. Then when you call json_encode on the whole message with the body as a string, the body gets double encode: you end up with escaped quotes:

$body = [
    'foo' => 'bar',
];

$message = [
    'body' => json_encode($body),    
];

var_dump(json_encode($message)); // => string(28) "{"body":"{\"foo\":\"bar\"}"}"

Ommiting string typehint does not couple encoding\decoding logic. As far as I can see the Queue Interop contains only interfaces and they contain no encoding\decoding logic with or without string. Please, correct me if I am wrong.

@makasim
Copy link
Member

makasim commented Apr 12, 2019

Ommiting string typehint does not couple encoding\decoding logic.

Most of the transports accept only a string. What should those transport do if something else given?

It would force us to introduce a kind of encoding\decoding interfaces so they can transform that data to a string. The other way is to throw an exception which is not interoperable (some transports would work but others dont)

@Sevavietl
Copy link

It is hard to tell without wide domain knowledge. Can you, please, give me an example of transport where you can use only string for the body? Thank you in advance.

@Sevavietl
Copy link

@makasim I have looked through the enqueue source code. And frankly speaking, I do not see any caveats of not using string body. Every transport implementation already accepts only message of specific type, so LSP doesn't hold there.

I can create fork for this repo and fork for enqueue, that will use it. Just as proof of concept. Will you consider to review them and continue discussion?

Thank you in advance.

@makasim
Copy link
Member

makasim commented Apr 15, 2019

I've given it another thought and now I tend to agree with you. The issue is clearly present.

Sure I'll review it!

Thank you all for your effort.

@Steveb-p
Copy link

@makasim can you look at #30 and, if there are no issues with it, merge it so we can work on it enqueue-dev?

@dexy86
Copy link

dexy86 commented Oct 27, 2020

Hello guys
I also have the same question, why is body type string?
if i have a DTO object and i don't wan't it double encoded, how should i deal with that ?
the message that is the array which contains body, properties and headers (which i don't see the purpose of using in google pub/sub) is json_encoded before sending, so if i have a body value which is an object or an array i have to encode it or serialize it which is not optimal

e.g.

//don't look at the naming this is just to test
$dto = new StdClass();
$dto->id = 10;
$dto->computeId = 44;
$s = new StdClass();
$s->storeId = 4;
$s->stock = 11;
$dto->obj = $s;
// var_dump($dto);

$msg = ['body' => null, 'properties' => null, 'headers' => null];

$bodyMsg = json_encode($dto); //because body needs to be a string :/
$bodyMsgSerialized = serialize($dto); //serialized version

$msg['body'] = $bodyMsg;
echo "json encode bodyMsg: \n";
print_r(json_encode($msg));

$msg['body'] = $bodyMsgSerialized;
echo "\n\nphp serialize bodyMsgSerialized: \n";
print_r(json_encode($msg));

//but if body was a array/Obj = the suggested way
$msg['body'] = $dto;
echo "\n\narray/Obj example: \n";
print_r(json_encode($msg));

http://sandbox.onlinephpfunctions.com/code/61f3dd92697b40db568bbbd818959e9e493d57ae

suggestion would be to remove queue-interop as a dependency for php-enquque or fix it to use some config for message format/standard, so everyone could adjust for them how they need, cause unfortunately i can't see queue-interop to satisfy everyones needs :( (great idea though)

@dexy86
Copy link

dexy86 commented Nov 9, 2020

Hello guys
I also have the same question, why is body type string?
if i have a DTO object and i don't wan't it double encoded, how should i deal with that ?
the message that is the array which contains body, properties and headers (which i don't see the purpose of using in google pub/sub) is json_encoded before sending, so if i have a body value which is an object or an array i have to encode it or serialize it which is not optimal

e.g.

//don't look at the naming this is just to test
$dto = new StdClass();
$dto->id = 10;
$dto->computeId = 44;
$s = new StdClass();
$s->storeId = 4;
$s->stock = 11;
$dto->obj = $s;
// var_dump($dto);

$msg = ['body' => null, 'properties' => null, 'headers' => null];

$bodyMsg = json_encode($dto); //because body needs to be a string :/
$bodyMsgSerialized = serialize($dto); //serialized version

$msg['body'] = $bodyMsg;
echo "json encode bodyMsg: \n";
print_r(json_encode($msg));

$msg['body'] = $bodyMsgSerialized;
echo "\n\nphp serialize bodyMsgSerialized: \n";
print_r(json_encode($msg));

//but if body was a array/Obj = the suggested way
$msg['body'] = $dto;
echo "\n\narray/Obj example: \n";
print_r(json_encode($msg));

http://sandbox.onlinephpfunctions.com/code/61f3dd92697b40db568bbbd818959e9e493d57ae

suggestion would be to remove queue-interop as a dependency for php-enquque or fix it to use some config for message format/standard, so everyone could adjust for them how they need, cause unfortunately i can't see queue-interop to satisfy everyones needs :( (great idea though)

waoooooo 14days and still no response :D

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

Successfully merging a pull request may close this issue.

5 participants