How to get generic message as json from MassTransit Fault event - masstransit

I have a microservices based application and wish to create a service that captures all Fault events with their message payloads (as json) and stores them in a database for later analysis and potential resubmission. I have created a Fault consumer and can capture the Fault but am unable to generically extract the message payload as json.
public Task Consume(ConsumeContext<Fault> context)
{
if (context is PipeContext pipeContext)
{
var result = pipeContext.TryGetPayload(out ConsumeContext<Fault> payload2);
var serCont = context.SerializerContext;
}
Console.WriteLine($"A message faulted:{context.Message.FaultedMessageId} " +
$"{context.Message.Exceptions} " +
$"{context.ConversationId}"
);
return Task.CompletedTask;
}
I can see the full details I want in the context.SerializerContext._message but this is unaccessable.
context.SerializerContext._message
I saw you comment for a similar question:
If you did want to later get the actual fault message, you could use
consumeContext.TryGetMessage<Fault>(out var faultContext) and if it
was present you'd get it back.
I don't have "T" from every service and therefore want to handle all Faults a JSON.
Is there a way I can capture the full Fault with the message, ideally as json, without having access to every T across my system?
I am on MassTransit 8.
Thanks

If you have the message type (T), you can use TryGetMessage<Fault<T>> and it will return the message type deserialized.
If you don't, or if you want to deal with the JSON in a message directly, using V8 you can get the actual JsonElement from the deserializer and navigate the JSON yourself:
var jsonElement = context.TryGetMessage<JsonElement>()
Previous answer, but for Newtonsoft: https://stackoverflow.com/a/46779547/1882

Related

customization in protobuf java generated code

We have a use case where, we have many RPC defined in different-different .proto files , and we generate a java based grpc stub code by using google's protobuf-java & protoc-gen-grpc-java as gradle plugin.
The requirement is we want to generate a new Service which flips the request, response and add stream to new flipped rpc.
So for example :
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
to be converted to like
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloStreaming (stream HelloReply) returns (stream HelloRequest) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
In java generated code I should be having 2 services for each original service. We just want the final java generated code to be having 2 services, the parser may/may not update original .proto files.
Is this customization possible with current protoc ? Can we extend the plugin and write ours -> Can someone please give some pointers.
Your question is unclear to me.
Revising proto files is a fundamental requirement of gRPC.
The Java tutorial on https://grpc.io includes an example of adding a method to a service. In part, this is because adding|removing|updating methods|messages|fields is a common behavior.
NOTE To clarify nomenclature, in your example, you're proposing adding a method to an existing service (definition). If you consider the proto as defining an API, this represents a non-breaking change. See Versioning gRPC services for a good overview. Existing clients will continue to work (they are only aware of SayHello) while new clients will be aware of SayHelloStreaming too.

Get message content from mime message?

