How to use Jawampa (Java WAMP implementation) to subcribe to an event - java

i want to use the poloniex API. https://poloniex.com/support/api/
So far i made Jawampa ( https://github.com/Matthias247/jawampa ) running with IntelliJ.
My first Question is, how to login successfuly? (The Docu of Jawampa doesnt help)
I got a API Key and a Secret. Which functions i have to use in the builder of Jawampa:
withRealm
withRoles
withConnectorProvider
withConnectionConfiguration
withSerializations
withStrictUriValidation
withAuthId
withAuthMethod
withObjectMapper
I have so far this code
try {
WampClientBuilder builder = new WampClientBuilder();
builder.withConnectorProvider(connectorProvider)
.withUri("wss://api.poloniex.com")
.withAuthId("APIKEY")
.withRealm("realm2")
.withInfiniteReconnects()
.withReconnectInterval(1, TimeUnit.SECONDS);
client1 = builder.build();
} catch (Exception e) {
e.printStackTrace();
return;
}
Is wss://api.poloniex.com correct or should i use wss://api.poloniex.com/returnTicker for that client?
Do I have to make always a new client for every URI?
Thank you so much in advance.

My first Question is, how to login successfuly?
You don't have to authenticate to access Poloniex Push API via WAMP protocol. Push API methods are public, so you don't have to supply the API key and secret. Just connect to wss://api.poloniex.com and subscribe to a desired feed (Ticker, Order Book and Trades, Trollbox).
Btw, you need to supply the API Key only with Trading API methods. And the Secret is used to sign a POST data.
Which functions i have to use in the builder of Jawampa:
This is how you connect to the Push API:
WampClient client;
try {
WampClientBuilder builder = new WampClientBuilder();
IWampConnectorProvider connectorProvider = new NettyWampClientConnectorProvider();
builder.withConnectorProvider(connectorProvider)
.withUri("wss://api.poloniex.com")
.withRealm("realm1")
.withInfiniteReconnects()
.withReconnectInterval(5, TimeUnit.SECONDS);
client = builder.build();
} catch (Exception e) {
return;
}
Once your client is connected, you subscribe to a feed like this:
client.statusChanged().subscribe(new Action1<WampClient.State>() {
#Override
public void call(WampClient.State t1) {
if (t1 instanceof WampClient.ConnectedState) {
subscription = client.makeSubscription("trollbox")
.subscribe((s) -> { System.out.println(s.arguments()); }
}
}
});
client.open();
Is wss://api.poloniex.com correct or should i use
wss://api.poloniex.com/returnTicker for that client?
wss://api.poloniex.com is correct. Besides, returnTicker belongs to the Public API and is accessed via HTTP GET requests.
Do I have to make always a new client for every URI?
In respect to the Push API, once you connected a client to wss://api.poloniex.com, you can use this client to make subscriptions to multiple feeds. For example:
client.statusChanged().subscribe(new Action1<WampClient.State>() {
#Override
public void call(WampClient.State t1) {
if (t1 instanceof WampClient.ConnectedState) {
client.makeSubscription("trollbox")
.subscribe((s) -> { System.out.println(s.arguments()); });
client.makeSubscription("ticker")
.subscribe((s) -> { System.out.println(s.arguments()); });
}
}
});
However, according to Jawampa Docs:
After a WampClient was closed it can not be reopened again. Instead of this a new instance of the WampClient should be created if necessary.

Related

Program to make the Java client wait until receiving a response from the server

Currently, I am developing a simple WebRTC application, in which the client and server communicate with each other through RPC. Because of its blocking nature, in essence, meaning if I have a request and send it to the server, I need to wait till I receive the response. I have trouble how to make a client wait till receiving a response from the server then move on. Initially, I did some things like Thread.sleep(), or using ExecutorService and CountDownLatch, they are working, but the responsive of the program is really downgraded, and I have no idea how long the client should sleep for a response from the server. I want to use CompleableFuture in this case, but I still don't have any idea how can I use this in my context, any help is much appreciated!
Here is the client code:
#Override
public CompletableFuture<SessionDescription> join(String sid, String uid, SessionDescription offer) {
String uuid = UUID.randomUUID().toString();
JsonRpcRequestMessage rpcMsg = new JsonRpcRequestMessage();
rpcMsg.setJsonrpc("2.0");
rpcMsg.setId(uuid);
rpcMsg.setMethod("join");
Map<String, Object> params = new HashMap<>();
params.put("offer", offer);
params.put("sid", sid);
params.put("uid", uid);
rpcMsg.setParams(params);
try {
String rpcText = objectMapper.writeValueAsString(rpcMsg);
webSocket.send(rpcText); // here the client sends a text message to the server, then immediately it has to wait to receive a response from the server
// should I use Thread.sleep(n), or something?
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// here I need to return whatever server responses when I send the text above.
}
You could disable the client's view, then create a CompletableFuture by the (delayed) server-response and eventually enable the client's view again, when the CompletableFeature is done.
So your method would look similiar to the following:
#Override
public CompletableFuture<SessionDescription> join(String sid, String uid, SessionDescription offer) {
return CompletableFuture.supplyAsync(() => {
String uuid = UUID.randomUUID().toString();
JsonRpcRequestMessage rpcMsg = new JsonRpcRequestMessage();
rpcMsg.setJsonrpc("2.0");
rpcMsg.setId(uuid);
rpcMsg.setMethod("join");
Map<String, Object> params = new HashMap<>();
params.put("offer", offer);
params.put("sid", sid);
params.put("uid", uid);
rpcMsg.setParams(params);
try {
String rpcText = objectMapper.writeValueAsString(rpcMsg);
webSocket.send(rpcText);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// return the server-response here.
});
}
and you would disable the client's view before calling it and enable it when the CompletableFuture is done:
// disable the view here
join(sid, uid, offer).thenAccept((serverResponse)=>{
// enable the view here
});
This way you don't need to check for Future-Completion manually since you tell Java what to do when the Future is done.

AWS API Gateway WebSocket Timeout?

How do I keep an API Gateway Websocket API with a Lambda Java back end from timing out after 30 seconds?
The AWS API Gateway and re:invent videos mention using pings or heartbeats to keep the Websocket connection alive but I haven't found a straight-forward working example (in Java). The front end is using HTML 5 Websockets (vanilla javascript).
I'm including my Lambda test driver in Java. It causes the API Gateway WS API to timeout after 30 seconds as documented. The driver will return successfully if you remove the delay. Any help is appreciated...
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
public class TestWSClient implements RequestStreamHandler {
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) {
try {
//
// How do we keep API Gateway from timing out after 30 seconds?
// Is something like this even needed in the lambda?
//
new Thread(() -> {
while(true) {
try {
// Ping client every 15 seconds
Thread.sleep(15000);
//outputStream.write(); // What to write -- 0x89 0x00?
outputStream.flush();
} catch(Exception e) { e.printStackTrace(); }
}
}).start();
//
// Simulate long processing time or streaming
//
// NOTE: commenting sleep enables service to return w/o a timeout
// connection from API Gateway
//
try { Thread.sleep(60000); } catch(Exception e) {}
var response = Map.of(
"statusCode", 200,
"headers", Map.of("Content-Type", "text/csv"),
"body", "Hello,World"
);
ObjectMapper om = new ObjectMapper();
outputStream.write(om.writeValueAsBytes(response));
outputStream.flush();
} catch(Exception e) { e.printStackTrace(); }
finally { try { outputStream.close(); } catch(Exception e) {} }
}
}
I do not think I understand your problem correctly but here is how WebSocket API work in my experience.
client(s) <-(1)-> API Gateway <-(2)-> Lambda
1) is the web socket connection which stays open for a maximum of 2 hours, with idle timeout of 10 minutes as mentioned here. https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html
2 )communication is managed using #connection https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-how-to-call-websocket-api-connections.html
I believe you want to use #connection for talking to your API Gateway from lambda.
It looks like a NAT Gateway is required for a Lambda to call the postToConnection function provided by the AWS ApiGatewayManagementApi SDK.
Its a shame this requirement isn't specified anywhere regarding Websockets API or API Gateway.
Search for 'NAT' on this page, and read that sentence:

How to stop streaming in the publish method of Wowza server

I need to stop publishing the stream in the publish() method and send the client a message such as "This name is incorrect, choose another."
I've looked at sendClientOnErrorStatus() but haven't found any examples showing how to handle it on the client side.
Also, can anyone explain what the sendResult(..) method does?
sendClientOnErrorStatus() and sendResult() only work in a Flash context.
sendClientOnErrorStatus()
On the Wowza server you can override the publish and releaseStream (for streams being published) methods and do something like:
sendClientOnStatusError(client, "NetStream.Publish.Denied", "Stream name is invalid: " + streamName);
On a Flash client using ActionScript you would add a NetStatusEvent listener:
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
private function netStatusHandler(event:NetStatusEvent):void {
switch (event.info.code) {
// do something with the event.info
}
}
sendResult()
This is used to send the result for a NetConnection.call which calls a custom method on the Wowza server.
Example:
Wowza server:
public void someMethod(IClient client, RequestFunction function,
AMFDataList params) {
{
sendResult(client, params, "response");
}
Client:
nc = new NetConnection();
nc.call("someMethod",new Responder(function(data:String):void {
trace(data);
})
);
Source: AS3 Reference

What can be the best approach to handle java.net.UnknownHostException for AWS users?

My application sends message to Amazon Simple Notification Service (SNS) topic but sometime (6/10) I get java.net.UnknownHostException:sqs.ap-southeast-1.amazonaws.com. The reason of exception is described in the amazon web services discussion forums, please look: https://forums.aws.amazon.com/thread.jspa?messageID=499290&#499290.
My problem is similar to what described in forums of amazon but my rate of publishing messages to topic is very dynamic. It can be 1 message/second or 1 message/minute or no message in an hour. I am looking for a cleaner, better and safe approach, which guaranties sending of message to SNS topic.
Description of problem in detail:
Topic_Arn= arn of SNS topic where application wants to publish message
msg = Message to send in topic
// Just a sample example which publish message to Amazon SNS topic
class SimpleNotificationService {
AmazonSNSClient mSnsClient = null;
static {
createSnsClient()
}
private void static createSnsClient() {
Region region = Region.getRegion(Regions.AP_SOUTHEAST_1);
AWSCredentials credentials = new
BasicAWSCredentials(AwsPropertyLoader.getInstance().getAccessKey(),
AwsPropertyLoader.getInstance().getSecretKey());
mSqsClient = new AmazonSQSClient(credentials);
mSqsClient.setRegion(region);
}
public void static publishMessage(String Topic_Arn, String msg) {
PublishRequest req = new PublishRequest(Topic_Arn, msg);
mSnsClient.publish(req);
}
}
class which calls SimpleNotificationService
class MessagingManager {
public void sendMessage(String message) {
String topic_arn = "arn:of:amazon:sns:topic";
SimpleNotificationService.publishMessage(topic_arn, message);
}
}
Please note that this is a sample code, not my actual code. Here can be class design issue but please ignore those if they are not related to problem.
My thought process says to have try-catch block inside sendMessage, so when we catch UnknownHostException then again retry but I am not sure how to write this in safer, cleaner and better way.
So MessagingManager class will look something like this:
class MessagingManager {
public void sendMessage(String message) {
String topic_arn = "arn:of:amazon:sns:topic";
try {
SimpleNotificationService.publishMessage(topic_arn, message);
} catch (UnknownHostException uhe) {
// I need to catch AmazonClientException as aws throws
//AmazonClientException when sees UnknownHostException.
// I am mentioning UnknownHostException for non-aws user to understand
// my problem in better way.
sendMessage(message); // Isn't unsafe? - may falls into infinite loop
}
}
}
I am open for answers like this: java.net.UnknownHostException: Invalid hostname for server: local but my concern is to dependent on solution at application code-level and less dependent on changes to machine. As my server application is going to run in many boxes (developer boxes, testing boxes or production boxes). If changes in machine host-files or etc is only guaranted solution then I prefer that to include with code level changes.
Each AWS SDK implements automatic retry logic. The AWS SDK for Java automatically retries requests, and you can configure the retry settings using the ClientConfiguration class.
Below is the sample example to create SNS client. It retries for 25 times if encounters UnKnownHostException. It uses default BackOff and retry strategy. If you want to have your own then you need to implement these two interfaces: http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/retry/RetryPolicy.html
private void static createSnsClient() {
Region region = Region.getRegion(Regions.AP_SOUTHEAST_1);
AWSCredentials credentials = new
BasicAWSCredentials(AwsPropertyLoader.getInstance().getAccessKey(),
AwsPropertyLoader.getInstance().getSecretKey());
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setMaxErrorRetry(25);
clientConfiguration.setRetryPolicy(new RetryPolicy(null, null, 25, true));
mSnsClient = new AmazonSNSClient(credentials, clientConfiguration);
mSnsClient.setRegion(region);
}
Have you considering looking into the JVM TTL for the DNS Cache?
http://docs.aws.amazon.com/AWSSdkDocsJava/latest//DeveloperGuide/java-dg-jvm-ttl.html

data cache for odata4j

I am implementing a RESTlet service via odata4j on Android.
When running the application there is a constant flow of data, which needs to be sent to a odata server.
The following method get's the new data:
private void freshData(Data data) {
try {
dataTransmitter.sendData(data, this.ptId);
} catch (Exception ex) {
//
}
The following method sends the data to the server:
ODataJerseyConsumer c = ODataJerseyConsumer.create(serviceUrl);
public void sendData(Data data, int ptId) throws Exception {
OEntity newData = c.createEntity(entitySet)
.properties(OProperties.int32("ptID", ptID),
OProperties.double_("data", data.getDouble())))
.execute;
So far no problem. But what if the mobile connection is cut off or lags?
1) Is there way to get the status from execute() (positive send, or no mobile connection for instance).
2) If the send has failed, or is still in progress I somehow need to store the new data to send it, when the old data is out. Is there a feature in odata4j (0.8-SNAPSHOT) available I haven't found, or do I need to do this with a queue for example?
Thank you for the help!

Categories

Resources