Consumer with message selector not working - activemq

I have a simple consumer:
try
{
factory = new NMSConnectionFactory(Settings.Endpoint);
connection = factory.CreateConnection(Settings.UserName, Settings.Password);
connection.ClientId = Settings.Name;
session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
destination = SessionUtil.GetDestination(session, Settings.QueueName, DestinationType.Queue);
consumer = session.CreateConsumer(destination, "portCode = 'GB'", false);
consumer.Listener += new MessageListener(OnMessage);
}
catch
{
throw;
}
I need to apply a selector to get messages when the portCode field is equal to "GB".
This queue receives many messages.
The message is in JSON and a sample of this message is shown below:
{
"message": {
"list": [
{
xxxxxxx
}
]
},
"header": {
"messageCode": "xxxxxx",
"portCode": "GB",
"sourceSystem": "origin",
"messageId": "ca0bf0e0-cefa-4f5a-a80a-b518e7d2f645",
"dateTimeMessage": "2021-04-22T07:12:48.000-0300",
"version": "1.0"
}
}
However, I do not receive messages using the specified "GB" selector.
It seems simple to define selectors, but it is not working for me.
Thanks.

Selectors do not work on the body of the message (i.e. your JSON data). They only work on the headers and properties of the message.

Related

Ktor-server RequestValidation not working

I am using ktor (2.1.0) to create a small API. While doing so, I am trying to leverage Ktor-server cool functionalities, including RequestValidation.
That being said, it is not working and I can't figure out why since it looks to me very close to the examples in the documentation.
This is my server config:
embeddedServer(Netty, port = 8080) {
routing {
post("/stock") {
val dto = call.receive<CreateStockRequest>()
call.respond(HttpStatusCode.NoContent)
}
}
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
})
}
install(StatusPages) {
exception<RequestValidationException> { call, cause ->
call.respond(HttpStatusCode.BadRequest, cause.reasons.joinToString())
}
}
install(RequestValidation) {
validate<CreateStockRequest> { request ->
if (request.name.isBlank())
ValidationResult.Invalid("Stock must have a name")
if (request.symbol.isBlank())
ValidationResult.Invalid("Symbol must have a name")
ValidationResult.Valid
}
}
}
This is the request object being "received":
#Serializable
data class CreateStockRequest(val name: String, val symbol: String)
And this is the body being sent:
{
"name": "",
"symbol": "something"
}
I was expecting to get a BadRequest response, but I am getting a NoContent response as if everything was fine with the request.
Am I doing something wrong?
In your example, the server responds with BadRequest only if both "name" and "symbol" are blank. You can replace your validation logic with the when expression:
validate<CreateStockRequest> { request ->
when {
request.name.isBlank() -> ValidationResult.Invalid("Stock must have a name")
request.symbol.isBlank() -> ValidationResult.Invalid("Symbol must have a name")
else -> ValidationResult.Valid
}
}
I found the accepted answer to be a cleaner code solution, and that's why it is the accepted one.
That being said, the actual problem I was having is better explained by understanding that the compiler was getting confused with scopes.
On each "if" clause, I needed to return the validation result, but the compiler was not having it.
The reason for that was the fact that it got confused with the context to which my return statement referred.
My Solution was to use the '#' notation to specify the scope for the return:
validate<CreateStockRequest> { request ->
if (request.name.isBlank())
return#validate ValidationResult.Invalid("Stock must have a name")
if (request.symbol.isBlank())
return#validate ValidationResult.Invalid("Symbol must have a name")
return#validate ValidationResult.Valid
}
}

IoT Hub Event Grid integration is creating two "Disconnected" events instead of a "Connected" and "Disconnected" event

