Accessing AWS WebSocket using VertX HttpClient - amazon-web-services

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.

Related

I can't receive the full image using a server Flask and Okhttp

I'm trying to make an app which sends a image to a server, it transforms the image and it return to the app. But when the app receive the image, only receive a part of it. I did a web with flask and I saw that it send well the picture, and I used Okhttp to download a picture from Internet I don't have any problem.
To send the picture from server I've used:
return flask.send_from_directory('path') and return flask.send_file(...)
To send and receive the picture in the client I've used:
void postRequest(String postUrl, RequestBody postBody) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(postUrl)
.post(postBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
// Cancel the post on failure.
call.cancel();
Log.d("FAIL", e.getMessage());
// In order to access the TextView inside the UI thread, the code is executed inside runOnUiThread()
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView responseText = findViewById(R.id.responseText);
responseText.setText(R.string.ip_failure);
}
});
}
#Override
public void onResponse(Call call, final Response response) throws IOException {
// In order to access the TextView inside the UI thread, the code is executed inside runOnUiThread()
runOnUiThread(new Runnable() {
#Override
public void run() {
TextView responseText = findViewById(R.id.responseText);
responseText.setText("");
try {
Bitmap imagenGAN;
imagenGAN = BitmapFactory.decodeStream(response.body().byteStream());
ImageView imagen = findViewById(R.id.imageView);
imagen.setImageBitmap(imagenGAN);
SaveImage(imagenGAN);
}catch(Exception e){
}
}
});
}
});
}
Example of the received image:
I don't know why I don't receive the full image. Can someone help me?

How can i solve proxy problem when using AWS device farm?

I'm trying to execute aws device farm example code that we can get below site.
https://docs.aws.amazon.com/devicefarm/latest/testgrid/getting-started-local.html
// Import the AWS SDK for Java 2.x Device Farm client:
...
// in your tests ...
public class MyTests {
// ... When you set up your test suite
private static RemoteWebDriver driver;
#Before
void setUp() {
String myProjectARN = "...";
DeviceFarmClient client = DeviceFarmClient.builder().region(Region.US_WEST_2).build();
CreateTestGridUrlRequest request = CreateTestGridUrlRequest.builder()
.expiresInSeconds(300)
.projectArn(myProjectARN)
.build();
CreateTestGridUrlResponse response = client.createTest.GridUrl(request);
URL testGridUrl = new URL(response.url());
// You can now pass this URL into RemoteWebDriver.
WebDriver driver = new RemoteWebDriver(testGridUrl, DesiredCapabilities.firefox());
}
#After
void tearDown() {
// make sure to close your WebDriver:
driver.quit();
}
}
After executing above codes, the error was occurred and the message is like this.
java.net.UnknownHostException: devicefarm.us-westt-2.amazonaws.com
I guess the code can't resolve host because of proxy server.
How can i resolve this problem?
Thanks.
Can you please confirm which line throws java.net.UnknownHostException: devicefarm.us-westt-2.amazonaws.com. Is it client.createTest.GridUrl(request) or WebDriver driver = new RemoteWebDriver(testGridUrl, DesiredCapabilities.firefox());
If it is the client.createTest.GridUrl(request), then please follow Proxy Configuration mentioned at https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/section-client-configuration.html
My current setUp method is like this.
#Before
public void setUp() {
try {
ProxyConfiguration.Builder proxyConfig = ProxyConfiguration.builder();
proxyConfig.endpoint(new URI("<YOUR PROXY URL>"));
proxyConfig.username("<YOUR USER ID>");
proxyConfig.password("YOUR PASSWORD");
ApacheHttpClient.Builder httpClientBuilder =
ApacheHttpClient.builder()
.proxyConfiguration(proxyConfig.build());
String myARN = "<YOUR ARN>";
DeviceFarmClient client = DeviceFarmClient.builder()
.credentialsProvider(DefaultCredentialsProvider.create())
.region(Region.US_WEST_2)
.httpClientBuilder(httpClientBuilder)
.overrideConfiguration(ClientOverrideConfiguration.builder().build())
.build();
CreateTestGridUrlRequest request = CreateTestGridUrlRequest.builder()
.expiresInSeconds(300) // 5 minutes
.projectArn(myARN)
.build();
URL testGridUrl = null;
CreateTestGridUrlResponse response = client.createTestGridUrl(request);
testGridUrl = new URL(response.url());
driver = new RemoteWebDriver(testGridUrl, DesiredCapabilities.chrome());
} catch (Exception e) {
e.printStackTrace();
}
}
Thank you again.

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

Vertx Websocket: Connection Refused Error on AWS

I have written a simple Websocket application that has a server verticle and a client verticle. It runs perfectly fine on my local Windows system (Eclipse). The problem starts when it is deployed on AWS EC2(Ubuntu). While the server verticle seemingly has no problem and listens on the assigned port, when the Websocket client verticle, running on the same system attempts to connect to the server, it gets a connection refused message from the server.
I even checked connecting to the Websocket from an external system through a browser - even that fails to connect.
However, when I run an Http Server verticle on the same machine, I have no problem connecting to it and receiving message from the server.
I have enabled all incoming traffic on all ports of the AWS instance. What is going wrong? Please help.
Here is the code:
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.ServerWebSocket;
import io.vertx.core.http.WebSocket;
public class WebSocketServerApp {
public static void main(String[] args) {
Vertx vertx = Vertx.vertx();
vertx.deployVerticle(new WebSocketServerVerticle());
vertx.deployVerticle(new WebSocketClientVerticle("A"));
}
}
class WebSocketServerVerticle extends AbstractVerticle {
#Override
public void start(Future<Void> startFuture) {
HttpServer httpServer = vertx.createHttpServer();
httpServer.websocketHandler(new Handler<ServerWebSocket>() {
#Override
public void handle(ServerWebSocket event) {
System.out.println("Request received: " +event.binaryHandlerID());
event.writeTextMessage("Message from WS server");
}
}).listen(9999);
}
}
class WebSocketClientVerticle extends AbstractVerticle {
String name;
public WebSocketClientVerticle(String name) {
this.name = name;
}
#Override
public void start(Future<Void> startFuture) {
HttpClient client = vertx.createHttpClient();
client.websocket(9999, "localhost", "", new Handler<WebSocket>() {
#Override
public void handle(WebSocket ws) {
System.out.println("WS Client: "+ ws.textMessageHandler(msg-> System.out.println("Received: "+msg)));
}
});
}
}
Put a sleep between the two verticle deployments.
Client verticle might be becoming up quicker than the server verticle becoming up.

Activemq concurrency fail in Apache camel route

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.