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.
Related
I have a problem with delaying messages when sending them to rabbitmq consumer. I have set the x-delay header however the problem is that I want messages to be send at one sec-time distance to the consumer. But in the case of the application with this code, they are all sent at the same time but after 1 sec of starting the application. So how can I send them gradually with 1 sec time difference between each other?
public void produce(Company company){
// for (Company company:
// companies) {
amqpTemplate.convertAndSend(exchange, routingkey, company, new MessagePostProcessor() {
#Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setHeader("x-delay",10000);
return message;
}
});
System.out.println("Send msg = " + company);
// }
// amqpTemplate.convertAndSend(exchange, routingkey, company);
}
In the main application I'm calling the produce method for each company from company list (also tried with for inside produce method, didn't work).
I am trying to update my Code from pubnub sdk v3 to v4 and I am stuck at callbacks.
I have following function which I would like to update:
void transmitMessage(String toID, JSONObject packet){
if (this.id==null){ .
mRtcListener.onDebug(new PnRTCMessage("Cannot transmit before calling Client.connect"));
}
try {
JSONObject message = new JSONObject();
message.put(PnRTCMessage.JSON_PACKET, packet);
message.put(PnRTCMessage.JSON_ID, "");
message.put(PnRTCMessage.JSON_NUMBER, this.id);
this.mPubNub.publish(toID, message, new Callback() {
#Override
public void successCallback(String channel, Object message, String timetoken) {
mRtcListener.onDebug(new PnRTCMessage((JSONObject)message));
}
#Override
public void errorCallback(String channel, PubNubError error) {
mRtcListener.onDebug(new PnRTCMessage(error.errorObject));
}
});
} catch (JSONException e){
e.printStackTrace();
}
}
The docs say one does not Need to instantiate com.pubnub.api.Callback and one should use the new SubscribeCallback class. I am not sure how to handle it, the SubscribeCallback contains These Methods: Status, message and presence, currently I have a successCallback method and a errorCallback.
The code at https://www.pubnub.com/docs/android-java/api-reference-publish-and-subscribe#listeners should help you with this.
You can create listeners using the code below:
pubnub.addListener(new SubscribeCallback() {
#Override
public void status(PubNub pubnub, PNStatus status) {
switch (status.getOperation()) {
// let's combine unsubscribe and subscribe handling for ease of use
case PNSubscribeOperation:
case PNUnsubscribeOperation:
// note: subscribe statuses never have traditional
// errors, they just have categories to represent the
// different issues or successes that occur as part of subscribe
switch (status.getCategory()) {
case PNConnectedCategory:
// this is expected for a subscribe, this means there is no error or issue whatsoever
case PNReconnectedCategory:
// this usually occurs if subscribe temporarily fails but reconnects. This means
// there was an error but there is no longer any issue
case PNDisconnectedCategory:
// this is the expected category for an unsubscribe. This means there
// was no error in unsubscribing from everything
case PNUnexpectedDisconnectCategory:
// this is usually an issue with the internet connection, this is an error, handle appropriately
case PNAccessDeniedCategory:
// this means that PAM does allow this client to subscribe to this
// channel and channel group configuration. This is another explicit error
default:
// More errors can be directly specified by creating explicit cases for other
// error categories of `PNStatusCategory` such as `PNTimeoutCategory` or `PNMalformedFilterExpressionCategory` or `PNDecryptionErrorCategory`
}
case PNHeartbeatOperation:
// heartbeat operations can in fact have errors, so it is important to check first for an error.
// For more information on how to configure heartbeat notifications through the status
// PNObjectEventListener callback, consult <link to the PNCONFIGURATION heartbeart config>
if (status.isError()) {
// There was an error with the heartbeat operation, handle here
} else {
// heartbeat operation was successful
}
default: {
// Encountered unknown status type
}
}
}
#Override
public void message(PubNub pubnub, PNMessageResult message) {
String messagePublisher = message.getPublisher();
System.out.println("Message publisher: " + messagePublisher);
System.out.println("Message Payload: " + message.getMessage());
System.out.println("Message Subscription: " + message.getSubscription());
System.out.println("Message Channel: " + message.getChannel());
System.out.println("Message timetoken: " + message.getTimetoken());
}
#Override
public void presence(PubNub pubnub, PNPresenceEventResult presence) {
}
});
Once you've subscribed to a channel like below, when a message or presence event is received the above listeners will be called.
pubnub.subscribe()
.channels(Arrays.asList("my_channel")) // subscribe to channels
.withPresence() // also subscribe to related presence information
.execute();
Please note that we have recently launched new features with new types of listeners as well, all of which are listed in the link above.
Getting Unirest Config exception when I use java with Unirest API to call the web service asynchronous way. It is working as expected in the sync method.
I am writing a Java code for Apache Spark to call REST API.
Future> future = ui.post("http://x.x.x.x:x/xwa/evalrules").body(Str).asStringAsync(
new Callback() {
public void failed(UnirestException e) {
System.out.println("JTX Failed Get message"+ e.getMessage());
}
public void completed(HttpResponse<String> resp) {
System.out.println(new Date() + " Consumer JTXX recvd response -> " + resp.getStatus() + "/" + resp.getBody());
//out_JSON=resp.body();
}
public void cancelled() {
System.out.println("The request has been cancelled JTX");
}
});
Expected: It is working as expected for first few calls. post that it is failing. I suspected the timeout so i have already disabled using approach.
Config c = Unirest.config().socketTimeout(0).connectTimeout(0).concurrency(10, 8);
UnirestInstance ui = new UnirestInstance(c);
Error Message:
kong.unirest.UnirestConfigException: Http Clients are already built in order to build a new config execute Unirest.config().reset() before changing settings.
This should be done rarely.
Any suggestions on how to resolve this will be highly appreciated. Thanks.
Muthu
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 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