kafkatemplate is modifying message sent, need original message to be sent as it is - spring-kafka

I have implemented custom kafkalistenererrorhandler. I want to send the message to retry topic if message fails in processing. For this purpose I have added some headers to it. For doing this I am using spring-meesage.
Issue is when I am sending message using kafkatemplate it adds "\" to the string message.
Following is the code what I am doing.
public Object handleError(Message<?> message, ListenerExecutionFailedException exception) {
logger.info("Enter handleError message");
int numberOfRetries = messageRetryCount(message);
MessageBuilder<?> messageBuilder = MessageBuilder.fromMessage(message).removeHeader(KafkaHeaders.TOPIC)
.removeHeader(KafkaHeaders.PARTITION_ID).removeHeader(KafkaHeaders.MESSAGE_KEY)
.setHeader(KafkaHeaders.TOPIC, numberOfRetries > 0 ? retryTopic : dlqTopic);
template.send(messageBuilder.build());
Internally spring-kafka converts message to producerRecord. which in output adds \ to the string.
2020-03-20 12:25:28.804 INFO 10936 --- [_consumer-0-C-1] c.h.kafkaretry.consumer.SimpleConsumer : in rety :: "\"testfail\""
Does anyone faced same issue ? any alternatives or solution ?

Looks like you use JsonSerializer while your data is just a plain string. Consider to use a StringSerializer or JsonDeserializer on the consumer side.

Related

How to response with a success JSON format after completing a transaction in corda

Hi everyone i am working on a project in which i need to send a response in JSON format to the CLI that the Transaction have completed let me give you an example.Consider that i have stated a flow Start ExampleFlow pojo: {iouValue: 7}, otherParty: "O=PartyB,L=London,C=GB" and the result will be Starting
Generating transaction based on new IOU.
Verifying contract constraints.
Signing transaction with our private key.
Gathering the counter party's signature.
Collecting signatures from counterparties.
Verifying collected signatures.
Obtaining notary signature and recording transaction.
Broadcasting transaction to participants
Done
Flow completed with result: SignedTransaction(id=F95406D901209BA77396C1A4D375585C6E051414EE22BE441FC02E5AE147A050)
but what i want is that their should be a JSON format result not all of it but something like this
{response: success }
i just want some success response in JSON format
i am using IOU project
thanks
You can achieve that by establishing an RPC connection with your node; call the flow, then return the JSON object.
There are a couple of approaches that you can follow, and I recommend that you go through the samples repository https://github.com/corda/samples to explore them:
Create a webserver (SpringBoot application) that server REST API's that call your flows and return a JSON object: https://github.com/corda/samples/tree/release-V4/spring-webserver
Create a simple Java app that establishes an RPC connection with your node and serves as a client to call a certain method/flow: https://github.com/corda/samples/blob/release-V4/cordapp-example/clients/src/main/java/com/example/server/JavaClientRpc.java
If you follow the webserver sample, you can add a method to your controller that does something like:
#GetMapping(value = "/my-api", produces = MediaType.APPLICATION_JSON_VALUE)
private ResponseEntity<YourObject> getSomething() {
// Some code that calls your flow and returns YourObject.
return ResponseEntity.ok().body(YourObject);
}
so i got the answer what u need to do is add this dependency in client build.gradle
cordaCompile "net.corda:corda-jackson:$corda_release_version"
after that you just need to implement this code snip
String json = "";
try {
ObjectMapper mapper = JacksonSupport.createNonRpcMapper();
json = mapper.writeValueAsString(results);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return json;
result can be any datatype you want to convert to json

HTTP.call throws errors instead of returning response

I am working with the Facebook graph API and have run into trouble regarding handling failed requests.
I use this code to create a new post
SocialFacebook.createPosting = function(data) {
var options = {
params: {
access_token : data.tokens.accessToken,
message : data.text
}
};
var url = 'https://graph.facebook.com/' + data.graphId + '/feed';
var response = HTTP.call('POST', url, options).data;
return response;
}
But instead of returning a JS object with error information in the response, it throws an error on failed requests
Exception while invoking method 'createPosting' Error: failed [500] {"error":{"message":"Duplicate status message","type":"FacebookApiException","code":506,"error_subcode":1455006,"is_transient":false,"error_user_title":"Duplicate Status Update","error_user_msg":"This status update is identical to the last one you posted. Try posting something different, or delete your previous update."}}
Because it's wrapped in an Error, the otherwise JSON object is now a string with some other stuff appended to it, which makes it difficult to parse and extract the attributes
Any idea as to why it throws an error, instead of returning a JS object with error details like usually?
Much appreciated
According to the docs, about HTTP.call():
On the server, this function can be run either synchronously or asynchronously. If the callback is omitted, it runs synchronously and the results are returned once the request completes successfully. If the request was not successful, an error is thrown.
So there you have it: since you called HTTP.call() synchronously (without providing a callback), if it responds with an error (in your case, Code 500) the error is thrown and not included in the data.

ASP.NET Web API removing HttpError from responses

I'm building RESTful service using Microsoft ASP.NET Web API.
My problem concerns HttpErrors that Web API throws back to user when something go wrong (e.g. 400 Bad Request or 404 Not Found).
The problem is, that I don't want to get serialized HttpError in response content, as it sometimes provides too much information, therefore it violates OWASP security rules, for example:
Request:
http://localhost/Service/api/something/555555555555555555555555555555555555555555555555555555555555555555555
As a response, I get 400 of course, but with following content information:
{
"$id": "1",
"Message": "The request is invalid.",
"MessageDetail": "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'MyNamespaceAndMethodHere(Int32)' in 'Service.Controllers.MyController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
}
Something like this not only indicates that my WebService is based on ASP.NET WebAPI technology (which isn't that bad), but also it gives some information about my namespaces, method names, parameters, etc.
I tried to set IncludeErrorDetailPolicy in Global.asax
GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Never;
Yeah, that did somehow good, now the result doesn't contain MessageDetail section, but still, I don't want to get this HttpError at all.
I also built my custom DelegatingHandler, but it also affects 400s and 404s that I myself generate in controllers, which I don't want to happen.
My question is:
Is there any convinient way to get rid of serialized HttpError from response content? All I want user to get back for his bad requests is response code.
What about using a custom IHttpActionInvoker ?
Basically, you just have to send an empty HttpResponseMessage.
Here is a very basic example :
public class MyApiControllerActionInvoker : ApiControllerActionInvoker
{
public override Task<HttpResponseMessage> InvokeActionAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken)
{
var result = base.InvokeActionAsync(actionContext, cancellationToken);
if (result.Exception != null)
{
//Log critical error
Debug.WriteLine("unhandled Exception ");
return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.InternalServerError));
}
else if (result.Result.StatusCode!= HttpStatusCode.OK)
{
//Log critical error
Debug.WriteLine("invalid response status");
return Task.Run<HttpResponseMessage>(() => new HttpResponseMessage(result.Result.StatusCode));
}
return result;
}
}
In Global.asax
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpActionInvoker), new MyApiControllerActionInvoker());
One other important thing you could do, not related to Web Api, is to remove excessive asp.net & IIS HTTP headers. Here is a good explanation.
I believe your approach of using the message handler is correct because regardless of the component in the Web API pipeline that sets the status code to 4xx, message handler can clear out response body. However, you do want to differentiate between the ones you explicitly set versus the ones set by the other components. Here is my suggestion and I admit it is a bit hacky. If you don't get any other better solution, give this a try.
In your ApiController classes, when you throw a HttpResponseException, set a flag in request properties, like so.
Request.Properties["myexception"] = true;
throw new HttpResponseException(...);
In the message handler, check for the property and do not clear the response body, if the property is set.
var response = await base.SendAsync(request, cancellationToken);
if((int)response.StatusCode > 399 && !request.Properties.Any(p => p.Key == "myException"))
response.Content = null;
return response;
You can package this a bit nicely by adding an extension method to HttpRequestMessage so that neither the ApiController nor the message handler knows anything about the hard-coded string "myException" that I use above.

