How to add alternate exchange while defining binding url? - jms

I need to create queue on application start and should delete when application stop. Also messages need to reroute to alternate exchange on application shutdown. How can we add alternate exchange option in the Binding URL? I am using Java Qpid client 6.1.0 and JMS 1.1.
Binding URL:
topic://ToApp.Ex/test.queue?routingkey='#.am.#'&durable='false'&autodelete='true'&exclusive='false'

I able to create a queue and connect to alternate exchange using address string.
address string is as below.
queue.name;{assert: always, node:{x-declare: {alternate-exchange: 'Forwarder.Ex', auto-delete:True }, x-bindings: [{ exchange: 'ToApp.Ex', key: '#.am.#' }], type: queue }, create: always, delete: always}
Thanks

Related

setting ack to client results in duplicate message delivery stomp

I have a stomp application and I set the ack mode to client during subscription from front-end. During the subscription the same client during a session would connect to the same queue in the message broker ActiveMQ Artemis because a session id is used for queue.But a different id is passed in the header every time the user reloads the page.
The subscription code is shown below.
consumer.subscribe(
'/queue.'+ rscSessionId,
function (response) {
console.log("resposne");
},
{
"subscription-type": "ANYCAST",
ack: "client",
id: generateId(),
}
);
Once I send message from client it gets send to frontend with following headers.
MESSAGE
subscription:1234
message-id:1543449
destination:/queue.sessionid
expires:1653914606725
redelivered:false
priority:4
persistent:true
timestamp:1653912806717
destination-type:ANYCAST
__AMQ_CID:30e64793-dd9b-11ec-8843-c238460c3152
_type:ResponseData
content-length:300
and afterwards on every reload.
MESSAGE
subscription:1235
message-id:1543449
destination:/queue.sessionid
expires:1653914606725
redelivered:true
priority:4
persistent:true
timestamp:1653912806717
destination-type:ANYCAST
__AMQ_CID:30e64793-dd9b-11ec-8843-c238460c3152
_type:ResponseData
content-length:300
You can see that redelivered is set to true after first delivery and after that every response has redelivered to false. the subscription value keeps getting changed though because of the id passed in header.
How can I make it deliver only once but with guarantee?
Are you actually acknowledging the message once you receive it? If you don't acknowledge the message then once the client closes the connection and subscribes again it will receive the same message again. The different value you're seeing for the subscription header indicates this is what is happening.
To be clear, if you're using the client acknowledgement mode then once you receive the MESSAGE frame you need to send a corresponding ACK frame in order to acknowledge the message. Your client should have a way to do this since it is a standard part of the STOMP specification.
I guess that Artemis is configured with publisher/subscriber messaging style. In this case, every new consumer/receiver/client will get the messages aka you write/read from a topic.
Changing to a point-to-point message style would fix the issue (would only be read once) aka a queue.
This is usually decided by the setup but I recall that ActiveMQ allowed producer to create those on the fly.
If you do need a topic, then you will have to handle the IDs on the client side.

API Gateway WebSocket API postConnection timeout

I'm trying to set up a WebSocket API on API Gateway. I'm following the basic tutorial, and I have everything up and running -> Routes for $connect, $disconnect, "test", $default. I am able to connect to the API, store the connectionId in Redis, and retrieve it when accessing from the test route.
The problem is when I try to send back a message from my lambda (single lambda handling all routes). I'm using the following code
const apigwManagementApi = new AWS.ApiGatewayManagementApi({
apiVersion: '2018-11-29',
endpoint: `https://${event.requestContext.domainName}/${event.requestContext.stage}`
});
Then I call
await apigwManagementApi.postToConnection({
ConnectionId: connectionId,
Data: `Echo: ${data}`
}).promise()
This is only called on the "test" route.
All of this is as per their guide. I had to add a patch to be able to make postConnection work, again, as per their tutorial. The problem is when the above method is called I get a Internal Server Error message from the API Gateway and the lambda times out after 3 seconds.
There is very little info on this method. I'm not sure what is causing the internal server error. I have checked the endpoint and the connectionId, both are correct.
What am I doing wrong? Any suggestions?
So the problem wasn't the actual lambda but the fact that it wasn't set up in a VPC that had access to the Internet. So if you're lambda has VPC enabled, make sure you it has a NAT gateway and Internet gateway set up.

Validate exchange, routing key when publishing message using Spring RabbitMessagingTemplate

Is there a way to validate that the exchange and routing key/queue when sending message using RabbitMessagingTemplate? Currently, there is a default exchange and routing key which blank string and there's no error being thrown.
messagingTemplate.convertAndSend(message.getExchange(), message.getRoutingKey(), message.getPayload());
Please, see Returns and Confirms callback: https://docs.spring.io/spring-amqp/docs/2.1.2.RELEASE/reference/html/_reference.html#template-confirms. So, if there is anything wrong with exchange or queue on the routing key, you’re going to have message returned with an error

