Activemq concurrency fail in Apache camel route - concurrency

Trying to send multiple requests at same instant to camel activemq route, one request is serviced and the other request is not serviced and sent back as it is. The Jms messages are set with JMScorrelationId too before sending like below
textMessage.setJMSCorrelationID(UUID.randomUUID().toString());
below is my activemq route
from("activemq:queue:TEST_QUEUE?disableReplyTo=true")
.setExchangePattern(ExchangePattern.InOut)
.process(new Processor() {
public void process(Exchange e) throws Exception {
log.info("Request : "
+ MessageHelper.extractBodyAsString(e.getIn()));
/*Processing Logic*/
}
})
.beanRef("testBean","postDetails")
.inOnly("activemq:queue:TEST_QUEUE");
Multiple (Test for 2 requests) requests sent to the above route concurrently not serviced except one. The servicemix.log shows all recieved requests. But only one is serviced.
Below is the code what is sending request deployed in jboss 6.1 as part of web application.
public Message receive(String message, String queueName) {
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(
"tcp://localhost:61616");
String userName = "smx";
String password = "smx";
Connection connection;
Message response =null;
try {
connection = connectionFactory.createConnection(userName, password);
connection.start();
((ActiveMQConnectionFactory) connectionFactory)
.setDispatchAsync(false);
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Queue destination = session.createQueue(queueName);
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
TextMessage textMessage = session.createTextMessage(message);
Queue tempQueue = session.createQueue(queueName);
textMessage.setJMSReplyTo(tempQueue);
producer.send(textMessage);
MessageConsumer consumer = session.createConsumer(tempQueue);
response = consumer.receive();
response.acknowledge();
session.close();
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
return response;
}
Is there some or the other parameter im missing?? please suggest.

Camel will auto send back a reply if the JMS message has a JMSReplyTo header, so your route should just be
from("activemq:queue:TEST_QUEUE")
.process(new Processor() {
public void process(Exchange e) throws Exception {
log.info("Request : "
+ MessageHelper.extractBodyAsString(e.getIn()));
/*Processing Logic*/
}
})
.beanRef("testBean","postDetails");
At the end of the route (eg after calling testBean) then the content of the message body is used as the reply message, that are sent back to the queue named defined in the JMSReplyTo header.

Related

Accessing AWS WebSocket using VertX HttpClient

I have created an API Gateway with a Web Socket on AWS. I would like to connect to it using the HttpClient provided by VertX. I am using the following code for the client verticle:
public class WebSocketClient extends AbstractVerticle {
// application address replaced by [address]
protected final String host = "[address].execute-api.us-east-1.amazonaws.com";
protected final String path = "/dev";
protected final int port = 80;
protected final String webSocketAddress = "wss://[address].execute-api.us-east-1.amazonaws.com/dev";
#Override
public void start() throws Exception {
startClient(this.vertx);
}
protected void startClient(Vertx vertx) {
HttpClient client = vertx.createHttpClient();
client.webSocket(port, host, path, asyncWebSocket -> {
if (asyncWebSocket.succeeded()) {
WebSocket socket = asyncWebSocket.result();
System.out.println("Successfully connected. Node closing.");
socket.close().onFailure(throwable -> {
throwable.printStackTrace();
});
} else {
asyncWebSocket.cause().printStackTrace();
}
});
}
}
The same code works when I am testing it with a VertX server running on the localhost, so I assume that it is a question of the correct WebSocketConnectionOptions.
When I try to connect to the AWS socket using the HttpClient verticle, I get a "connection refused" error. Connecting to it using wscat works without problems.
Thanks a lot for your help.
This question is dealing with basically the same problem. I will post the solution here just to document a straight-forward way to use AWS ApiGateway Websockets with VertX.
So, the goal is to implement a VertX WebClient connected to a deployed AWS Api WebSocket Gateway which can be reached under the WsUri "wss://[address].execute-api.us-east-1.amazonaws.com/dev" (you will have to replace [address] by the address of your ApiGateway Websocket).
Here the code to set up the WebClient, connect to the Websocket, print out a success message, and then disconnect again:
public class WebSocketClient extends AbstractVerticle {
protected final String webSocketUrl = "wss://[address].execute-api.us-east-1.amazonaws.com/dev"
protected final String host = "[address].execute-api.us-east-1.amazonaws.com";
protected final String path = "/dev";
protected final int sslPort = 443;
#Override
public void start() throws Exception {
startClient(this.vertx);
}
protected void startClient(Vertx vertx) {
HttpClient client = vertx
.createHttpClient(new
HttpClientOptions().setDefaultHost(host).setDefaultPort(sslPort).setSsl(true));
// connect to the web socket
client.webSocket(path, asyncWebSocket -> {
if (asyncWebSocket.succeeded()) {
// executed on a successful connection
WebSocket socket = asyncWebSocket.result(); // use this for further communication
System.out.println("Successfully connected. Closing the socket.");
// Closing the socket
socket.close().onFailure(throwable -> {
throwable.printStackTrace();
});
} else {
// executed if the connection attempt fails
asyncWebSocket.cause().printStackTrace();
}
});
}
You can use the following class to run the example:
public class PlayWebSocket {
public static void main(String[] args) throws URISyntaxException{
Vertx vertx = Vertx.vertx();
WebSocketClient clientVerticle = new WebSocketClient();
vertx.deployVerticle(clientVerticle);
}
}
On the Java side, this should print the message about the successful connection and the closing of the socket. On the AWS side, the $connect and the $disconnect methods of the ApiGateway should be called. You can check this in the logs of your handler function(s) using CloudWatch.

com.sun.xml.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:text/html. Is this an error message instead of a SOAP response?

I am consuming SOAP service where sending request to soap url and getting the response. But when i try to connect using WebServiceTemplate getting a nested exception as
com.sun.xml.messaging.saaj.SOAPExceptionImpl: Invalid Content-Type:text/html. Is this an error message instead of a SOAP response?
Below is the code where i am sending the request to soap client
soapClient.sendEmail(request); - From the service to soap client
Below is the soap client code to connect and send the request
#Service
public class SoapClient {
#Autowired
private Jaxb2Marshaller marshaller;
private WebServiceTemplate template;
#Value("${email.url}")
String emailUrl;
#Value("${email.vaultQuery}")
String querytaken;
#Value("${email.valtQu}")
String queryp;
public MessageResponse sendEmail(MessageRequest request) {
template = new WebServiceTemplate(marshaller);
String plainCredentials = querytaken + ":" + queryp;
String base64Credentials = new String(Base64.encodeBase64(plainCredentials.getBytes()));
return (MessageResponse) template.marshalSendAndReceive(emailUrl, request,new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) throws IOException {
TransportContext context = TransportContextHolder.getTransportContext();
HttpUrlConnection connection = (HttpUrlConnection) context.getConnection();
connection.getConnection().setRequestProperty("Authorization", "Basic " + base64Credentials);
}
});
}
}
Can anyone help me out for my issue

