Push Notifications Error when device is registered to the same channel as an internal subscription

If I have multiple registrations in Backendless for a device I get this weird error when I try to send a push notification:

UserInfo={NSLocalizedDescription=Backendless encountered an error while handling the request. An internal trouble ticket with ID bl-server:7B77F0A6-BB75-0042-FFC7-5EDF4AB83100 has been created and we will be investigating the issue.

Is there anything else I should do or how would I know when this internal ticket is resolved?

If it helps I’m trying (unsuccessfully) to get a device registered to multiple channels for push notifications. My app registers on startup, then after the user login I pull the deviceToken from the db and use that to re-register the device with an array of channels that the user is subscribed to.

quick follow up…

I wasn’t able to pull the token from the db because of the data mangling with the hex mapping so I just stored it in a global var for now…so registering multiple channels works BUT

if I have the device registered to a named channel that is also subscribed to internally with listeners then I get the error message in my first post. So it seems that it doesn’t like being registered AND subscribed to.

I was doing both because I am assuming that is how I can get push noti as well as real time msging, but maybe I’m approaching this wrong?

Hi @David_Thompson,

Could you please provide more information?

  1. What is you App ID?
  2. Which platform SDK do you use? (Maybe it’s Codeless?)
  3. Please provide a step by step instructions of how to reproduce this issue?

Regards,
Olha

Hi @olhadanylova

  1. AppID: 0A712AC8-04AB-0261-FF80-964B643D3000
  2. iOS with BE v 7.0.1

To register the device and subscribe to channel:

//subscribe to channel
t.channel = Backendless.shared.messaging.subscribe(channelName: "E7880B05-C212-4DF3-947F-425D592FFD99")
//add listener
let _ = t.channel?.addCustomObjectMessageListener(forClass: MessageAndSender.self, responseHandler: { message in
    if let receivedMsg = message as? MessageAndSender {
        if(receivedMsg.fromObjectId != self.pubProfile.objectId) {
            t.messages?.insert(receivedMsg, at: 0)
            SoundManager.shared.playMsgAlert(sound: .alert)
        }
    }
    print("Received message as a custom object: \(message)")
}, errorHandler: { fault in
    print("Error: \(fault.message ?? "")")
})

//register device
Backendless.shared.messaging.registerDevice(deviceToken: t, channels: ["E7880B05-C212-4DF3-947F-425D592FFD99"]) { response in
      print("device maybe reg: \(response)")
  } errorHandler: { fault in
      print(fault)
  }

The error happens when I try to send a msg. The addCustomObjectMessageListener doesn’t fire when both the device and subscribed channel are named the same. If I change the name of the device registration to the default it works fine.

Looking into it.

@David_Thompson unfortunately I cannot reproduse this issue and need more details.
What do you mean by the device name here

both the device and subscribed channel are named the same.

?
Do I understand correctly the steps?

  1. register device in APNS and get device token
  2. wait until some actions are done (e.g. user login)
  3. subscribe for a channel “E7880B05-C212-4DF3-947F-425D592FFD99” and add a listener to it
  4. register the device in the “E7880B05-C212-4DF3-947F-425D592FFD99” channel with token received from APNS
  5. send message (expected behavior: listener triggered, current behavior: listener not trigerred)

If so, could you please show the message body you send and the MessageAndSender class structure.

Yes, those steps are correct. I just tried commenting out the channel subscription/listener block and I still received the error so the problem is not because of the same name issue. It is just when I send a msg through the named channel.

Here is the class of the MessageAndSender:

import Foundation
import Backendless

@objcMembers
class MessageAndSender: NSObject, ObservableObject, Identifiable {
    
    var objectId: String?
    ///objectId of MsgThread object
    var threadObjectId: String?
    @Published var msgTxt: String?
    @Published var pubName: String?
    @Published var pubProfilePicURL: String?
    ///objectId of senders public profile
    var fromObjectId: String?
    var created: Date?
}

This is how I am sending/publishing a msg:

//publish message to channel and send push notification
let publishOptions = PublishOptions()
publishOptions.headers = ["ios-alert":"Alert message", "ios-badge":1, "ios-sound":"default"]
let deliveryOptions = DeliveryOptions()
                        
Backendless.shared.messaging.publish(channelName: msgThread.objectId!, message: newMsgAndSender, publishOptions: publishOptions) { status in
    print("Message Object published: \(status)")
} errorHandler: { fault in
    print(fault)
}

Here is the full error msg:

 UserInfo={NSLocalizedDescription=Backendless encountered an error while handling the request. An internal trouble ticket with ID bl-server:EC655DA9-0E8E-6E51-FF94-D74C062AE900 has been created and we will be investigating the issue.
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class java.lang.String (java.util.LinkedHashMap and java.lang.String are in module java.base of loader 'bootstrap')
java.lang.RuntimeException: java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class java.lang.String (java.util.LinkedHashMap and java.lang.String are in module java.base of loader 'bootstrap')
	at com.backendless.services.notifications.PushService.sendNotifications(PushService.java:126)
	at com.backendless.gamification.AbstractGamificationInterceptor.invoke(AbstractGamificationInterceptor.java:67)
	at com.backendless.services.messaging.publish.PublishMessage.getV3Message(PublishMessage.java:90)
	at com.backendless.services.messaging.publish.PublishMessage.execute(PublishMessage.java:80)
	at com.backendless.services.messaging.operation.MessagingOperationsService.sendMessage(MessagingOperationsService.java:205)
	at com.backendless.services.messaging.operation.MessagingOperationsService.publish(MessagingOperationsService.java:135)
	at com.backendless.services.messaging.operation.MessagingCustomLogicDecorator.lambda$publish$0(MessagingCustomLogicDecorator.java:44)
	at com.backendless.servercode.codeModel.ModelCodeExtender.performActionWithValidationUnsafe(ModelCodeExtender.java:175)
	at com.backendless.servercode.codeModel.ModelCodeExtender.performActionWithValidation(ModelCodeExtender.java:128)
	at com.backendless.servercode.codeModel.ModelCodeExtender.performActionWithValidation(ModelCodeExtender.java:114)
	at com.backendless.services.messaging.operation.MessagingCustomLogicDecorator.publish(MessagingCustomLogicDecorator.java:45)
	at com.backendless.services.messaging.operation.AnalyticsDecorator.publish(AnalyticsDecorator.java:41)
	at com.backendless.services.messaging.operation.SecurityDecorator.publish(SecurityDecorator.java:35)
	at com.backendless.services.messaging.operation.RunnerDecorator.publish(RunnerDecorator.java:30)
	at com.backendless.inject.interceptors.AbstractApiCallInterceptor.lambda$invokeSync$0(AbstractApiCallInterceptor.java:57)
	at com.backendless.services.DefaultApiCallAnalyticsRecorder.executeApiCall(DefaultApiCallAnalyticsRecorder.java:47)
	at com.backendless.inject.interceptors.AbstractApiCallInterceptor.invokeSync(AbstractApiCallInterceptor.java:54)
	at com.backendless.inject.interceptors.AbstractApiCallInterceptor.invoke(AbstractApiCallInterceptor.java:43)
	at com.backendless.services.messaging.MessagingService.publish(MessagingService.java:48)
	at controllers.messaging.api.Messaging.lambda$publish$3(Messaging.java:128)
	at com.backendless.async.BackendlessExecutorService.lambda$submit$0(BackendlessExecutorService.java:84)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class java.lang.String (java.util.LinkedHashMap and java.lang.String are in module java.base of loader 'bootstrap')
	at com.backendless.services.notifications.SendMessagesTask.getMessageForPush(SendMessagesTask.java:515)
	at com.backendless.services.notifications.SendMessagesTask.publishMessageToPushMessage(SendMessagesTask.java:235)
	at com.backendless.services.notifications.SendMessagesTask.<init>(SendMessagesTask.java:128)
	at com.backendless.services.notifications.PushService.sendNotifications(PushService.java:104)
	... 23 more
}

I think I found the problem, but I don’t know how to fix it. When I send/publish the message with the MessageAndSender instance as the message it throws the error, but when I just send a plain String it doesn’t throw the error. It seems like sending a class object is the problem.

So I guess the question is how do I pass a class object as a message through a push notification channel? Currently I have a channel for each message thread. I can pass a MessageAndSender object just fine, but when I try to pass the object when the device is also registered to receive push noti with the same channel name it can’t handle the class object. It only likes to see txt.

How can I handle a custom class object being passed through a noti channel?

Finally was able to reproduce this issue. Will fix it as soon as possible.

Issue is fixed in v7.0.2.
@David_Thompson could you please update and check if it works now?

ok…just downloaded and tried again. A string works, but sending a class object still throws the same error :frowning:

Can I use your app for testing? Because, unfortunately, I cannot reproduce in mine.
If so, please provide APP ID and channel name I can register to.
Also please provide a simple code sample that can reproduce the error (please simplify as possible for easier testing, it should be a class description for custom object + code that reproduces the error without additional variables that come from another classes)

Yes definitely…

AppID: 0A712AC8-04AB-0261-FF80-964B643D3000

Channel Name: E7880B05-C212-4DF3-947F-425D592FFD99

Class Object:

import Foundation
import Backendless

@objcMembers
class MessageAndSender: NSObject, ObservableObject, Identifiable {
    
    var objectId: String?
    ///objectId of MsgThread object
    var threadObjectId: String?
    @Published var msgTxt: String?
    @Published var pubName: String?
    @Published var pubProfilePicURL: String?
    ///objectId of senders public profile
    var fromObjectId: String?
    var created: Date?
}

Here is the code to test:

let publishOptions = PublishOptions()
publishOptions.headers = ["ios-alert":"Alert message", "ios-badge":1, "ios-sound":"default"]
let dOpts = DeliveryOptions()
dOpts.publishPolicy = PublishPolicyEnum.BOTH.rawValue
  
var test = MessageAndSender()
  
Backendless.shared.messaging.publish(channelName: msgThread.objectId!, message: test, publishOptions: publishOptions, deliveryOptions: dOpts) { status in
    print("Message Object published: \(status)")
} errorHandler: { fault in
    print(fault)
}

If I replace the message parameter with a string (like “test”) then I don’t get an error so it makes me think it has something to do with passing an object.

Thanks for samples. I’ll investigate it ASAP.

Hi @David_Thompson,

I was able to reproduce the issue directly within your app (request works fine in another app). Our backend dev will check this issue.

awesome, thank you.

With version 7.0.2 and 7.0.3: addCustomObjectMessageListener does not work. This is the code I’m using to register:

let _ = t.channel?.addCustomObjectMessageListener(forClass: MessageAndSender.self, responseHandler: { msg in
    print("Received msg: \(msg)")
}, errorHandler: { fault in
    print(fault)
})

This worked in version 7.0.1, but not since the update.

I can see the message being published on the backend but it won’t show up on the client.

Does it work for you with v7.0.1 now? (if so, it is weird)
Our backend devs investigate this issue, because the error occurs with your app not only with Swift-SDK but also when sending the curl publish request and error comes from server not from SDK (SDK RT features haven’t been changed in v 7.0.2 or 7.0.3)
I also see that the fix is ready and waiting for the code review so it should be available soon.
Sorry for the inconvenience, we’ll notify you as soon as fix is ready.

Thank you for checking…no it has not worked since I have updated from 7.0.1. I assumed it was still working for 7.0.1, but you are correct that it is a server error so I’ll wait for the update before trying again.

sorry I think I should clarify …

There are now 2 issues…

  1. PUSH notifcations throwing a server error, and
  2. Custom object listeners not receiving/registering a message through a channel

Adding a custom object listener to a channel WAS working fine. The part that didn’t work (and was throwing a server error) was when I tried to publish a custom object for a PUSH notification.

Now adding a custom object listener to a channel doesn’t work and I don’t receive an error. The message gets through to the client because a standard addMessageListener will work for the channel, but not the custom object listener.