How to fix guava problem when deploying firebase admin to payara
I recently implement firebase admin for our sign-in process. And I immediately face a problem in our local deployment. Since firebase admin still uses google-api-client library instead google-auth-library.
But this one is pretty easy to fix . Just exclude firebase admin guava dependency in your build.gradle and add the most recent guava dependency and you’re set for development.
compile ('com.google.firebase:firebase-admin:5.2.0') {
exclude group: 'com.google.guava'
}
compile 'com.google.guava:guava:23.0'A bigger problem arise when I’m deploying the app to our production server. As a note we’re using jetty in development and uses payara (glassfish fork) in our production environment.
When I deployed the app I’m faced with this annoying error.
com.google.common.base.Preconditions.checkState(ZLjava/lang/String;Ljava/lang/Object;)V
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkState(ZLjava/lang/String;Ljava/lang/Object;)V
at com.google.firebase.FirebaseApp.checkNotDeleted(FirebaseApp.java:314)I know this probably related to something with conflicting guava version. I already removed any old guava jar in my WEB-INF/lib. This kind of problem is harder to trace. Even trying to print all the guava library dependency only works in our dev environment, not in our production environment.
Further reading shows that payara app server actually have a guava dependency. With the way Payara class loader works the classes from payara will be loaded, even though the application itself includes different versions.
Luckily since version 171, payara introduce a simpler way to isolate this class loading problem. You can whitelist classes from libraries included on Payara Server. Basically it says that you can list all the classes that payara will load from their modules folder instead of from the application lib folder. This is a little bit counter intuitive, but related to our problem.
So how can we use this to force payara to load our guava version instead of payara version? The catch from the whitelist rule, is that for the classes not specified in the whitelist, Payara Server will look at the libraries included on the deployed application and throw a ClassNotFoundException if they are not present.
So all you have to do is create a glassfish-web.xml file that whitelist a package. I’m using glassfish package because by default it will be always loaded from the Payara Server module. And put it in the same folder as your web.xml file. And the server will load your version of guava instead of the one in the payara folder module.
Here’s an example of glassfish-web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
<whitelist-package>org.glassfish</whitelist-package>
</glassfish-web-app>I’m using my firebase admin case to tell this story. But this solution basically can be used for any conflicting library in Payara Server. Hope that helps.
