How to get my topic name from message header and publish - json

I am new to spring-integration. I am trying to build a spring rest service where it will get any HTTP requests with some json message and publish to kafka topic.
My json message will be posted thru RequestBody which will contain the topic name in the message header.
I am able to post the message from my controller to kafka channel, however I am getting hard time to get the topic name from my json message header.
Can anyone suggest a way to get the topic name from my message header (typically a HTTP request consists a json message with topic name) and use the topic to publish the message.
my json :
{"resourceType": "MessageHeader",
"topicName": "testToptic",
"messagePayload":{
"location": "chennai",
"messageDetail": {
"department-id": 123,
"department-name": "SSS",
"pincode": 600009
}
}
}}
here my bean and handler
#Bean
public IntegrationFlow hanldeGenericKafka() {
return IntegrationFlows.from(sendToKafkaChannel)
.handle(
kafkaGenericMessageHandler(producerFactory),
e -> e.id("kafkaProducer2"))
.get();
}
public KafkaProducerMessageHandlerTemplateSpec<String, String> kafkaGenericMessageHandler(
ProducerFactory<String, String> producer) {
return Kafka
.outboundChannelAdapter(producer)
.sync(true)
.headerMapper(kafkaDefaultHeaderMapper())
.messageKey(m -> m.getHeaders()
.get("topicname"))
.configureKafkaTemplate(t -> t.id("kafkaTemplate"));
}

You can use an expression with the built-in JsonPath SpEL function to extract a field value from a JSON payload.
Use the expression in the adapter's .topicExpression().

Related

The value is not valid put request

I'm developing a web api using net core 5 and I'm getting the following error message after executing a put request from POSTMAN
"errors": {
"id": [
"The value '44' is not valid."
]
}
I have a breakpoint inside my controller method but doesn't hit any part of that code. So maybe this is a problem with the url that I'm using or some parameters configuration.
This is my httpmethod in my controller:
[HttpPut("Edit/{id}")]
public IActionResult Update(Guid id, [FromBody]Model mod)
{
return mod.SomeValue;
}
And this is my request from POSTMAN:
https://localhost:8820/api/controller/Edit/44
I'm sending params from body as a JSON object (the same object works using my POST method)
What can be the problem?
The problem is from using Guid type for storing a number.
you can't store 44 value in a Guid variable so change it to int.
[HttpPut("Edit/{id}")]
public IActionResult Update(int id, [FromBody]Model mod)
{
return mod.SomeValue;
}

#RequestParam to pass pojo fields in spring boot from form-data of postman

I have made a post mapping in spring boot to pass all the field values of my pojo from form-data of postman.
One of the fields involves uploading a file which is handled by multipartfile.
I am getting an internal server error in postman when running this method
#RequestMapping(method=RequestMethod.POST,value="/upload/{jobID}")
public Application upload(#RequestParam("file") MultipartFile file,#PathVariable String jobID,
#RequestParam("name") String name,#RequestParam("emailId") String emailId,
#RequestParam("applicationStatus") ApplicationStatus applicationStatus) throws IOException {
Offer offer=offerRepository.findById(jobID).get();
Application application=new Application();
System.out.println(file.getContentType());
System.out.println(file.getOriginalFilename());
System.out.println(file.getSize());
application.setApplicationStatus(ApplicationStatus.valueOf("APPLIED"));
application.setResume(file.getBytes());
application.getMykey().setOffer(offer);
return applicationRepository.save(application);
}
and here is the detailed error
{
"timestamp": "2018-10-15T17:31:31.346+0000",
"status": 500,
"error": "Internal Server Error",
"message": "No message available",
"path": "/api/upload/SE"
}
try to use POJO as requestParams to more organize method input
see
http://dolszewski.com/spring/how-to-bind-requestparam-to-object/
and before getting optional test if present
if(optional.isPresent()) then optional.get()

Wrapping default REST error response in custom object

