Mobile Backend Starter subscribeToCloudMessage will not work
When I use the subscribeToCloudMessage() function with CloudBackendMessaging.TOPIC_ID_BROADCAST as the topicId, as I did in CloudBackendFragment.java, everything works fine, but when I provide my own string for the function, I get this message:
Error:
m.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
"code": 400,
"errors": [
{
"domain": "global",
"message": "SubscriptionIDs: String properties must be 500 characters or less. Instead, use com.google.appengine.api.datastore.Text, which can store strings of any length.",
"reason": "badRequest"
}
],
"message": "SubscriptionIDs: String properties must be 500 characters or less. Instead, use com.google.appengine.api.datastore.Text, which can store strings of any length."
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:111)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:38)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1042)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at com.google.cloud.backend.core.CloudBackend.list(CloudBackend.java:314)
at com.google.cloud.backend.core.CloudBackendAsync.access$8(CloudBackendAsync.java:1)
at com.google.cloud.backend.core.CloudBackendAsync$9.callBackend(CloudBackendAsync.java:270)
at com.google.cloud.backend.core.CloudBackendAsync$9.callBackend(CloudBackendAsync.java:1)
at com.google.cloud.backend.core.CloudBackendAsync$BackendCaller.run(CloudBackendAsync.java:402)
Solution
This error message indicates that the value of the property SubscriptionIDs,
which you can find under the _DeviceSubscription
type in the data store, exceeds the 500 Unicode character limit. Read docs for reference.
From the documentation:
For text strings and unencoded binary data (byte strings), the
Datastore supports two value types:
- Short strings (up to 500 Unicode characters or bytes) are indexed
and can be used in query filter conditions and sort orders.- Longstrings (up to 1 megabyte) are not indexed and cannot be used in query filters and sort orders.
This happens because MBS tries to write all subscriptions to a single property.
So, to overcome this problem, we need to enter Text instead of String
noopener nofollow”>MBS backend source code for the SubscriptionIDs
property. To do this, you need to make the following changes in the DeviceSubscription.java
class:
To set the Text
property, replace this line of code:
deviceSubscription.setProperty(PROPERTY_SUBSCRIPTION_IDS, this.gson.toJson(subscriptions));
With this line:
deviceSubscription.setProperty(PROPERTY_SUBSCRIPTION_IDS, new Text(this.gson.toJson(subscriptions)));
Get the Text
property from the data store:
Replace this line:
String subscriptionString = (String) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS);
With this:
Text text = (Text) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS); String subscriptionString = text.getValue();
Replace this line:
String ids = (String) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS);
With this:
Text text = (Text) deviceSubscription.getProperty(PROPERTY_SUBSCRIPTION_IDS); String ids = text.getValue();
Replace this line:
String[] ids = new Gson().fromJson((String) entity.getProperty(PROPERTY_SUBSCRIPTION_IDS), String[].class);
With this:
Text text = (Text) entity.getProperty(PROPERTY_SUBSCRIPTION_IDS); String[] ids = new Gson().fromJson(text.getValue(), String[].class);
Seems like an effective solution. So far, I have not noticed a negative impact on my project.
Note: As stated in the documentation, text
is not indexed and cannot be used to query filters and sort order. Therefore, if property SubscriptionIDs
need to be indexed, this restriction can cause additional problems.