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
Related
I am trying to do the following with Play Framework 2.6:
The browser targets the server and a WebSocket is created
Later on (after some other request is performed), the servers sends a message to the browser via the WebSocket previously created
Point 1 can be easily done with a route:
public WebSocket socket() {
return WebSocket.Text.accept(request -> {
// Log events to the console
Sink<String, ?> in = Sink.foreach(System.out::println);
// Send a single 'Hello!' message and then leave the socket open
Source<String, ?> out = Source.single("Hello!").concat(Source.maybe());
return Flow.fromSinkAndSource(in, out);
});
}
and the WebSocket can be saved server side.
But then how can I send data via the WebSocket? (triggered server side)
This was easy to do with 2.5 but the documentation is not very helpful for Play 2.6.
I've managed to implement websocket with help of Akka actors. At first step define actor that will handle messages
public class WebSocketActor extends AbstractActor {
private final ActorRef out;
#Inject
public WebSocketActor(ActorRef out) {
this.out = out;
}
#Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, message ->
out.tell("Sending message at " + LocalDateTime.now().toString(), self())
)
.build();
}
public static Props props(final ActorRef out) {
return Props.create(WebSocketActor.class, out);
}
}
This actor will be created per client. ActorRef out will send message to connected client. In this example response is send to client on each string message passed to WebSocketActor.
Now define API endpoint to open access to websocket for clients. Define ActorFlow that will create new instance of actor on new connection
public WebSocket ws() {
return WebSocket.Text.accept(request -> ActorFlow.actorRef((out) -> WebSocketActor.props(out), actorSystem, materializer));
}
According to source code ActorFlow creates actors with flowActor name. So to send message to websockets somewhere in the code we can find actors by their path. This will broadcast message to all connected clients
actorSystem.actorSelection("/user/*/flowActor").tell("Hello", ActorRef.noSender());
Unfortunately I didn't find easy way to change ActorFlow default name but maybe this answer may help you play-scala-akka-websockets-change-actor-path.
Also you can check play-java-websocket-example project from playframework examples.
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.
I am new to Atmosphere so I must be missing something simple. I made a sample and can get the #Broadcast to work but not BroadcasterFactory to work. I can trace the onMessage to be hit (via a listener) but I dont see onBroadcast happening unless the #Broadcast is specified. Also, unless I specify the #Broadcast, I dont see the message delivered to the client. My WebSocket code is very basic:
#Path("/chat")
#AtmosphereService(
interceptors = {AtmosphereResourceLifecycleInterceptor.class,
TrackMessageSizeInterceptor.class/*,
BroadcastOnPostAtmosphereInterceptor.class*/}//,
)
public class HelloWorldWS {
#GET
#Produces(MediaType.APPLICATION_JSON)
public SuspendResponse<String> connect(#Context AtmosphereResource res)
{
// eventually this will be done via subscription in the post area
BroadcasterFactory.getDefault().get().addAtmosphereResource(res);
return new SuspendResponse.SuspendResponseBuilder<String>()
//.broadcaster(BroadcasterFactory.getDefault().get())
.outputComments(true)
.addListener(new ResourceListener())
.build();
}
//#Broadcast(writeEntity = false)
#POST
public void broadcast(String message) {
final String msg = String.format("{'author':'fdsa','message':'%s'}", "Override proof");
// Send to all
BroadcasterFactory.getDefault().get().broadcast(msg);
// No Really, send to all
Collection<Broadcaster> broadcasters = BroadcasterFactory.getDefault().lookupAll();
for (Broadcaster b : broadcasters)
{
System.out.println("Broadcaster: " + b.toString() + "; Count: " + b.getAtmosphereResources().size());
for (AtmosphereResource r : b.getAtmosphereResources())
{
System.out.println("Notifying Resource: " + r.toString());
r.write(msg);
}
}
}
}
When I enable the #Broadcast/BroadcastOnPostAtmosphereInterceptor then the message is relayed to the client (my code in the "broadcast" function does nothing then). When I comment out the #Broadcast/BroadcastOnPostAtmosphereInterceptor then I would expect my Broadcast code to deliver the message.
With #Broadcast I show the following ResourceListener callbacks: onPreSuspend, onSuspend, onConnect, onMessage, onBroadcast (client gets it)
When #Broadcast is commented out I show the following ResourceListener callbacks: onPreSuspend, onSuspend, onConnect, onMessage (client never gets message)
What am I doing wrong?
I am using atmosphere 2.1.2 with Jersey 1.17
get rid of AtmosphereResourceLifecycleInterceptor is you use the SuspendResponse API as it may conflict.
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񹹚.
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
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!