I'm building a simple REST api for integration purposes, and i want the response to be as consistent as possible (the same regardless of errors).
I've used the #ExceptionHandler method in the past - so I'll most likely go with the class version of this...#ControllerAdvice if i remember correctly.
I know it works, I've used SO before to help me, it just requires setting up. This is not my question...
The API allows creating messages and searching messages (two separate requests), and thus, accepts date values which are internally validated. Upon testing this i received a really nicely formatted and incredibly detailed error response:
{
"timestamp": "2018-08-31T10:35:10.748+0000",
"status": 400,
"error": "Bad Request",
"errors": [
{
"codes": [
"typeMismatch.IntegrationMessageFilter.fromDate",
"typeMismatch.fromDate",
"typeMismatch.java.util.Date",
"typeMismatch"
],
"arguments": [
{
"codes": [
"IntegrationMessageFilter.fromDate",
"fromDate"
],
"arguments": null,
"defaultMessage": "fromDate",
"code": "fromDate"
}
],
"defaultMessage": "Failed to convert property value of type 'java.lang.String' to required type 'java.util.Date' for property 'fromDate'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [#com.fasterxml.jackson.annotation.JsonFormat java.util.Date] for value '213-456-45'; nested exception is java.lang.IllegalArgumentException",
"objectName": "IntegrationMessageFilter",
"field": "fromDate",
"rejectedValue": "213-456-45",
"bindingFailure": true,
"code": "typeMismatch"
}
],
"message": "Validation failed for object='IntegrationMessageFilter'. Error count: 1",
"path": "/Integration/get"
}
What i want to do is intercept this error and wrap it in my own response object which will be the same response object for every API method available:
e.g.
{
"success": Boolean,
"messageId": Integer, (null on search, int on successful create)
"messages": Array, (searched IntegrationMessage objects)
"errorMessage": String, (error message during manual validation (e.g. range validation depending on the field))
"error" [SPRING DEFAULT ERROR] (this is what i want to intercept from spring-boot and include in this response object)
}
It just sees a bit pointless to manually faff about creating a detailed error message when the system does it already...I don't know what object it uses to create the first JSON message above, or even if i can intercept it.
NOTE: This is purely for the convenience of the API users not having to differentiate between different response objects, and the convenience for me, not having to re-develop the wheel (so to speak).
OK so I've found how to acheive (sort of) what i want.
I was under the impression i could intercept the full exception response message and just put it inside my object, regardless of the type of exception. Turns out, i can get most of the default information, but it is specific to each error type (obviously).
First Attempt:
My first attempt was to simply "test" the default error response with the following. This was meant to identify what spring was doing (which error it was using - I genuinly thought it would have been the handleTypeMismatch exception) - the method below is just one in the class (the one that I'm currently dealing with):
#ControllerAdvice
public class IntegrationExceptionHandler extends ResponseEntityExceptionHandler
{
#Override
public ResponseEntity<Object> handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request)
{
return super.handleBindException(ex, headers, status, request);
}
}
I expected exactly the same error message as the default one, however this produced no response (or an empty response?).
My "Solution":
While i don't have to re-develop the wheel, i do have to do some hoop jumping:
#Override
public ResponseEntity<Object> handleBindException(final BindException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request)
{
IntegrationResponse response = new IntegrationResponse(ex.getMessage());
response.setErrors(ex.getBindingResult().getAllErrors());
return new ResponseEntity<Object>(response, headers, status);
}
Where errors is private List<ObjectError> errors; (org.springframework.validation.ObjectError)
So I'll have to try and replicate each overridable error in the ResponseEntityExceptionHandler (that applies to my situation) and treat it slightly differently, you can see now why i just wanted to wrap the existing response.
Just as a side note, I did try adding: private Object error; and private BindingResult error; as variables in my response object, however both attempts seem to reject my response object and show JUST the default message (as if there is no controller advice) with no hint as to why.
If anyone does discover how to skip the ResponseEntityExceptionHandler step and just wrap the default exception response object, I'll happily accept that answer.

Codenameone how to add multiple JSON subentries in a POST query

I have a REST webservice which allows me to upload user details in JSON format via a POST request. It looks like I can do this using
post.addArgument("Name",entry.get("Name").toString());
post.addArgument("JobRole",entry.get("JobRole").toString());
"entry" is an ArrayList < MapString, Object>
As you can see in the below JSON I also have the option of sending multiple entries per user (in this case address details) as in this JSON example:
{
"Name":"Fred Flintstone",
"JobRole":"Quarry worker",
"Address":[
{
"Address1" :"Boulder House",
"Address2" :"Rock Way",
"Address3" :"Rock City"
}
]
}
I have tried using
post.addArgumentArray("Address",entry.get("Address1").toString,entry.get("Address2"))
to combine the entries for the user under Address but I get "400: Bad Request" returned. So how do I add multiple entries like this to my request?
Regards
Those are POST style arguments and they are added as regular HTTP arguments not as JSON (it's like submitting a form in HTML).
What you are looking for is something like:
ConnectionRequest cr = new ConnectionRequest(url, true) {
protected void buildRequestBody(OutputStream os) throws IOException {
// snipped this but you should get the rest...
os.write("{\"Name\":\"Fred Flintstone\",\"JobRole\":\"Quarry worker\", ...");
}
};
Alternatively you can use the new terse REST API:
Map<String, Object> jsonData = Rest.post(myUrl).body(bodyValueAsString).getAsJsonMap();

Can Web API HttpPost return ICollection

Newb to writing Web Services. Am using C#/ASP.Net with WebAPI. End goal is to receive JSON collection, and deserialize the data to database, and inform client application of any failed records, which client will log.
Can the HTTPPost return a collection of the failed rows (as serialized Json) through an IHttpActionResult or HttpResponseMessage, kind of like this:
[HttpPost]
public HttpResponseMessage Post([FromBody]List<Things> t)
{
// deserialize t and process to database
// list of failed records
ICollection<Thing> things= new List<Thing>();
things.Add(...);
things.Add(...);
string jsonFailedRows =
JsonConvert.SerializeObject(things, Formatting.Indented);
// Write the list to the response body
HttpResponseMessage response =
Request.CreateResponse(HttpStatusCode.OK, jsonFailedRows);
return response;
}
I saw this link: StackOverFlow, which says the I can do the following, but is this correct for a Post?
"The latter is done for you if you call the ApiController.Ok() method:
return Ok(jsonFailedRows);
And lastly, is there any way of using CreatedAtRoute to do so?
The solution posted in the linked response indeed answers this question.