Linebreak in AWS SNS through Api Gateway and Java - java

I am triggering the AWS SNS through the API Gateway.
JSONObject requestBody = new JSONObject();
requestBody.put("phone_number", receiverNumber);
requestBody.put("sender_id", senderAlias);
requestBody.put("message_text", messageText);
This JSONObject is being sent to the api gateway as a ByteArrayInputStream throug the AWS SDK for Java v1.
There are "\n" in the text, to create line breaks. The sms however does not have a new line there, it just prints \n.
In the Api Gateway the message is extracted like this: method.request.body.message_text
How do I have to set up the messageText variable to print new lines in the SMS? I tried replacing it with \n or \\n or \\\\n.. Also tried ASCII, didn't work.
Invocation
As this is a quite complex programm I can't show all of it. It's triggered via Insomnia with a String in Json format like this:
It has to be a double backslahed n because thats just how the code needs it. The aws integration is an additional provider so it has to fit in already existing frames. The json object looks like this before being executed.
So I need to find a way to manipulate the string thats going in the object. But I don't know how.
EDIT 3:
Deleting previous edits, as they were not helpful and did not target the problem as I know now.
Finally closing down the issue. It's a problem in the API-Gateway. The object reaches the gateway just fine, with a \n. Which would work in the SNS Service. But to trigger the SNS Service, it's all going into one URL, which converts the \n into %5Cn
Before transformation:
URL:
So the problem is in the URL encoding..

Thanks to the AWS Support I now am able to send SMS with line breaks through the api gateway.
It was wrong to use URL Query Parameters. I removed all of them
I needed one HTTP Header:
Content-Type: 'application/x-www-form-urlencoded'
Then I used a Messaging Template like this, with passthrough: Never:
#set($message = $input.path('$.message_text'))
#set($phoneNumber = $input.path('$.phone_number'))
Action=Publish&PhoneNumber=$util.urlEncode($phoneNumber)&Message=$util.urlEncode($message)&MessageAttributes.entry.1.Name=AWS.SNS.SMS.SenderID&MessageAttributes.entry.1.Value.DataType=String&MessageAttributes.entry.1.Value.StringValue=Alias
Having my JSON Object in the Request like this:
{
"phone_number": "+4912345678",
"message_text": "Break\nHere",
"sender_id":"Alias"
}
Works perfectly fine with a line break in the SMS

Related

Sending Java/Kotlin objects to RSocket route

I've set up #MessageMapping endpoint using Spring's RSocket support and tested it with RSocketRequester. This flow is working perfectly since Spring handles bunch of low-level stuff for us.
Now, I'd like to have some sort of UI to show whatever data I'm working with and do any UI updates on that data through mentioned #MessageMapping endpoint. The problem is that I have no idea how to send full Java/Kotlin object (as JSON) to my endpoint using either rsocket-java or rsocket-kotlin libraries. Since I have to send both data and metadata and metadata is encoded as ByteBuf I had to encode JSON to ByteBuf, but it comes to endpoint all messed up and it cannot be deserialized.
I've also tried sending raw string value and it also comes to endpoint all messed up (bunch of non-UTF chars). I've tried both APPLICATION_JSON and TEXT_PLAIN for data mime type, but it didn't work for either.
Also, I guess whatever I'm doing wrong is not strictly related to Java/Kotlin libraries, but can be applied to any other existing RSocket library (Go, Rust, JS, etc.)
If you are using an rsocket-kotlin client (not building on spring-boot) then you can copy the code from https://github.com/rsocket/rsocket-cli/blob/master/src/main/kotlin/io/rsocket/cli/Main.kt
It builds metadata for the route with
this.route != null -> {
CompositeMetadata(RoutingMetadata(route!!)).toPacket().readBytes()
}
I guess I've figured it out.
I've scratched that binary encoded metadata and borrowed what I found on the internet for RSocket in JavaScript and it worked :)
So, the solution is to use routing metadata mime type (I was using composite since example I found was using it) and the payload then can be created like this:
val json = "{}"
val route = "myawesomeroute"
DefaultPayload.create(<json>, "${route.length.toChar()}$route")

In Twilio voice, how do I make TWO outgoing calls and connect both together?

I want to programmatically make two outgoing calls using the Java Twilio API. What I have so so far is as following:
I registered two numbers with twilio. The I execute the following code to make the first outgoing call:
val call = Call.creator(
PhoneNumber(numberOne), // TO
PhoneNumber(TWILIO_NUMBER0), // FROM
URI.create(twilioInformURL(id)) // INSTRUCTIONS for when person picks up
).setMethod(HttpMethod.POST)
.setStatusCallback(twilioStatusURL(id))
.setStatusCallbackMethod(HttpMethod.POST)
.setStatusCallbackEvent(listOf("initiated", "in-progress", "ringing", "answered", "completed"))
.create()
This will call numberOne number from TWILIO_NUMBER0, then do an API POST Call to my URL where I return the following to make the second call:
val number = Number.Builder(numberTwo).build()
val dial = Dial.Builder().number(number).build()
val response = VoiceResponse.Builder().dial(dial).build()
return response.toXml()
Unfortunately this doesn't work. It just calls and reads out numberTwo.
If anyone knows how to make this work I would really appreciate it.
Twilio developer evangelist here.
If Twilio is just reading out your number then you are likely not serving the TwiML as XML. If Twilio doesn't see a Content-Type header of text/xml or application/xml then it assumes text content and reads out the text contents of the elements.
Make sure you are setting your Content-Type header in the webhook response and this should work.

Can I return non-JSON data from an AWS lambda called through API gateway?