Invoke worklight SQL adapter procedure using AJAX

Can someone give an example of how to invoke and receive a response from an SQL adapter in worklight using AJAX call? I'm using worklight 6.0
I have security at the app level. I need to invoke a procedure that doesn't need authentication (example: Registering an account) and hence need to invoke the adapter using AJAX
This is my adapter:
var invocationData = {
adapter : 'UserInfo',
procedure : 'addUserInfo',
parameters : [ customerData.firstName,
customerData.lastName, customerData.email,
customerData.province, customerData.zipPostal,
customerData.phoneNumber, customerData.streetName,
customerData.streetNumber, customerData.country,
customerData.city ]
};
WL.Client.invokeProcedure(invocationData, {
onSuccess : insertUserSuccess,
onFailure : insertUserFailure
});
My understanding is that you just want to invoke an Adapter procedure using Ajax from some client.
Is it the same as this other question ?
Calling Worklight adapter from external app
You can check the details of the HTTP API here
http://www-01.ibm.com/support/knowledgecenter/SSZH4A_6.0.0/com.ibm.worklight.help.doc/admin/r_http_interface_of_the_prod_server.html?lang=en
Update:
Also note that if you have any security tests configured, different than "wl_unprotected" (your adapter is 100% public with that, be careful!!) you may need extra steps to handle authentication.
If you have a default adapter, without any security test set, you may receive a 401 unauthorized in your first request, and in the body of the 401 you may find a WL-Instance-ID property, that you must send together with a new request to get authorized to use it.
Update 2:
Worklight/MobileFirst Platform doesn't enable CORS (so you can't "naturally" call adapters using ajax from an external web page). It may be possible to workaround that by using a gateway (IHS maybe) that adds the header "Access-Control-Allow-Origin" to all adapter responses. Note that you are handling a security thing, so make sure you know what you are doing.
Worklight (6.3 and below) adapters can work only with the Worklight Server.
If you plan on using Worklight adapters, you are required to use the API as provided by the Worklight framework - the code mentioned in the question.
You can still use regular AJAX requests - but those won't/cannot be requests sent to/by the Worklight adapter.
WLJQ.ajax( "some-URL" )
.done(function (data) {
console.log(data);
});
If the destination does require going through the Worklight Server, and it is not protected by any realm, what is the problem then? Send the request.
Perhaps you should not protect the app at the environment level but rather at the procedure level (set the security test on the adapter procedure in the adapter XML and not on the environment in application-descriptor.xml).
Perhaps you need to better explain your specific scenario...

STOMP Messages not reaching queue

I am trying to send a message that the client inputs into the browser to a queue using STOMP and ActiveMQ. The STOMP connection is successful from the readouts I get in the console. I am not receiving errors and am using the line:
stompClient.send("/queue/testQSource", {}, JSON.stringify({ 'name': name }));
in my index.html to do so. However, when I check the ActiveMQ console after inputting into the browser, there is no addition to testQSource. Am I using the correct STOMP syntax to make this happen? Do I need to add any sources at the top of the HTML file other than the STOMP source?
The queue is instantiated here in the camel route:
<from uri="jms:queue:testQSource"/>
<to uri="securityBean"/>
<log message="Routing message from testQSource to testQDestination queue with data ${body}"/>
<to uri="jms:queue:testQDestination"/>
<to uri="activationBean"/>
<log message="message: ${body}"/>
EDIT
I am now getting a message through, but am receiving the following warning:
WARN : org.apache.camel.component.jms.JmsBinding - Cannot determine specific JmsMessage type to use from body class. Will use generic JmsMessage. Body class: hello.HelloMessage. If you want to send a POJO then your class might need to implement java.io.Serializable, or you can force a specific type by setting the jmsMessageType option on the JMS endpoint.
I believe this is because the STOMP message is of a different form than the queue and/or route are expecting. However, I am not sure how to configure my route in a way that will allow me to use my STOMP message. Any tips?
It's a bit tough to say without more information but my first guess is that the stomp client connection is being closed before the message gets a chance to be written to the socket or read by ActiveMQ. You might want to consider doing a blocking put to the queue by adding a request id to the out-bound frame and wait for the Broker to send you a response frame. This will ensure that your message is posted prior to the connection being closed.
How you perform the blocking put depends on the client you are using so you need to review the documentation to see what the correct means of doing so is. Usually there is either a sync send method or the client adds the 'receipt' header to the frame and then doing a blocking receive until you get back a RECEIPT frame with the correctly matching 'receipt-id' header.
Are you connecting on the stomp port on the ActiveMQ server ?
As seen in the config (activemq.xml) under "transportConnector"
stomp needs to connect on port 61613 on a default configuration.
Using Node.js with "stomp-client" and a default ActiveMQ server on localhost:
var my_client = new Stomp('127.0.0.1', 61613, 'admin', 'admin');

Resources