http streaming response unsupported message type: class org.jboss.netty.handler.stream.ChunkedStream

I am trying to write a netty based http server which takes text as input and returns an image as output. This image is generated on the fly based on the input text.
I copied the logic of org.jboss.netty.example.http.file.HttpStaticFileServerHandler into my own handler, and rather than writing a DefaultFileRegion as output in the channel,
final FileRegion region = new DefaultFileRegion(raf.getChannel(), 0, fileLength);
writeFuture = ch.write(region);
I am doing the following in my own handler:
InputStream imageIOStream = imageGenerator.generateImage(inputText);
ChannelFuture writeFuture = ch.write(new ChunkedStream(imageIOStream));
But I get the following exception on the server when I try to write back to the client.
java.lang.IllegalArgumentException: unsupported message type: class org.jboss.netty.handler.stream.ChunkedStream
at org.jboss.netty.channel.socket.nio.SocketSendBufferPool.acquire(SocketSendBufferPool.java:56)
at org.jboss.netty.channel.socket.nio.NioWorker.write0(NioWorker.java:463)
at org.jboss.netty.channel.socket.nio.NioWorker.writeFromUserCode(NioWorker.java:390)
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.handleAcceptedSocket(NioServerSocketPipelineSink.java:137)
at org.jboss.netty.channel.socket.nio.NioServerSocketPipelineSink.eventSunk(NioServerSocketPipelineSink.java:76)
at org.jboss.netty.handler.codec.oneone.OneToOneEncoder.handleDownstream(OneToOneEncoder.java:68)
at org.jboss.netty.channel.Channels.write(Channels.java:611)
at org.jboss.netty.channel.Channels.write(Channels.java:578)
at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:251)
Can someone please help me.
In your pipeline, have you setup the following?
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
See https://github.com/netty/netty/blob/master/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerPipelineFactory.java.