I am using IoT Hub's Event Grid integration to monitor device connections and disconnections and am finding that I receive 2 "Disconnected" events and no "Connected" events. I am currently routing the Events to an Azure Function. Please let me know if I have configured it correctly.
IoT Hub Configuration:
Azure Function Code:
public static class IoTConnectionTrigger
{
//public static void Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
[FunctionName("IoTConnectionTrigger")]
public static void Run([EventGridTrigger]JObject eventGridEvent, ILogger log)
{
log.LogInformation(eventGridEvent.ToString(Formatting.Indented));
}
}
}
Code used to create the IoT Hub message:
static void Main(string[] args)
{
for (int i=0; i<10; i++)
{
DeviceClient client = DeviceClient.CreateFromConnectionString("HostName=<IoT Hub Name>.azure-devices.net;DeviceId=SampleDevice;SharedAccessKey=<key>");
// Create JSON message
var telemetryDataPoint = new
{
Temperature = 50,
Location = "Calgary",
TimeStamp = DateTime.Now
};
var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
Message message = new Message(Encoding.UTF8.GetBytes(messageString));
message.ContentType = "application/json";
message.ContentEncoding = "UTF-8";
try
{
client.SendEventAsync(message).Wait();
Console.WriteLine("Sent!");
} catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
Console.WriteLine("Complete");
}
Output: (Note the two "Microsoft.Devices.DeviceDisconnected" event types, and that no "Connected" events were raised)
Executing 'IoTConnectionTrigger' (Reason='EventGrid trigger fired at 2022-03-18T16:15:16.3717212+00:00', Id=84001f7e-6743-4847-ba73-48b597af33fa)
2022-03-18T16:15:16.372 [Information] {
"id": "de252911-9e70-b66f-954a-641d2c508040",
"topic": "/SUBSCRIPTIONS/7965FC25-694A-478C-B4FA-911F94239D30/RESOURCEGROUPS/TMRESOURCEGROUP/PROVIDERS/MICROSOFT.DEVICES/IOTHUBS/TMIOTHUB",
"subject": "devices/SampleDevice",
"eventType": "Microsoft.Devices.DeviceDisconnected",
"data": {
"deviceConnectionStateEventInfo": {
"sequenceNumber": "000000000000000001D80D890755FFF30000004500000000000000000000000B"
},
"hubName": "<IoT Hub Name>",
"deviceId": "SampleDevice"
},
"dataVersion": "",
"metadataVersion": "1",
"eventTime": "2022-03-18T16:14:36.8975903Z"
}
2022-03-18T16:15:16.372 [Information] Executed 'IoTConnectionTrigger' (Succeeded, Id=84001f7e-6743-4847-ba73-48b597af33fa, Duration=1ms)
2022-03-18T16:15:16.371 [Information] Executing 'IoTConnectionTrigger' (Reason='EventGrid trigger fired at 2022-03-18T16:15:16.3717212+00:00', Id=84001f7e-6743-4847-ba73-48b597af33fa)
2022-03-18T16:15:16.372 [Information] {
"id": "de252911-9e70-b66f-954a-641d2c508040",
"topic": "/SUBSCRIPTIONS/7965FC25-694A-478C-B4FA-911F94239D30/RESOURCEGROUPS/TMRESOURCEGROUP/PROVIDERS/MICROSOFT.DEVICES/IOTHUBS/TMIOTHUB",
"subject": "devices/SampleDevice",
"eventType": "Microsoft.Devices.DeviceDisconnected",
"data": {
"deviceConnectionStateEventInfo": {
"sequenceNumber": "000000000000000001D80D890755FFF30000004500000000000000000000000B"
},
"hubName": "<IoT Hub Name>",
"deviceId": "SampleDevice"
},
"dataVersion": "",
"metadataVersion": "1",
"eventTime": "2022-03-18T16:14:36.8975903Z"
Once a device is registered, the Hub start polling device status at a rate of about once per minute. So if a device is connected for 5 minutes, you should expect 5 reported connection events. If the device then disconnects for the next 3 minutes, you should expect 3 disconnection events. Because the sample is only taken once per minute, if a device manages to connect and then disconnect within a minute, the reported connection status may never actually report that it was connected. The way it works is documented here: https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-event-grid#limitations-for-device-connected-and-device-disconnected-events

RabbitMQ StompJs recieving just one Message

I'm trying to recieve a Message from the RabbitMq-Que with the Stomp-plugin. This works fine but the Problem is that I get every Message from the Queue. So if the Queue has 13 Messages, I get 13. The Key is that I just want to get 1 Message and after sending Ack or Nack the next one. Do somebody got any Idea how to get only one Message? Thanks for Help.
Here the code I got:
GetMessage()
{
this.GetRabbitMqClient().then((client)=>
{
var headers ={ack:'client', 'x-max-priority': '10'};
var subscription = client.subscribe("/queue/TestQue",this.messageCallback,headers);
});
}
private messageCallback = function(Message :IMessage)
{
console.log(Message.body);
setTimeout(()=> {Message.ack();},100000000000000);
}
private GetRabbitMqClient( ):Promise<Client> {
var promise = new Promise<Client>((resolve,reject)=>{
var client = new Client(
{
brokerURL: "ws://localhost:15674/ws",
connectHeaders:
{
login: "guest",
passcode: "guest"
},
// debug: function (str) {
// console.log(str);
// },
reconnectDelay: 5000,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000
});
client.onConnect = function (frame) {
resolve(client);
};
client.onStompError = function (frame) {
// Will be invoked in case of error encountered at Broker
// Bad login/passcode typically will cause an error
// Complaint brokers will set `message` header with a brief message. Body may contain details.
// Compliant brokers will terminate the connection after any error
reject(frame);
console.log('Broker reported error: ' + frame.headers['message']);
console.log('Additional details: ' + frame.body);
};
client.activate();
});
return promise;
}
I found the solution:
you just need to set in the headers the attribute:
'prefetch-count':'1'

API Automation - Is it possible to get response of the post call

I'm learning how to automate API with frisby.js on gmail.api.
I want to create a test where I create and delete(or send) a Draft message.
So I wrote a test which creates a Draft and my question is - can I write a code that gets at least ID of generated response from my Post call?
var frisby = require('frisby');
frisby.create('Create Draft Google')
.post('https://www.googleapis.com/gmail/v1/users/me/drafts?access_token=*my-token-here*', {
message: {
raw: "RGFuJ3MgVG9vbHMgYXJlIGNvb2wh",
id: "1547265285486966899"
}
}, { json: true })
.inspectJSON()
.inspectBody()
.expectStatus(200)
.toss();
So, to clarify, I want to write another part of THIS^ test with
.after(function(err, res, body){}
Steps:
I create a Draft message
I want my test to automatically get ID of just created Draft
So I could Delete it\Send it
Thanks!
When you create a draft, you will get the id of the newly created draft in the response:
Request
POST https://www.googleapis.com/gmail/v1/users/me/drafts?access_token={access_token}
{
"message": {
"raw": "RnJ..."
}
}
Response
{
"id": "r5019331921817638435",
"message": {
"id": "157948187e41b5bb",
"threadId": "157948187e41b5bb",
"labelIds": [
"DRAFT"
]
}
}
Then you can use this id to either send or delete the message.
.afterJSON(function(json){
callback(json.id);
})
I used this function and it worked. Thanks to my friend for help :D
Here're full tests if someone needs it:
This is how I get an ID of created Draft
var frisby = require('frisby');
var new_id = function(frisby, callback)
{
frisby.create('Create Draft Google')
.post('https://www.googleapis.com/gmail/v1/users/me/drafts?access_token=[my_token]', {
message: {
raw: "RGFu...",
}
}, { json: true })
.inspectJSON()
.inspectBody()
.expectStatus(200)
.afterJSON(function(json){
callback(json.id);
})
.toss();
};
module.exports = new_id;
This is how I used it to delete this Draft
var frisby = require('frisby');
var getid_spec = require("./getid_spec.js");
getid_spec(frisby,function(id){
frisby.create('Delete Google Draft Test')
.delete("https://www.googleapis.com/gmail/v1/users/me/drafts/" +id +"?access_token=[my_token]", {})
.expectStatus(204)
.toss();
})

Google Script button_action fetching error

I am trying to use Sniply API with the following Google Script code, yet i keep receiving an error message. Except the button configuration everything seems to work properly, btw.
The code looks like:
// Main Parmaters
var url = "picky.com"
var message = "This is a text from the Google Spreadsheet API2"
// Button Parameters (Optional)
var button_text = "I am a button2"
var button_url = "mailto:info#picky.com"
var button_background_color = "#000000"
var button_text_color = "#ffffff"
// Button (Optional)
var button_action =
{
"text": button_text,
"url": button_url,
"text_color": button_text_color,
"background_color": button_background_color,
}
var sniply =
{
"button_action": button_action,
"url": url,
"message": message,
}
var options =
{
"method": "post",
"headers" : {
"Authorization" : accesstoken,
},
"payload": sniply,
}
var response = UrlFetchApp.fetch('http://snip.ly/api/snips/', options);
Logger.log(response.getContentText());
The error message, I receive is:
Request failed for http://snip.ly/api/snips/ returned code 400. Truncated server response: {"button_action": [{"non_field_errors": ["Invalid data"]}]} (use muteHttpExceptions option to examine full response)
I would be grateful in case you can help me..
Cheers,
EMG
You are configuring the objects with an extra comma on the end. Try removing the comma:
You have:
var button_action =
{
"text": button_text,
"url": button_url,
"text_color": button_text_color,
"background_color": button_background_color,
}
There is an extra comma at the end of:
"background_color": button_background_color,
That's an incorrect syntax. I'm not saying that is the problem, but I'd start there first.