I am sending messages to ASB using WCF NetMessaging.
The message can contain any number of custom data contracts.
I have a Service Fabric stateless service with a custom listener for ASB delivering messages pushed onto the queue. All examples I’ve seen are able to only handle a single type of message (seems most guidance is to serializable to JSON but that’s not what I need to do here). I want the subscriber to the queue be able to handle a number of messages (any message sent to any action of the service).
I am able to add the Action to the BrokeredMessage.Properties so I know where to send it. The problem is I haven’t figured out how deserialize the message body in any way that works.
I can read it from a stream and get it to a string, but can’t do this:
var myDTO = message.GetBody();
That throws serialization exceptions. I’ve also tried a variant of that passing in a DataContractSerializer - even though I think that is the default.
Furthermore, what I really need is a way to do this without knowing the type of data in the body - I could, conceivably, add more message.Properties for the types serialized in the body but I figure there has to be a direct way to do it using only the data in the body - after all WCF and similar techs do this with ease. But how?
Thanks for any help,
Will
To have a stand-alone message body:
Create an envelope type that describes the content (Type name, sender, timestamp, etc.), and holds a payload (string) property to contain the serialized object.
To send out messages, you serialize (compress, encrypt) the object, assign the result to the payload property of an Envelope instance. Serialize the Envelope and send that out.
To receive messages, deserialize the message body into an Envelope, examine the type information, and deserialzie the payload.
This is more or less how SOAP based WCF services do/did it.
Make sure your DTO is datacontract-serializable, by creating some unit tests.
Keep in mind that the message body size is limited in ASB, XML may not be your best choice of serialization.
You may also be hitting this issue.
Related
From my client application I make a POST call to a \validate end-point. This call is made to execute the controller on the server side and not to create any resource. In response, server can provide one of the two totally unrelated JSON objects. From the client, how do I know which of the two types I should use during deserialization? What is the clean way to do this?
There are multiple ways to do it.
Add some header to the http response to determine body type. Client should check header and use corresponding deserializer. This is a typical approach for webhooks API where you have single endpoint to process different event type. As an example, you could check AWS SNS API that uses x-amz-sns-message-type header to define response type.
As an alternative you could use special body format with some type field and payload that depends on this type.
{
"type: "Type",
"paylod": {
...
}
}
But from my opinion this approach is much harder to handle for the client and would required 2-step deserialization process.
I want to retrieve data about a bunch of resources. Let's say an Array of book id and the response is JSON Array of book objects. I want to send the request payload as JSON to the server.
Should I use GET and POST method?
Note:
I don't want to make multiple GET request for each book ID.
POST seems to be confusing as it is supposed to be used only when the request creates a resource or modifies the server state.
I want to retrieve data about a bunch of resources. Let's say an Array of book id and the response is JSON Array of book objects.
If you are thinking about passing the array of book id as the message body of the HTTP Request, then GET is a bad idea.
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
You should use POST instead
POST seems to be confusing as it is supposed to be used only when the request creates a resource or modifies the server state.
That's not quite right. POST can be used for anything -- see GraphQL or SOAP. But what you give up by using POST is the ability of intermediate components to participate in the conversation.
For example, for cases that are effectively read-only, you would like to use a safe method, because that allows pre-caching optimization, and automated retry of lost responses on an unreliable network. POST doesn't have extra semantic constraints, so you lose out.
What HTTP really wants is that you GET using the URI; this can be done in one of two relatively straightforward ways:
POST the ids to the server, to create a new resource (meaning that the server retains for itself a copy of the list of ids), and receive a new resource identifier back in exchange. Then GET using this new identifier any time you want to know the current representation of the results.
Encode the information you need into the URI itself. Most commonly, this is done using the query part of the URI, although that isn't strictly necessary. The downside here is that if the URI encoded representation of the array of ids is very long, you may have trouble with some implementations that enforce arbitrary URI limits.
There aren't always great answers:
The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.
If I understand correctly, you want to get a list of all of the items in a list, in one pull. This would be possible using GET, as REST returns the JSON it can by default be up to 100 items, and you can get more items if needed by specifying $top.
As far as writing back or to the server, POST would be what your looking for, this to my understanding would need to be one for one.
you are going to use a GET-Request and put your request-data (book-id array) in the data-section of your ajax (or whatever you're going to use) request. See How to pass parameters in GET requests with jQuery
According to the testing section of the docs, I can verify that a particular payload has been sent to a stream. If that's a POJO message that gets converted into JSON in the end though, I can't seem to find native support for asserting that JSON. Instead, I can only access the payload in the form of that POJO and do all sorts of assertions on it.
Currently, I just have a separate set of tests to ensure that a particular POJO type gets serialized into JSON in a way that I expect. But maybe there's a built-in support for testing the whole thing from calling a method to verifying the final JSON that ends up in Kafka.
I know this is a bit hacky but current circumstances can't allow me to rewrite certain aspects of the application.
rpcService.someServiceCall(String someParameter,
new AsyncCallback<LargeClientObject>(){
Basically, we have a very large response from the server to client called LargeClientObject. The deserialization on the client side is taking a very long time to unmarshal. I was wondering what the best way would be to send deserialized data (raw JSON) to the client so that the client doesn't have to waste time deserializing it.
I was wondering if there was a way to simply do:
rpcService.someServiceCall(String someParameter,new ASyncCallback_WithNoClientSerialization<LargeClientObject>(){
FYI,I've tried using RequestFactory to load ClientObjects but it has many custom objects which would take forever to write RequestProxies for and I'd have to refactor most of the existing application.
I think you may consider two approaches.
A. Call a servlet to get a,JSON response without using RPC.
B. Use the existing RPC service but change the return type to String instead of LargeClientObject, and pass a JSON string.
You probably have to test which approach works better.
I'm using Web Api and have a scenario where clients are sending a heartbeat notification every n seconds. There is a heartbeat object which is sent in a POST rather than a PUT, because as I see it they are creating a new heartbeat rather than updating an existing heartbeat.
Additionally, the clients have a requirement that calls for them to retrieve all of the other currently online clients and the number of unread messages that individual client has. It seems to me that I have two options:
Perform the POST followed by a GET, which to me seems cleaner from a pure REST standpoint. I am doing a creation and a retrieval and I think the SOLID principles would prefer to split them accordingly. However, this approach means two round trips.
Have the POST return an object which contains the same information that the GET would otherwise have done. This consolidates everything into a single request, but I'm concerned that this approach would be considered ill-advised. It's not a pure POST.
Option #2 stubbed out looks like this:
public HeartbeatEcho Post(Heartbeat heartbeat)
{
}
HeartbeatEcho is a class which contains properties for the other online clients and the number of unread messages.
Web Api certainly supports option #2, but just because I can do something doesn't mean I should. Is option #2 an abomination, premature optimization, or pragmatism?
The option 2 is not an abomination at all. A POST request creates a new resource, but it's quite common that the resource itself is returned to the caller. For example, if your resources are items in a database (e.g., a Person), the POST request would send the required members for the INSERT operation (e.g., name, age, address), and the response would contain a Person object which in addition to the parameters passed as input it would also have an identifier (the DB primary key) which can be used to uniquely identify the object.
Notice that it's also perfectly valid for the POST request only return the id of the newly created resource, but that's a choice you have, depending on the requirements of the client.
public HttpResponseMessage Post(Person p)
{
var id = InsertPersonInDBAndReturnId(p);
p.Id = id;
var result = this.Request.CreateResponse(HttpStatusCode.Created, p);
result.Headers.Location = new Uri("the location for the newly created resource");
return result;
}
Whichever way solves your business problem will work. You're correct POST for new record vs PUT for update to existing record.
SUGGESTION:
One thing you may want to consider is adding Redis to your stack and the apps can post very fast, then you could use the Pub/Sub functionality for the echo part or Blpop (blocking until record matches criteria). It's super fast and may help you scale and perfectly designed for what you are trying to do.
See: http://redis.io/topics/pubsub/
See: http://redis.io/commands/blpop
I've used both Redis for similar, but also RabbitMQ and with RabbitMQ we added socket.io connection to "stream" the heartbeat in real time without need for long polling.