AWS adaptor with Spring Cloud function - payload body is removed - spring-cloud-function

I am building a AWS lambda function using Spring cloud, aws adapter and spring native.
The lambda is fronted by a APIGateway HTTP API V2.0.
<java.version>11</java.version>
<spring-cloud.version>2021.0.2</spring-cloud.version>
<spring-native.version>0.11.4</spring-native.version>
<aws-lambda-events.version>3.9.0</aws-lambda-events.version>
<wrapper.version>1.0.27.RELEASE</wrapper.version>here
When I hit the API with the cloud function pointing to echo function, I get a response with the body of the request removed!
I setup below test to debug the issue. Found that the below highlighted code from
org.springframework.cloud.function.adapter.aws.AWSLambdaUtils
is causing the issue. I see that the highlighted line is removed in the 4X branch. Request to kindly guide how to incorporate that fix into my project while staying on the release version of the dependencies.
public static void main(String[] args) {
String message = "{\r\n"
+ " \"version\": \"2.0\",\r\n"
+ " \"routeKey\": \"POST /updatePet\",\r\n"
+ " \"rawPath\": \"/updatePet\",\r\n"
+ " \"rawQueryString\": \"\",\r\n"
+ " \"headers\": {\r\n"
+ " \"accept\": \"*/*\",\r\n"
+ " \"accept-encoding\": \"gzip, deflate, br\",\r\n"
+ " \"content-length\": \"77\",\r\n"
+ " \"content-type\": \"application/json\",\r\n"
+ " \"host\": \"XXXXXX.execute-api.ap-south-1.amazonaws.com\",\r\n"
+ " \"postman-token\": \"2004009f-2661-46ea-9a31-2d6be0bb9281\",\r\n"
+ " \"user-agent\": \"PostmanRuntime/7.29.0\",\r\n"
+ " \"x-amzn-trace-id\": \"Root=1-62823410-XXXXXXXXXXXXX\",\r\n"
+ " \"x-forwarded-for\": \"111.11.111.111, 111.111.111.111\",\r\n"
+ " \"x-forwarded-port\": \"443\",\r\n"
+ " \"x-forwarded-proto\": \"https\"\r\n"
+ " },\r\n"
+ " \"requestContext\": {\r\n"
+ " \"accountId\": \"123456733\",\r\n"
+ " \"apiId\": \"xxxxx\",\r\n"
+ " \"domainName\": \"xxxxxx.execute-api.ap-south-1.amazonaws.com\",\r\n"
+ " \"domainPrefix\": \"vaoo36b2l5\",\r\n"
+ " \"http\": {\r\n"
+ " \"method\": \"POST\",\r\n"
+ " \"path\": \"/updatePet\",\r\n"
+ " \"protocol\": \"HTTP/1.1\",\r\n"
+ " \"sourceIp\": \"1.1.1.1\",\r\n"
+ " \"userAgent\": \"PostmanRuntime/7.29.0\"\r\n"
+ " },\r\n"
+ " \"requestId\": \"SN0SoioabccwEJuQ=\",\r\n"
+ " \"routeKey\": \"POST /updatePet\",\r\n"
+ " \"stage\": \"$default\",\r\n"
+ " \"time\": \"16/May/2022:11:22:56 +0000\",\r\n"
+ " \"timeEpoch\": 1652700176657\r\n"
+ " },\r\n"
+ " \"body\": \"{\\r\\n\\\"id\\\":1,\\r\\n\\\"name\\\":\\\"toto\\\",\\r\\n\\\"type\\\":\\\"dog\\\",\\r\\n\\\"owner\\\":{\\\"name\\\":\\\"test\\\",\\\"age\\\":8}\\r\\n}\",\r\n"
+ " \"isBase64Encoded\": false\r\n"
+ "}";
Message<byte[]> msg = AWSLambdaUtils.generateMessage(message.getBytes(StandardCharsets.UTF_8), headers(), String.class, mapper());
var payload = new String(msg.getPayload(),StandardCharsets.UTF_8);
System.out.println("payload is"+payload);
}

Related

Data management outputted from a transaction

