When we subscribe a device for a topic - called by a service in
JBoss application server AS7.1 - the Admin SDK fails with "
Required parameter is missing: response_type". This is the stack trace:
java.util.concurrent.ExecutionException: com.google.firebase.messaging.FirebaseMessagingException: Error while calling IID backend service
at com.google.firebase.tasks.Tasks.getResultOrThrowExecutionException(Tasks.java:179) [firebase-admin-5.11.0.jar:]
at com.google.firebase.tasks.Tasks.await(Tasks.java:109) [firebase-admin-5.11.0.jar:]
at com.google.firebase.internal.TaskToApiFuture.get(TaskToApiFuture.java:74) [firebase-admin-5.11.0.jar:]
.....
Caused by: com.google.firebase.messaging.FirebaseMessagingException: Error while calling IID backend service
at com.google.firebase.messaging.FirebaseMessaging.makeTopicManagementRequest(FirebaseMessaging.java:304) [firebase-admin-5.11.0.jar:]
at com.google.firebase.messaging.FirebaseMessaging.access$100(FirebaseMessaging.java:57) [firebase-admin-5.11.0.jar:]
at com.google.firebase.messaging.FirebaseMessaging$2.call(FirebaseMessaging.java:195) [firebase-admin-5.11.0.jar:]
at com.google.firebase.messaging.FirebaseMessaging$2.call(FirebaseMessaging.java:192) [firebase-admin-5.11.0.jar:]
at com.google.firebase.tasks.Tasks$1.run(Tasks.java:82) [firebase-admin-5.11.0.jar:]
.....
Caused by: java.io.IOException: Error getting access token for service account:
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:385) [google-auth-library-oauth2-http-0.9.0.jar:]
at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:175) [google-auth-library-oauth2-http-0.9.0.jar:]
at com.google.auth.oauth2.OAuth2Credentials.getRequestMetadata(OAuth2Credentials.java:161) [google-auth-library-oauth2-http-0.9.0.jar:]
at com.google.auth.http.HttpCredentialsAdapter.initialize(HttpCredentialsAdapter.java:96) [google-auth-library-oauth2-http-0.9.0.jar:]
at com.google.firebase.internal.FirebaseRequestInitializer.initialize(FirebaseRequestInitializer.java:46) [firebase-admin-5.11.0.jar:]
at com.google.api.client.http.HttpRequestFactory.buildRequest(HttpRequestFactory.java:93) [google-http-client-1.23.0.jar:1.23.0]
at com.google.api.client.http.HttpRequestFactory.buildPostRequest(HttpRequestFactory.java:133) [google-http-client-1.23.0.jar:1.23.0]
at com.google.firebase.messaging.FirebaseMessaging.makeTopicManagementRequest(FirebaseMessaging.java:289) [firebase-admin-5.11.0.jar:]
.....
Caused by: com.google.api.client.http.HttpResponseException: 400 Bad Request
<!DOCTYPE html><html .....
<p><b>Error: invalid_request</b></p>
<p id="errorDescription">Required parameter is missing: response_type</p>
....
<div id="request_info_header">Request Details
<ul id="request_info_items">
<li class="param_entry" id="param_entry_0">grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer</li>
<li class="param_entry" id="param_entry_1">assertion=.....</li>
</ul>
....
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1070) [google-http-client-1.23.0.jar:1.23.0]
at com.google.auth.oauth2.ServiceAccountCredentials.refreshAccessToken(ServiceAccountCredentials.java:383) [google-auth-library-oauth2-http-0.9.0.jar:]
When we do the same in a simple Java class, called from the main() method, it works fine.
Here the code (in principle)
public static final void main(final String[] args) {
try {
final FirebaseApp fbApp = getFirebaseApp();
final int numRegs = createRegistration(fbApp);
if (numRegs > 0) {
final String id = sendNotification(fbApp, false);
System.out.println("Done! ID = " + id);
}
} catch (final Exception e) {
System.err.println("Failed! " + e.getMessage());
System.exit(-1);
}
}
private static int createRegistration(final FirebaseApp fbApp) throws InvalidAppConfigException, PushBrokerException {
try {
final StringBuilder errors = new StringBuilder();
final String regToken = TOKEN;
final ApiFuture<TopicManagementResponse> registerListener = FirebaseMessaging
.getInstance(fbApp)
.subscribeToTopicAsync(Collections.singletonList(regToken), TOPIC);
System.out.println("Sent registration for registration token " + regToken + " for topic " + TOPIC);
TopicManagementResponse response = registerListener.get(); // <-- here we crash in JBoss AS7.1
if (response != null) {
System.out.println("Received response for new registration : " + response.toString());
if (response.getErrors() != null && !response.getErrors().isEmpty()) {
for (final TopicManagementResponse.Error error : response.getErrors()) {
errors.append(errors.length() > 0 ? "\n" : "");
errors.append(error.getReason());
}
System.err.println(errors.toString());
}
} else {
System.err.println("Didn't receive a response for registration of registration token " + regToken
+ " for topic " + TOPIC);
}
return response != null ? response.getSuccessCount() : 0;
} catch (final InterruptedException ie) {
System.err.println("Registration interrupted : " + ie.getMessage());
return -1;
} catch (final ExecutionException ee) {
System.err.println("Failed to register : " + ee.getMessage());
return -1;
}
}
private static FirebaseApp getFirebaseApp() {
final String pgwAppId = "try-out-app";
// get Firebase application
FirebaseApp fbApp = null;
try {
fbApp = FirebaseApp.getInstance(pgwAppId);
if (fbApp != null) { // already initialized?
return fbApp; // no need to initialize again
}
} catch (final IllegalStateException ise) {
}
// build Firebase credentials
ServiceAccountCredentials fbServiceCredentials = null;
try {
fbServiceCredentials = ServiceAccountCredentials.fromPkcs8(
"1166_and_so_on", // client ID
"firebase-ad...@my-project-name.iam.gserviceaccount.com", // client mail
"-----BEGIN PRIVATE KEY-----\n_and_so_on", // private key
"f239_and_so_on", // private key id
null, // scopes
null, // transport factory
new URI("https://accounts.google.com/o/oauth2/token"), // token url
null); // service acount user
} catch (final IOException ioe) {
System.err.println("Invalid private key");
return null;
} catch (final URISyntaxException use) {
System.err.println("Invalid token URI");
return null;
}
// build Firebase options
final FirebaseOptions fbOptions = new FirebaseOptions
.Builder()
.setConnectTimeout(10000)
.setReadTimeout(60000)
.setProjectId("my-project-name") // project id
.setCredentials(fbServiceCredentials)
.setDatabaseUrl("https://my-project-name.firebaseio.com") // database url
.build();
// initialize Firebase application
try {
fbApp = FirebaseApp.initializeApp(fbOptions, pgwAppId);
System.out.println("Firebase app initialized : " + fbApp);
} catch (final IllegalStateException ise1) {
System.err.println("Firebase app already initialized");
try {
return FirebaseApp.getInstance(pgwAppId);
} catch (final IllegalStateException ise2) {
System.err.println("Firebase app not initialized");
}
return null;
}
return fbApp;
}
private static String sendNotification(final FirebaseApp fbApp, final boolean dryRun) {
Message fbMessage = createMessage();
String response = null;
String id = null;
try {
final ApiFuture<String> sendListener = FirebaseMessaging.getInstance(fbApp).sendAsync(fbMessage, dryRun);
response = sendListener.get();
System.out.println("Sent push-notification : \n\t\tpayload = " + fbMessage.toString());
if (response != null && !response.isEmpty()) {
System.out.println("Received response for push-notification : " + response);
id = response.substring(response.lastIndexOf('/') + 1);
} else {
System.err.println("Didn't receive a response for push-notification");
}
} catch (final InterruptedException ie) {
System.err.println("Sending push-notification interrupted : " + ie.getMessage());
return null;
} catch (final ExecutionException ee) {
System.err.println("Failed to send push-notification : " + ee.getMessage());
return null;
}
return id;
}