I have a java spring integration project that is receving emails through the below code:
ClassPathXmlApplicationContext ac =
new ClassPathXmlApplicationContext(
"/integration/gmail-imap-idle-config.xml");
DirectChannel inputChannel = ac.getBean("receiveChannel", DirectChannel.class);
inputChannel.subscribe(message -> {
org.springframework.messaging.Message<MimeMailMessage> received =
(org.springframework.messaging.Message<MimeMailMessage>) message;
log.info("content" + message);
List<String> sentences = null;
try {
} catch (Exception e) {
}
I get the email, and I can get the subject, but I can never actually extract the message body. How do I do this?
Thank you!
You have to use this option on the channel adapter:
simple-content="true"
See its description:
When 'true', messages produced by the source will be rendered by 'MimeMessage.getContent()'
which is usually just the body for a simple text email. When false (default) the content
is rendered by the 'getContent()' method on the actual message returned by the underlying
javamail implementation.
For example, an IMAP message is rendered with some message headers.
This attribute is provided so that users can enable the previous behavior, which just
rendered the body.
But still it is doubtful, since I see in case of GMail message it is never simple. The content is a MimeMultipart and we need to read its parts to get access to the real body.
So, this is how you should change your code as well:
log.info("content" + ((MimeMultipart) ((MimeMessage) message.getPayload()).getContent()).getBodyPart(0).getContent());

How to handle empty JSONObject in Processing?

Hi I am using loadJSONObject function in Processing IDE to receive a JSON Object from a URL.
Following is my code:
JSONObject jsonUserLocations = loadJSONObject("http://smrt.utd.sg/eLocation/getLocs.php?userId="+usrID+"&sTime="+strtTime+"&eTime="+endTym);
This code works when the php returns some data (for some users).
The problem occurs when it doesn't return any data. (php doesn't return any data when there is no data, browser shows a blank page. this means user has no location data)
At this instance, the Processing IDE gives me an error saying;
a jsonobject text must begin with {
My question is how can I handle empty JSON Object in this type of situation? I need to skip if this is empty and request data for next user. Your help is much appreciated.
Thanks,
Hasala
Edit:
This is sample json object I receive when there is data.
{"locations":[{"latitude":"1.3809274","longitude":"103.7654596","startTime":"1421918587868","duration":"0","accuracy":"30"},{"latitude":"1.3805307","longitude":"103.7661015","startTime":"1421941711737","duration":"0","accuracy":"45"},{"latitude":"1.3805304","longitude":"103.7660959","startTime":"1421942011727","duration":"0","accuracy":"45"},{"latitude":"1.3799822","longitude":"103.7658037","startTime":"1421942311835","duration":"0","accuracy":"82.5"}],"success":1}
You have two options:
You could read the String form the URL first, and if it's blank, don't bother with the parsing.
Or you could just catch the exception that Processing throws:
try{
JSONObject jsonUserLocations = loadJSONObject("http://smrt.utd.sg/eLocation/getLocs.php?userId="+usrID+"&sTime="+strtTime+"&eTime="+endTym);
}
catch(JSONException e){
e.printStackTrace();
//json was blank, do something else
}

how to get jsonobject form volley onResponse library

I'm an android beginner and I want to make a login using volley library, but i don't
know how i can obtain the JSONObject response from my server and use it to check
login parameters and launch a specific activity if the user exist.
//assuming you are implementing this part from an activity.
//otherwise, replace “this” with relevant context
RequestQueue myQueue = queue = Volley.newRequestQueue(this);
//your server address
String url = "http://my-json-feed";
//Create your JSON object request
JsonObjectRequest jsObjRequest = new JsonObjectRequest
(Request.Method.GET, url, null, new Response.Listener() {
#Override
public void onResponse(JSONObject response) {
//process the server response here.
//use the “response” object for checking the login parameters, etc.
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//Handle errors such as network failures,etc here
}
});
//add the request object to the Volley queue
myQueue.add(jsObjRequest);
The "onResponse()" is the callback function which will give you the json object returned by the server. Inside that function, use that response to do whatever you want (for your case, to check login parameters, etc.)
For details, look here: Request JSON
Another note:
If you are to use the VolleyQueue only in one or two activities, it's okay to create separate volley queues for those couple of activities. But, if you have lots of activities and all of them needs to use Volley, then it would be a very bad choice to create volley queues for each activity. It can cause you OutOfMemory exception in the worst case. You can consider creating a singleton VolleyQueue which will be used by the whole application (Creating an ApplicationController class and including the Volley singleton queue in it can be one way to do that).

What is the correct way to call patch from an OData client in Web Api 2

Following the OData samples created by the web api team, my controller has the following for supporting Patch:
public HttpResponseMessage Patch([FromODataUri] int key, Delta<Foo> item)
{
var dbVersion = myDb.GetById(key);
if(dbVersion == null)
throw Request.EntityNotFound();
item.Patch(dbVersion);
myDb.Update(dbVersion);
return Request.CreateResponse(HttpStatusCode.NoContent);
}
and using the auto-generated client (derived from DataServiceContext), I submit a patch request like this:
var foo = svcContainer.Foos.Where (f => f.Id == 1).SingleOrDefault();
foo.Description = "Updated Description";
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges(SaveChangesOptions.PatchOnUpdate);
However, tracing the call in fiddler, I see that all other properties of Foo are serialized and sent to the service. Is that the correct behavior? I expected only the Id and Description to be sent over the wire. Also, if I debug the service method and call
GetChangedPropertyNames on item, all its property names are returned.
Should I be creating some sort of Delta instance on the client?
I understand the disconnected nature of the service and thus the service side does not have a context for tracking changes, but it seems to me the api team added support for patch for a reason, so I'd like to know if the client ought to be invoking the update in a different manner.
Update
The link YiDing provided explains how to create a true PATCH request from the client (using the Microsoft.OData.Client.DataServiceContext created by the Microsoft.OData.Client 6.2.0 and above.
For convenience, here is the code snippet:
var svcContainer = new Default.Container(<svcUri>);
var changeTracker = new DataServiceCollection<Foo>(svcContainer.Foos.Where(f => f.Id == 1));
changeTracker[0].Description = "Patched Description";
svcContainer.SaveChanges();
The DataServiceCollection implements property tracking, and using this pattern, only the updated properties are sent to the service.
Without using DataServiceCollection and simply using
svcContainer.UpdateObject(foo);
svcContainer.SaveChanges();
all properties are still sent over the wire despite documentation to the contrary, at least as of Microsoft.OData.Client 6.7.0
The client side property tracking is now supported from Microsoft.OData.Client version 6.2.0. It will detect only the modified properties of an entity and send the update request as PATCH instead of PUT to meet the requirement of your scenario. Please refer to this blog post for more details:
https://devblogs.microsoft.com/odata/tutorial-sample-client-property-tracking-for-patch/

Resources