I have a smart contract in which I simulate an event through a set that manually inputs certain data like this: (I use Remix)
[ "From", "to", "object", [ "rules1", "rules2"]], [[1, "data1"], [2, "data2"], [3, "data3"]]
This is my code:
pragma experimental "v0.5.0";
pragma experimental ABIEncoderV2;
contract StructContract {
struct Certificate{
uint id;
string data;
}
struct StructEvent {
string _from;
string _to;
string _object;
string[] _rules;
}
StructEvent structEvent;
Certificate[] certificate;
function setEvent(StructEvent eventS,Certificate[] eventC) public{
certificate.length=0;
structEvent = eventS;
for(uint i=0;i<(eventC.length);i++){
certificate.push(Certificate(eventC[i].id,eventC[i].data));
}
}
function getStruct() view public returns(StructEvent){
return(structEvent);
}
function getCertificate() view public returns(Certificate[]){
return(certificate);
}
function returnAllData() view public returns(StructEvent,Certificate[]){
return(structEvent,certificate);
}
}
once this is done, what I expect is that these data are put into a transaction that is then uploaded to blockchain. Then I have to take the data in these transactions to perform checks on them.
So I need to have data that are put on blockchain, as a solution to this problem I created this code: (I use web3 1.0.0-beta.36)
function printTransaction(txHash) {
web3.eth.getTransaction(txHash, function (error, tx) {
if (tx != null) {
var inputData = tx.input;
try {
var myContract = new web3.eth.Contract(abi, tx.to);
var result = web3.eth.abi.decodeParameters(['tuple(string,string,string,string[])',
'tuple(uint,string)[]'], inputData.slice(10));
var data1 = result[0];
var data2 = result[1];
console.log("\n\n");
console.log("--- transactions ---");
console.log(" tx hash : " + tx.hash + "\n"
+ " nonce : " + tx.nonce + "\n"
+ " blockHash : " + tx.blockHash + "\n"
+ " blockNumber : " + tx.blockNumber + "\n"
+ " transactionIndex: " + tx.transactionIndex + "\n"
+ " from : " + tx.from + "\n"
+ " to : " + tx.to + "\n"
+ " value : " + tx.value + "\n"
+ " gasPrice : " + tx.gasPrice + "\n"
+ " gas : " + tx.gas + "\n"
+ " input : " + tx.input + "\n"
+ " decodeinput : " + "\n"
+ " Struct : " + data1 + "\n"
+ " Certificates : " + data2);
web3.eth.getAccounts(function (err, account) {
myContract.methods.setEvent(data1, data2).send({ from: account[0], gas: 3000000 }, function (err, resul) {
if (err) {
console.log("err");
} else {
console.log("\n\n");
console.log("--- data ---");
myContract.methods.returnAllData().call().then(console.log);
}
});
});
} catch (Error) { }
}
});
}
What I decided to do is create, in a js file, a method that was able to take the transactions, decode the input related to the data contained in it and pass this data, through the send, to my smart contract in which it will be used.
these methods that I created represent the right solution? or I have to use another kind of approach, another method to do this?
Thanks in advance.

Why won't my function execute

I'm relatively new to python and the only other experience I've had is C++. Whenever I define a function in Python, I can't seem to execute it.
This my current code for my assignment, if possible I just want to know why my code won't execute
def birthexp(birthyear):
product = birthyear**birthyear
length = len(str(product))
onesCount = str(product).count("1")
threeCount = str(product).count("3")
fiveCount = str(product).count("5")
sevenCount = str(product).count("7")
nineCount = str(product).count("9")
sumCount = onesCount+threeCount+fiveCount+sevenCount+nineCount
oneRation = onesCount/float(length)*100
threeRatio = threeCount/float(length)*100
fiveRatio = fiveCount/float(length)*100
sevenRatio = sevenCount/float(length)*100
nineRatio = nineCount/float(length)*100
totalRatio = sumCount/float(length)*100
print(str(product) + ": product after multiplying the birth year to itself.")
print(str(onesCount) + ": number of ones found at a rate of " +str(oneRation)+ "percent.")
print(str(threeCount) + ": number of threes found at a rate of " +str(threeRatio)+ "percent")
print(str(fiveCount) + ": number of fives found at a rate of " +str(fiveRatio)+ "percent")
print(str(sevenCount) + ": number of sevens found at a rate of " +str(sevenRatio)+ "percent")
print(str(nineCount) + ": number of nine found at a rate of " +str(nineRatio)+ "percent")
print(str(sumCount) + ": total odd numbers found at a rate of " +str(totalRatio)+ "percent")
birthyear(1990)
You have a typo in this line totalRatio = sumCount/floar(length)*100. You need float instead of floar.
Secondly, you have loads of missing parenthesis in almost all lines with the print function.
If you want the function to return value, you should use return instead of print's:
return (str(product)
+ ": product after multiplying the birth year to itself.\n"
+ str(onesCount)
+ ": number of ones found at a rate of " + str(oneRation) + "percent.\n"
+ str(threeCount)
+ ": number of threes found at a rate of " + str(threeRatio) + "percent\n"
+ str(fiveCount)
+ ": number of fives found at a rate of " + str(fiveRatio) + "percent\n"
+ str(sevenCount)
+ ": number of sevens found at a rate of " + str(sevenRatio) + "percent\n"
+ str(nineCount)
+ ": number of nine found at a rate of " + str(nineRatio) + "percent\n"
+ str(sumCount)
+ ": total odd numbers found at a rate of " + str(totalRatio) + "percent\n")

