0

On upgrading Guava to the latest 23.5-jre from 18.0 I am getting an exception like below

Exception in thread "main" java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V
    at com.van.common.VanExecutors.getSpec(VanExecutors.java:91)
    at com.van.common.VanExecutors.newFixedSizeExecutor(VanExecutors.java:114)
    at com.van.storage.config.ConfigStoreFactory.getOrCreateUncachedStore(ConfigStoreFactory.java:56)
    at com.van.storage.config.ConfigStoreFactory.getOrCreateStore(ConfigStoreFactory.java:74)
    at com.van.storage.config.PolicyManager.loadFromSystemProperties(PolicyManager.java:79)
    at com.van.tools.metric.HbaseMetricStoreSetup.main(HbaseMetricStoreSetup.java:25)

The relevant code

private ExecutorSpec getSpec(String executorName) {
        Preconditions.checkArgument(isValid(), "Not initialized");
        Preconditions.checkArgument(NullOrEmpty.isFalse(executorName), "No executor name given");
        Preconditions.checkArgument(POOL_NAME_PATTERN.matcher(executorName).matches(), "Executor name %s must end with -exec", executorName);
        for (ExecutorSpec spec : executorsSpec.getExecutorSpecList()) {
            if (spec.getName().equalsIgnoreCase(executorName)) return spec;
        }
        return null;
    }

As per the stacktrace line 91 is the last Preconditions check.

Can someone let me know what is going wrong?

tuk
  • 5,941
  • 14
  • 79
  • 162
  • 1
    https://stackoverflow.com/questions/45247193/nosuchmethoderror-com-google-common-base-preconditions-checkargumentzljava-lan – Julius Hörger Dec 20 '17 at 07:33
  • As with the linked question: "You have multiple versions of Guava on your classpath. Figure out which of your dependencies depend on Guava, and make sure only one version remains.". You compile against the new version which has the method, but execute with an older one, which doesn't (before 20.0, there was just a varargs overload). – maaartinus Dec 20 '17 at 09:29
  • @maaartinus Can you let me know how can I determine that? I have done `mvn dependency:tree` but it is reporting the latest `23.5-jre` in all places. – tuk Dec 20 '17 at 11:44
  • I'm not using maven and it's long time since I had such a problem. The old versions aren't called `*-jre` and this may be related. There's a maven cache somewhere in the home directory, try `find ~/.m2 -name "*guava*"`, maybe delete them all, recompile and look again. No idea, if it helps... – maaartinus Dec 20 '17 at 15:40
  • @maaartinus - One doubt since compilation is not failing. maven dependencies are getting correctly resolved. But when running should not it pick the version that it was compiled with even if the old version is in the class path? – tuk Dec 20 '17 at 16:46
  • Are the multiple Guava versions in `~/.m2`? When running, AFAIK the first found version of a given class gets loaded. Which mean, you never want to have multiple versions there. Try to remove all but one versions. +++ You should probably add the output of `mvn dependency:tree` to your question. – maaartinus Dec 20 '17 at 18:54
  • @maaartinus Yes I am seeing multiple guava in .m2. Even if I am removing .m2 compiling the project again downloading multiple guava. The problem I am having is mvn dependency:tree is not showing any old version of guava. The dependency tree is too big to post it here – tuk Dec 21 '17 at 03:49
  • Since it gets downloaded and since there's the classpath problem, we can be pretty sure that the presence of the old version is the cause. Unfortunately, I have no idea how to stop maven from doing this. I guess, the old version lacks the `-jre` suffix, which is why it doesn't get replaced by the new one. – maaartinus Dec 21 '17 at 11:47
  • 1
    Is `VanExecutors` precompiled against a different version of Guava? It's possible it's not showing up in `dependency:tree` if it's compiled totally separately. The issue is not the _runtime_ version of Guava, since the update from v18 to v19 had source-level API compatibility but not binary-level compatibility. Old jars might need to be recompiled to make sure their `.class` files reference the correct `Preconditions` methods – rdshapiro Dec 21 '17 at 14:22
  • @rdshapiro Are you sure? The referenced but missing method is `checkArgument(ZLjava/lang/String;Ljava/lang/Object;)`, which is https://github.com/google/guava/blob/4bd7d17d99316aecb4006873d8f8bb73fe636b78/guava/src/com/google/common/base/Preconditions.java#L207 and exists since 20.0. So I think that the failing class was compiled against a *current* (>=2.0) version but gets an *old* (<2.0) version at runtime. – maaartinus Dec 21 '17 at 19:00
  • @maaartinus - You are correct. Used jhades (http://jhades.github.io/) to determine which jar is getting loaded. It is loading some old version from the classpath. – tuk Dec 22 '17 at 04:26
  • @rdshapiro - Can you suggest something if there is a way I can avoid an old guava from getting loaded ? – tuk Dec 22 '17 at 04:27
  • What about [this answer](https://stackoverflow.com/a/29738173/581205)? – maaartinus Dec 22 '17 at 04:44

2 Answers2

0

Seems to me that the method isValid() returns a String (was this changed?) but a boolean is expected (and was in release 18 too).

jensgram
  • 31,109
  • 6
  • 81
  • 98
  • I have edited the questions. The last precondition check is throwing the error. – tuk Dec 20 '17 at 07:46
0

To resolve this issue I prefixed by CLASSPATH ( export CLASSPATH=<guava-23.5>;$CLASSPATH ) with Guava 23.5 jre.

tuk
  • 5,941
  • 14
  • 79
  • 162