I am implementing he ENPush in Android app. It is working fine I am able to receive the notifications also. But sometime I am getting following error:-
com.ibm.cloud.eventnotifications.destination.android.ENPushException: Unable to retrieve deviceToken after maximum retries
ENPush enPush = ENPush.getInstance();
enPush.setCloudRegion(region);
enPush.initialize(context,instanceGUID,destinationID, apiKey);
enPush.registerDeviceWithUserId(ecpUserId, new ENPushResponseListener<String>() {
#Override
public void onSuccess(String response) {
//handle successful device registration here
Log.d("PushNotificationManager :device registration success", response);
}
#Override
public void onFailure(ENPushException exception) {
//handle failure in device registration here
}
});
Related
I am looking for a way to delivery a message, and once the message is delivered (and routed) successfully, i need to perform some operations.
I have enabled publisher confirms and returns by:
spring.rabbitmq.publisher-confirm-type=correlated
spring.rabbitmq.publisher-returns=true
I have configured return and confirm callback on the rabbit template:
rabbitTemplate.setMandatory(true);
rabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {
System.out.println("Message returned");
});
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
System.out.println("confirm"); //correlationData.returnedMessage has the original message
});
Here is my publish code:
CorrelationData crd = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("X-ORDERS", "ORDER_PLACED", request, crd);
crd.getFuture().addCallback(new ListenableFutureCallback<Confirm>() {
#Override
public void onFailure(Throwable throwable) {
log.info("Failure received");
}
#Override
public void onSuccess(Confirm confirm) {
if(confirm.isAck()){
log.info("Success received");
doSomethingAfterSuccess();
}}
});
Now, when i publish a message that is unable to route the message :-
rabbitTemplate's returnCallBack AND confirmCallBack are also being
called
the onSuccess(..) of the correlationData is still called with
isAck() = true
So, how can I check if the message is delivered successfully and routed?
EDIT: Found solution. The publish code :
CorrelationData crd = new CorrelationData(UUID.randomUUID().toString());
rabbitTemplate.convertAndSend("X-ORDERS", "ORDER_PLACED", request, crd);
crd.getFuture().addCallback(new ListenableFutureCallback<Confirm>() {
#Override
public void onFailure(Throwable throwable) {
log.info("Failure received");
}
#Override
public void onSuccess(Confirm confirm) {
if(confirm.isAck() && crd.getReturnedMessage == null){
log.info("Success received");
doSomethingAfterSuccess();
}}
});
basically changed the condition in onSuccess to "confirm.isAck() && crd.getReturnedMessage == null"
That is per the RabbitMQ documentation - you still get a positive ack, but it is guaranteed to be delievered after the return.
So simply check that the future.returnedMessage is not null in onSuccess().
See the documentation.
In addition, when both confirms and returns are enabled, the CorrelationData is populated with the returned message. It is guaranteed that this occurs before the future is set with the ack.
I am successfully connecting to a local websocket server with tyrus, but the onMessage method does not get called. I setup Fiddler as proxy in between and I see that the server responds with two messages, however, they are not printed out in my code. I more or less adapted the sampe code:
The onOpen Message is printed out
public static void createAndConnect(String channel) {
CountDownLatch messageLatch;
try {
messageLatch = new CountDownLatch(1);
final ClientEndpointConfig cec = ClientEndpointConfig.Builder.create().build();
ClientManager client = ClientManager.createClient();
client.connectToServer(new Endpoint() {
#Override
public void onOpen(Session session, EndpointConfig config) {
System.out.println("On Open and is Open " + session.isOpen());
session.addMessageHandler((Whole<String>) message -> {
System.out.println("Received message: " + message);
messageLatch.countDown();
});
}
}, cec, new URI("ws://192.168.1.248/socket.io/1/websocket/" + channel));
messageLatch.await(5, TimeUnit.SECONDS); //I also tried increasing timeout to 30sec, doesn't help
} catch (Exception e) {
e.printStackTrace();
}
}
That's a known issue - it will work if you rewrite lambda to anonymous class or use Session#addMessageHandler(Class, MessageHandler) (you can use lambdas here).
I am using the Spring implementation for websocket+stomp as server, and the SockJS as client. This works perfectly when the connection is fine. But I am trying to keep the messag resending when the connection is broken. Here is my code.
public void reliableSend(String target, Object data){
try{
simpMessagingTemplate.convertAndSend(target, data);
}
catch (MessagingException e){
e.printStackTrace();
timer.purge();
TimerTask task = new TimerTask() {
#Override
public void run() {
reliableSend(target, data);
}
};
timer.schedule(task, 1000);
}
}
My problem is I just cannot know convertAndSend fails, it won't throw MessagingException even I have disconnected the network and the websocket connection is broken. Is there a way I can know the failure?
I am making a wear app which fetches data from database(which is on handheld) on launch of app home screen.
So when the homepage activity launches, It sends a message using Wearable.MessageApi.sendMessage function from the android wear to handheld. On the handheld I have the WearableListenerService which receives this message in onMessageReceived function and reads database. After reading database it sends putDatamapRequest to the wear.
Now on the wear side, I have another WearableListenerService. In this service, onDataChanged() function is never invoked. It runs at times, so far it ran for 2-3 times but otherwise it doesn't run. It's very random. Also once the data is received in Wear side, I set a static Arraylist, which I use to display data in Activity. But since the onDataChanged function is not always called, it gives empty array list.
Here is my AndroidManifest file of wear app where I declared the service:
<service
android:name="com.example.deals.DataListenerService"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="com.google.android.gms.wearable.BIND_LISTENER" />
</intent-filter>
</service>
Here is my code to send message from wear to handheld:
mGoogleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).setResultCallback(new ResultCallback<NodeApi.GetConnectedNodesResult>() {
#Override
public void onResult(NodeApi.GetConnectedNodesResult getConnectedNodesResult) {
if(!getConnectedNodesResult.getNodes().isEmpty())
{
node = getConnectedNodesResult.getNodes().get(0);
System.out.println("Connected: "+ node.getId());
Wearable.MessageApi.sendMessage(mGoogleApiClient, node.getId(), FETCH_ALL_DEALS, null).setResultCallback(new ResultCallback<MessageApi.SendMessageResult>() {
#Override
public void onResult(MessageApi.SendMessageResult sendMessageResult) {
if (!sendMessageResult.getStatus().isSuccess()) {
Log.e("Wear:", "ERROR: failed to send Message: " + sendMessageResult.getStatus());
}
else
System.out.println("success");
}
});
}
else
System.out.println("Wear not connected to Phone");
}
});
}
#Override
public void onConnectionSuspended(int i) {
}
})
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.v("Phone to wear connection failed", "onConnectionFailed: " + result);
}
})
.addApi(Wearable.API)
.build();
mGoogleApiClient.connect();
Here is my code for onMessageReceive on Handheld:
public void onMessageReceived(MessageEvent messageEvent) {
System.out.println("Message Received on Phone on launch of wear homepage");
if(messageEvent.getPath().equals(FETCH_ALL_DEALS)) {
sendSavedDeals(); //fetch from db and make a datamap object using PutDataRequest
System.out.println("Message Received on Phone on launch of wear homepage");
}
else {
System.out.println("Unable to recognise action for "+messageEvent.getPath());
}
}
Now on my wear side I have a WearableListenerService but it's onDataChanged method never gets called. Could you please help me with that.
onDataChanged() is only called when the data really did change. If you put the same data into the DataApi multiple times, the method is only called once until you write different data.
To trigger an action on the wear side, even when the data didn't change, send a message after putting data into the DataApi.
Data should be changed or deleted to get call-back to onDataChanged in WearabaleListenerService in your wear.
if you want make changes open APP-info from settings and clear-data then after force stop .
Finally launch your app in phone..but ensure that wearable listener service should be already started in your wear..
When onDataChanged() is not being called :
Firstly, ensure that the handheld activity is connecting to the API at the start :
#Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
otherwise, it fails silently.
If it still doesn't work, to facilitate the debug, add this override method and this class in the handheld activity to generate data every 5 seconds :
#Override
public void onResume() {
super.onResume();
mDataItemGeneratorFuture = mGeneratorExecutor.scheduleWithFixedDelay(
new DataItemGenerator(), 1, 5, TimeUnit.SECONDS
);
}
/** Generates a DataItem based on an incrementing count. */
private class DataItemGenerator implements Runnable {
private int count = 0;
#Override
public void run() {
PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(COUNT_PATH);
putDataMapRequest.getDataMap().putInt(COUNT_KEY, count++);
PutDataRequest request = putDataMapRequest.asPutDataRequest();
Log.d("yourApp", "Generating DataItem: " + request);
if (!mGoogleApiClient.isConnected()) {
return;
}
Wearable.DataApi.putDataItem(mGoogleApiClient, request)
.setResultCallback(new ResultCallback() {
#Override
public void onResult(DataItemResult dataItemResult) {
if (!dataItemResult.getStatus().isSuccess()) {
Log.e("YourApp", "ERROR: failed to putDataItem, status code: "
+ dataItemResult.getStatus().getStatusCode());
}
}
});
}
}
Background Story:
I am developing a GWT application, using the standard MVP design pattern, and also using RPC to get data from my custom data handling servlet (does a lot behind the scenes). Anyway, my goal is to create a very simple custom caching mechanism, that stores the data returned from the RPC callback in a static cache POJO. (The callback also sends a custom event using the SimpleEventBus to all registered handlers.) Then when I request the data again, I'll check the cache before doing the RPC server call again. (And also send a custom event using the EventBus).
The Problem:
When I send the event from the RPC callback, everything works fine. The problem is when I send the event outside the RPC callback when I just send the cached object. For some reason this event doesn't make it to my registered handler. Here is some code:
public void callServer(final Object source)
{
if(cachedResponse != null)
{
System.err.println("Getting Response from Cache for: "+ source.getClass().getName());
//Does this actually fire the event?
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
else
{
System.err.println("Getting Response from Server for: "+ source.getClass().getName());
service.callServer(new AsyncCallback<String>(){
#Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
#Override
public void onSuccess(String result) {
cachedResponse = result;
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
}
Now I have two Activities, HelloActivity and GoodbyeActivity (taken from: GWT MVP code)
They also print out messages when the handler is called. Anyway, this is the output I get from the logs: (Not correct)
Getting Response from Cache for: com.hellomvp.client.activity.HelloActivity
Response in GoodbyeActivity from: com.hellomvp.client.activity.HelloActivity
Getting Response from Cache for: com.hellomvp.client.activity.GoodbyeActivity
Response in HelloActivity from: com.hellomvp.client.activity.GoodbyeActivity
What I expect to get is this:
Getting Response from Cache for: com.hellomvp.client.activity.HelloActivity
Response in HelloActivity from: com.hellomvp.client.activity.HelloActivity
Getting Response from Cache for: com.hellomvp.client.activity.GoodbyeActivity
Response in GoodbyeActivity from: com.hellomvp.client.activity.GoodbyeActivity
And I will get this expected output if I change the above code to the following: (This is the entire file this time...)
package com.hellomvp.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.hellomvp.events.ResponseEvent;
public class RequestManager {
private EventBus eventBus;
private String cachedResponse;
private HelloServiceAsync service = GWT.create(HelloService.class);
public RequestManager(EventBus eventBus)
{
this.eventBus = eventBus;
}
public void callServer(final Object source)
{
if(cachedResponse != null)
{
System.err.println("Getting Response from Cache for: "+ source.getClass().getName());
service.doNothing(new AsyncCallback<Void>(){
#Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
#Override
public void onSuccess(Void result) {
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
else
{
System.err.println("Getting Response from Server for: "+ source.getClass().getName());
service.callServer(new AsyncCallback<String>(){
#Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
#Override
public void onSuccess(String result) {
cachedResponse = result;
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
}
}
So the point it out, the only change is that I created a new RPC call that does nothing, and send the event in its callback, with the cached data instead, and it causes the application to work as expected.
So the Question:
What am I doing wrong? I don't understand why 'eventBus.fireEvent(...)' Needs to be in an RPC Callback to work properly. I'm thinking this is a threading issue, but I have searched Google in vain for anything that would help.
I have an entire Eclipse project that showcases this issue that I'm having, it can be found at: Eclipse Problem Project Example
Edit: Please note that using eventBus.fireEventFromSource(...) is only being used for debugging purposes, since in my actual GWT Application I have more than one registered Handler for the events. So how do you use EventBus properly?
If I understand your problem correctly you are expecting calls to SimpleEventBus#fireEventFromSource to be routed only to the source object. This is not the case - the event bus will always fire events to all registered handlers. In general the goal of using an EventBus is to decouple the sources of events from their handlers - basing functionality on the source of an event runs counter to this goal.
To get the behavior you want pass an AsyncCallback to your caching RPC client instead of trying to use the EventBus concept in a way other than intended. This has the added benefit of alerting the Activity in question when the RPC call fails:
public class RequestManager {
private String cachedResponse = null;
private HelloServiceAsync service = GWT.create(HelloService.class);
public void callServer(final AsyncCallback<String> callback) {
if (cachedResponse != null) {
callback.onSuccess(cachedResponse);
} else {
service.callServer(new AsyncCallback<String>(){
#Override
public void onFailure(Throwable caught) {
callback.onFailure(caught);
}
#Override
public void onSuccess(String result) {
cachedResponse = result;
callback.onSuccess(cachedResponse);
}
});
}
}
}
And in the Activity:
clientFactory.getRequestManager().callServer(new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
// Handle failure.
}
#Override
public void onSuccess(String result) {
helloView.showResponse(result);
}
});