Clear QList that is being used by QSerial

I have the following bit of code:
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updatecommstatus()));
timer -> start();
void MainWindow::updatecommstatus()
{
const auto infos = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo &info : infos) {
QString s = QObject::tr("Port: ") + info.portName() + "\n"
+ QObject::tr("Location: ") + info.systemLocation() + "\n"
+ QObject::tr("Description: ") + info.description() + "\n"
+ QObject::tr("Manufacturer: ") + info.manufacturer() + "\n"
+ QObject::tr("Serial number: ") + info.serialNumber() + "\n"
+ QObject::tr("Vendor Identifier: ") + (info.hasVendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Product Identifier: ") + (info.hasProductIdentifier() ? QString::number(info.productIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Busy: ") + (info.isBusy() ? QObject::tr("Yes") : QObject::tr("No")) + "\n";
if (QString::number(info.vendorIdentifier(), 16) == "16d0" && QString::number(info.productIdentifier(), 16) == "650")
{
ui->label_commport->setText(info.portName());
}
else
{
ui->label_commport->setText("COM Error");
}
}
}
It is utilising QSerial to display all the available COM ports info. I want to display the portName in a label when certain vendorIdentifierand and productIdentifier match some number.
The above code works well when the device is plugged in (my label displays the right information). But I want to have it when I unplug it that the label displays COM Error. This part does not work. The above code is being targetted by a QTimer and updated, but the Qlist infos is not clearing. Basically, how can I clear this Qlist ? infos.clear(); does not work.
As #lucaAngiolini alluded to in his comment, the scope of you label update seems wrong. I think your trying to do actually compile all available ports into a string, and then set the label thereafter.
void MainWindow::updatecommstatus()
{
const auto infos = QSerialPortInfo::availablePorts();
QStringList comport_labels;
if (infos.empty())
comprt_labels << "COM Error";
for (const QSerialPortInfo &info : infos) {
QString s = QObject::tr("Port: ") + info.portName() + "\n"
+ QObject::tr("Location: ") + info.systemLocation() + "\n"
+ QObject::tr("Description: ") + info.description() + "\n"
+ QObject::tr("Manufacturer: ") + info.manufacturer() + "\n"
+ QObject::tr("Serial number: ") + info.serialNumber() + "\n"
+ QObject::tr("Vendor Identifier: ") + (info.hasVendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Product Identifier: ") + (info.hasProductIdentifier() ? QString::number(info.productIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Busy: ") + (info.isBusy() ? QObject::tr("Yes") : QObject::tr("No")) + "\n";
if (QString::number(info.vendorIdentifier(), 16) == "16d0" && QString::number(info.productIdentifier(), 16) == "650")
{
comport_labels << info.portName();
}
else
{
comport_labels << "COM Error";
}
}
ui->label_commport->setText(comport_labels.join(","));
}

Path is wrong, what to do?