AWS Java SDK - Timeout waiting for connection from pool

I am working with AmazonSQS. I am using threads to read content from there, after a short time, I get the connection pool error
this is my thread logic
ReceiveMessageRequest request = new ReceiveMessageRequest(#url);
request.setMaxNumberOfMessages(#getMaxMessagesPolled);
request.setWaitTimeSeconds(5);
while (true) {
List<Message> messages = new ArrayList<>();
try {
messages = awsService.getMessages(parameters, request);
} catch (Exception clientException) {
continue;
}
for (Message message : messages) {
//process
awsService.removeMessage(parameters, message);
} catch (Exception e) {
continue;
}
}
}
error :
com.amazonaws.SdkClientException: Unable to execute HTTP request: Timeout waiting for connection from pool
As I know the default connection pool size is 50. I do not have >50 threads.
Thanks

Multiple websockets in QML

I understand that it's probably a trivial question but maybe someone knows how to handle multiple websocket clients in server-qml. I did not understand from the official documentation of Qt as NOT using the C++ function or webchannel to do it. Is it possible?
I have a websocket client and server in the program. If I connect from js code to html page(from the simplechat example) how do I send a socket inside the QML app and back. How to handle the name of each socket on the server and send to it the desired text. I would appreciate any help.
My current code.
WebSocketServer {
id: server
listen: true
port:1234
onClientConnected: {
webSocket.onTextMessageReceived.connect(function(message) {
appendMessage(qsTr("Server received message: %1").arg(message));
webSocket.sendTextMessage(qsTr("Hello Client!"));
// how to get a list of sockets and an instance of a particular connected socket
});
}
onErrorStringChanged: {
appendMessage(qsTr("Server error: %1").arg(errorString));
}
}
WebSocket {
id: socket
url: server.url
active:true
onTextMessageReceived: appendMessage(qsTr("Client received message: %1").arg(message))
onStatusChanged: {
if (socket.status == WebSocket.Error) {
appendMessage(qsTr("Client error: %1").arg(socket.errorString));
} else if (socket.status == WebSocket.Closed) {
appendMessage(qsTr("Client socket closed."));
}
}
}
The problem is that there is a page with the following code something like a chat client
var wsUri = "ws://localhost:1234";
var websocket = null;
function initWebSocket() {
try {
if (typeof MozWebSocket == 'function')
WebSocket = MozWebSocket;
if ( websocket && websocket.readyState == 1 )
websocket.close();
websocket = new WebSocket( wsUri );
websocket.onopen = function (evt) {
debug("CONNECTED");
};
websocket.onclose = function (evt) {
debug("DISCONNECTED");
};
websocket.onmessage = function (evt) {
console.log( "Message received :", evt.data );
debug( evt.data );
};
websocket.onerror = function (evt) {
debug('ERROR: ' + evt.data);
};
} catch (exception) {
debug('ERROR: ' + exception);
}
}
Its websocket creates client and connects to the server described. When a client connects from a js script, it can send a message to the server and take QML will be displayed in the hearth of the page. When a new client socket inside QML application connects to the server and sents to the alias in the message QML server and can receive messages from the server. But how to do so from the socket in the application message reached the customer at the js and back. To do this, probably it is necessary to the server as a defined desired socket, take the instance
webSocket.sendTextMessage(qsTr("Hello Client!"));
of the socket it is

How to replace response body in WSO2 API Manager 1.10.0 Custom Handler

I have written a CustomHandler which verifies if there is a specific key in the request. If the key is missing, handler should send back response to the client with the text saying that the key is missing. When a get request is sent to the server without key in the header, server responds back to the client with the modified payload. But, when a post request is sent to server, it sends back the original payload sent by the client. Below is the code that sends back response to the client with modified payload.
private void handleAuthenticationFailure(MessageContext messageContext, APISecurityException e){
SOAPBody body = messageContext.getEnvelope().getBody();
for (Iterator itr = body.getChildElements(); itr.hasNext();) {
OMElement child = (OMElement) itr.next();
child.detach();
}
org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).
getAxis2MessageContext();
axis2MC.setProperty(Constants.Configuration.CONTENT_TYPE, "application/xml");
axis2MC.removeProperty("NO_ENTITY_BODY");
axis2MC.setProperty("HTTP_SC", HttpStatus.SC_UNAUTHORIZED);
messageContext.setResponse(true);
messageContext.setProperty("RESPONSE", "true");
messageContext.setTo(null);
messageContext.getEnvelope().getBody().addChild(getFaultPayload(e));
Axis2Sender.sendBack(messageContext);
}
private OMElement getFaultPayload(APISecurityException e) {
OMFactory fac = OMAbstractFactory.getOMFactory();
OMNamespace ns = fac.createOMNamespace(APISecurityConstants.API_SECURITY_NS,
APISecurityConstants.API_SECURITY_NS_PREFIX);
OMElement payload = fac.createOMElement("fault", ns);
OMElement errorCode = fac.createOMElement("code", ns);
errorCode.setText(String.valueOf(e.getErrorCode()));
OMElement errorMessage = fac.createOMElement("message", ns);
errorMessage.setText("Missing Credentials");
OMElement errorDetail = fac.createOMElement("description", ns);
errorDetail.setText(e.getMessage());
payload.addChild(errorCode);
payload.addChild(errorMessage);
payload.addChild(errorDetail);
return payload;
}
Am I missing something ? How do I drop the original payload of the post request and send back the modified payload ? Thanks for any help.
We had a similar requirement: replacing an arbitrary string within the body payload of an HTTP response. We achieved this through custom mediation, but the approach should be equally valid through a handler.
We avoided using XML parsing, construction, and injection by using synapse JsonUtil (org.apache.synapse.commons.json.JsonUtil), specifically String jsonResponse = JsonUtil.jsonPayloadToString(axis2) to read the payload body and JsonUtil.newJsonPayload(axis2, jsonResponse, true, true) to write.
If you require the payload to be in XML, you'll want to look at Utils.setFaultPayload and Utils.sendFault, which can be found in their org.wso2.carbon.apimgt.gateway.handlers package at https://github.com/wso2/carbon-apimgt/blob/master/components/apimgt/org.wso2.carbon.apimgt.gateway/src/main/java/org/wso2/carbon/apimgt/gateway/handlers/Utils.java.
public static void setFaultPayload(MessageContext messageContext, OMElement payload) {
org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).
getAxis2MessageContext();
JsonUtil.removeJsonPayload(axis2MC);
messageContext.getEnvelope().getBody().addChild(payload);
Map headers = (Map) axis2MC.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
String acceptType = (String) headers.get(HttpHeaders.ACCEPT);
//If an Accept header has been provided.
if(!StringUtils.isEmpty(acceptType) && !"*/*".equals(acceptType)){
axis2MC.setProperty(Constants.Configuration.MESSAGE_TYPE, acceptType);
}
}
public static void sendFault(MessageContext messageContext, int status) {
org.apache.axis2.context.MessageContext axis2MC = ((Axis2MessageContext) messageContext).
getAxis2MessageContext();
axis2MC.setProperty(NhttpConstants.HTTP_SC, status);
messageContext.setResponse(true);
messageContext.setProperty("RESPONSE", "true");
messageContext.setTo(null);
axis2MC.removeProperty("NO_ENTITY_BODY");
// Always remove the ContentType - Let the formatter do its thing
axis2MC.removeProperty(Constants.Configuration.CONTENT_TYPE);
Map headers = (Map) axis2MC.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
if (headers != null) {
headers.remove(HttpHeaders.AUTHORIZATION);
headers.remove(HttpHeaders.AUTHORIZATION);
headers.remove(HttpHeaders.HOST);
}
Axis2Sender.sendBack(messageContext);
}