January 24, 2020

Salesforce Push Notifications and an "Unsupported Java type"

Some time ago, I wrote some code to send push notifications to our mobile application. Recently I dug up that code and merged it in, ready to do some proper testing, as it had been sidelined as I couldn't find a way to test them inside of scratch orgs. When it came to sending a notification in a test org where our managed package was installed, nothing happened, and then, in the words of Douglas Adams, "... after a second or so, nothing continued to happen.". Sighing, I granted login access, logged into the org through the LMA so I could access the logs, and quickly hit upon this:

|FATAL_ERROR|System.UnexpectedException: org.json.JSONException: Unsupported Java type

Which is weird, since this code used to work. 100%. I tested it a few times in the packaging org with no issues, so something has changed. After some trial and error with the message content, I worked out what was causing the problem: a Set in the data payload.

When initialising a message to send, you can include a payload that's mapped into a JSON object, as always on the Salesforce platform, you can represent this payload with a Map of String to Object:

Map<String, Object> data = new Map<String, Object>
{
    'id' => userIds,
    'type' => type,
    'message' => message
};

Map<String, Object> payload = Messaging.PushNotificationPayload.apple(title, '', null, data);

userIds in the code above, is a of the Set<String> type, and for some reason that now causes the exception mentioned.

The Fix

As you may well have guessed, simply changing this set to a different type avoids the problem:

Map<String, Object> data = new Map<String, Object>
{
	'id' => new List<String>(userIds),
	'type' => type,
	'message' => message
};

Map<String, Object> payload = Messaging.PushNotificationPayload.apple(title, '', null, data);

You may or may not want to just replace the set with a list to begin with, but if ensuring that only unique values are sent is important, then creating the list last minute as above does the job nicely. Something, somewhere, has changed, but it's not within our reach, so for now we'll just have to live with lists.