Send Data Using the WebRequest Class to DotNetOpenAuth website

I am trying to send data to DotNetOpenAuth website as described here http://msdn.microsoft.com/en-us/library/debx8sh9.aspx
Sender receive (500) Internal Server Error. The same code for blank website without DotNetOpenAuth works fine. Should I tweak something?
Here is an exception:
System.ArgumentNullException was unhandled by user code
Message="Value cannot be null.\r\nParameter name: key"
Source="mscorlib"
ParamName="key"
StackTrace:
at System.ThrowHelper.ThrowArgumentNullException(ExceptionArgument argument)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
at DotNetOpenAuth.OAuth.ChannelElements.OAuthChannel.ReadFromRequestCore(HttpRequestInfo request) in c:\BuildAgent\work\7ab20c0d948e028f\src\DotNetOpenAuth\OAuth\ChannelElements\OAuthChannel.cs:line 145
at DotNetOpenAuth.Messaging.Channel.ReadFromRequest(HttpRequestInfo httpRequest) in c:\BuildAgent\work\7ab20c0d948e028f\src\DotNetOpenAuth\Messaging\Channel.cs:line 372
at DotNetOpenAuth.OAuth.ServiceProvider.ReadRequest(HttpRequestInfo request) in c:\BuildAgent\work\7ab20c0d948e028f\src\DotNetOpenAuth\OAuth\ServiceProvider.cs:line 222
Exception occurs on last line of the code:
private void context_AuthenticateRequest(object sender, EventArgs e)
{
// Don't read OAuth messages directed at the OAuth controller or else we'll fail nonce checks.
if (this.IsOAuthControllerRequest())
{
return;
}
if (HttpContext.Current.Request.HttpMethod != "HEAD")
{ // workaround: avoid involving OAuth for HEAD requests.
IDirectedProtocolMessage incomingMessage = OAuthServiceProvider.ServiceProvider.ReadRequest(new HttpRequestInfo(this.application.Context.Request));
If you're sending the POST request with a Content-Type of application/x-www-form-urlencoded, but the POST entity contains something other than the normal key1=value1&key2=value2 format, that might explain it. It looks like DotNetOpenAuth can't handle a POST entity that claims to be name=value pairs but only has a value without a key in front of it. Arguably that's a bug in DotNetOpenAuth since normally that's just considered a value of a null key.
If you're not sending key=value pairs at all, I suggest you drop or change the Content-Type header so that you're not claiming to be sending key=value pairs. If you are sending them, but intentionally sending a null key, then hang on while the bug gets fixed.

Resources