I'd like to write something to my path.
My code is following
QString Log::logPacketsPath = QDir::currentPath() + "/logs/Packets/";
int userID = 1;
QString text = "test 1 2 3";
QFile logPacketFile(logPacketsPath + "UserID: " + userID + " - " + QDateTime::currentDateTime().toString("dd.MM.yy") + ".log");
if (logPacketFile.open(QFile::WriteOnly | QFile::Text | QFile::Append))
{
QTextStream out(&logPacketFile);
out << "[" << QDateTime::currentDateTime().toString("dd.MM.yy, hh:mm:ss") << "]: " << text << "\n";
logPacketFile.close();
}
But it only creates the file named "UserID" with nothing in it.
Do you know where the mistake is?
I'm not sure which OS you're using, but ':' is invalid in a Windows filename.
Next, you should flush the QTextStream before closing the file:
out.flush();
logPacketFile.close();
or create additional scope:
{
QTextStream out(&logPacketFile);
out << "[" << QDateTime::currentDateTime().toString("dd.MM.yy, hh:mm:ss") << "]: " << text << "\n";
}
logPacketFile.close();
Also, as Chemobyl has pointed out, you can get into trouble by concatinating the int userID to your filepath. I'd suggest using string formatting to create the filename:
QString logPacketFile("%1UserID%2 - %3.log")
.arg(logPacketsPath)
.arg(userID)
.arg(QDateTime::currentDateTime().toString("dd.MM.yy"));
Convert int to QString:
Use QString::number().
Output with your current code:
"C:/.../logs/Packets/UserID [bad symbols here] - 17.11.14.log"
Output with
QFile logPacketFile(logPacketsPath + "UserID " + QString::number(userID) + " - " + QDateTime::currentDateTime().toString("dd.MM.yy") + ".log");//removed colon
is:
"C:/.../logs/Packets/UserID 1 - 17.11.14.log"
It is source of big troubles. See next:
int userID = 70;
QString text = "test 1 2 3";
QFile logPacketFile(logPacketsPath + "UserID " + userID + " - " + QDateTime::currentDateTime().toString("dd.MM.yy") + ".log");
Output:
.../UserID F - 17.11.14.log"
Note F, not a 70 because operator+ thought that you use simple char and 70 in char is F:
http://www.asciitable.com/
So I strongly suggest you to use QString::number to prevent errors.

Try catch trouble in netbeans

I'm trying to create a search engine that gets information from my SQL database. Right now I'm struggling to make the combobox and textfield work. So far I can only make the first part of the code work, it allows the user to search for a name in the database. The rest however doesn't work at all, resulting in just an empty window where the info should pop up.
Here are some translations of the Swedish words present in the code:
Namn - Name
sokt - Searched
ANSTALLD - Employee
Aid - Employee id
telefon - phone
try
{
if(jComboBoxSokAID.getSelectedItem().equals("Namn"))
{
String namn = jTextFieldSokText.getText();
String namnQuery = "select * from ANSTALLD where namn = '" + namn + "'";
try
{
HashMap <String, String> soktNamn = idb.fetchRow(namnQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktNamn.get("namn") + "\n" + "Aid: " + soktNamn.get ("aid") + "\n" + "Telefon: " + soktNamn.get ("telefon") + "\n" + "Mail: " + soktNamn.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("Mail"))
{
String mail = jTextFieldSokText.getText();
String mailQuery = "select * from ANSTALLD where mail = '" + mail + "'";
try
{
HashMap <String, String> soktMail = idb.fetchRow(mailQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktMail.get("namn") + "\n" + "Aid: " + soktMail.get ("aid") + "\n" + "Telefon: " + soktMail.get ("telefon") + "\n" + "Mail: " + soktMail.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("Telefon"))
{
String telefon = jTextFieldSokText.getText();
String telefonQuery = "select * from ANSTALLD where telefon = '" + telefon + "'";
try
{
HashMap <String, String> soktTelefon = idb.fetchRow(telefonQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktTelefon.get("namn") + "\n" + "Aid: " + soktTelefon.get ("aid") + "\n" + "Telefon: " + soktTelefon.get ("telefon") + "\n" + "Mail: " + soktTelefon.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("AID"))
{
String AID = jTextFieldSokText.getText();
String AIDQuery = "select * from ANSTALLD where aid = '" + AID + "'";
try
{
HashMap <String, String> soktAID = idb.fetchRow(AIDQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktAID.get("namn") + "\n" + "Aid: " + soktAID.get ("aid") + "\n" + "Telefon: " + soktAID.get ("telefon") + "\n" + "Mail: " + soktAID.get ("mail"));
}
catch (InformatikException e)
{
if(jComboBoxSokAID == null)
jTextAreaSpecialistInfo.setText("Sökningen gav inga resultat");
}
}
}
catch (InformatikException e)
{
}
}
}
catch (InformatikException e)
{
}
}
}
catch (InformatikException e)
{
}
Don't write code this way.
Never have empty catch blocks.
I prefer to have a single try/catch in a method. Nesting them this way is an indication that you ought to refactor a method that's doing too much.
You've mingled persistence and UI code together in the worst way possible. Tease them apart so you can test and use them separately.
You don't close any database resources. This will come to grief.