I have a simple lambda in AWS that takes plain text (non-JSON) input and gives plain text (non-JSON) output, and it works when I test it in the Lambda Management Console. I'd like to call it by POSTing the input via HTTP, so I added API Gateway as a trigger, but it says "An error occurred during JSON parsing" - fair enough, because I didn't output JSON.
I found a number of similar questions here, but they focused on fixing the JSON. My question is whether it's possible to avoid it altogether. Can I configure API Gateway to just pass through the request and response bodies, or is there another way to get an HTTP request to my lambda that would allow that?

Use string from Java in Jenkins job

I have a string variable in my Java application that is being built by Jenkins. After Jenkins build is done, it sends a notification to our internal messenger. I need to include this Java string into the notification message. This string is not constant. It is dynamic and depends on the response that is being returned by a request that is handled in Java app.
Currently, the notification message consists of a build's metadata - status, build number, job name. These values are taken by Jenkins by getting the values of respective environment variables.
How can I get in Jenkins the value of the Java string variable?
According to our previuous comments, I guess you need to do something like this:
Create an API in your Java App: this API needs to publish an operation with the parsed response (the one which gets the 3rd service response).
Call this API from Jenkins, with, for example, a curl (you can do it with Groovy if you want to), something like this (assuming you return a json response):
//The next http://yourdomain... URL is the one your Java app will expose with your parsed response
def response = sh script: "curl 'http://yourdomain/api/v1/yourResource'", returnStdout: true
def jsonProcessed = readJSON text: response
//Do some post-process in Jenkins if you need to using readJSON. I just put a dummy raise error example (Check the readJSON link below)
if (jsonProcessed.key == 'whatever') {
error "Raise some error"
}
// Or directly the code to send the response to the messenger
// TODO Your sending code HERE
Send the response from Jenkins to your messenger.
Help with readJSON
Hope it helps.

How to set additional authentication properties in apache camel DSL or inside the camel Processor?

Here I am trying to convert Json data to CSV format and finally send this file to Ofbiz server api but the api endpoint require some authentication content when I send parameter in URL I got the output below.
{"_ERROR_MESSAGE_":"Error calling event: org.apache.ofbiz.webapp.event.EventHandlerException: Found URL parameter [configId] passed to secure (https) request-map with uri [uploadAndImportFileFromCSVFile] with an event that calls service [uploadAndImportFile]; this is not allowed for security reasons! The data should be encrypted by making it part of the request body (a form field) instead of the request URL. Moreover it would be kind if you could create a Jira sub-task of https://issues.apache.org/jira/browse/OFBIZ-2330 (check before if a sub-task for this error does not exist). If you are not sure how to create a Jira issue please have a look before at https://cwiki.apache.org/confluence/display/OFBIZ/OFBiz+Contributors+Best+Practices Thank you in advance for your help.","sessionId":"someId.jvm1","removePathAlias":false,"loggedIn":true,"USERNAME":"__","_LOGIN_PASSED_":"TRUE","webSiteId":"API"}
After that I used MultipartBuilder to send request below.
exchange.getIn().setHeader("bearer",token);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
File file =new File("//home/r2/Desktop/ofBizFile/orderFile.csv");
builder.addPart("configId",new StringBody("CON_ID"));
builder.addPart("fileTypeEnumId",new StringBody("CSV_FILE"));
builder.addPart("_uploadedFile_contentType",new StringBody("text/csv"));
builder.addPart("uploadedFile",new FileBody(file));
exchange.getIn().setBody(builder.build());
I also tried something like this.
exchange.setProperty(Exchange.CHARSET_NAME, "ISO-8859-1");
exchange.getIn().setHeader(Exchange.HTTP_QUERY,"USERNAME=abc&PASSWORD=bc69");
exchange.getIn().setBody("configId=CON_ID&fileTypeEnumId=CSV_FILE");
Here is my camel route
//Route 1
from("couchdb:http://localhost:5984/order")
.process(new JsonToCsvProcessor())
//Storing file into local directory
.to("file:/home/r2/Desktop/ofBizFile?fileExist=append&fileName=order-${date:now:yyyyMMdd}.csv");
.to("direct:jsonToCsv");
//Route 2
from("direct:jsonToCsv")
.setHeader(Exchange.HTTP_QUERY,constant("USERNAME=__&PASSWORD=__"))
//For get token
.to("https4://SomeAddress.com/centerAPI/getAuthenticationToken")
//Get the token and set required parameter for route 3
.process(new ProcessorGetToken())
.to("direct:hold");
//Route 3
from("direct:hold")
.setHeader(Exchange.HTTP_QUERY,constant("USERNAME=__&PASSWORD=__"))
.to("https4://SomeAddress.com/centerAPI/uploadAndImportFileFromCSVFile?throwExceptionOnFailure=false")
//How I know the file is submited successfuly ?
.to("stream:out").end();
So the problem is how I can send data inside the body in Route2 ProcessorGetToken for next Route3 ?
I'll give a shot into the dark here. Reading your error message:
The data should be encrypted by making it part of the request body (a form field) instead of the request URL
Don't you have a documentation about this integration? I think you need more clarification about this process and what's need to encrypt your data before sending it.
Also, try to set the Exchange.HTTP_METHOD to POST into your route, like this:
exchange.setProperty(Exchange.CHARSET_NAME, "ISO-8859-1");
exchange.getIn().setHeader(Exchange.HTTP_METHOD, "POST");
exchange.getIn().setHeader(Exchange.HTTP_QUERY,"USERNAME=abc&PASSWORD=bc69");
exchange.getIn().setBody("configId=CON_ID&fileTypeEnumId=CSV_FILE");
Take a look into this unit test to see more examples sending data over HTTP. There's also many other tests there.

Categories

Resources