Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shopify will crash with okhttp 4.9.0 #690

Open
keepmovingljzy opened this issue Feb 25, 2021 · 6 comments
Open

Shopify will crash with okhttp 4.9.0 #690

keepmovingljzy opened this issue Feb 25, 2021 · 6 comments

Comments

@keepmovingljzy
Copy link

Shopify will crash with okhttp 4.9.0

when I use the shopify with okhttp 4.9.0,it will crash,I have forced all versions to be unified

    configurations.all {
      resolutionStrategy.force 'com.squareup.okhttp3:okhttp:4.9.0'
      resolutionStrategy.force 'com.squareup.okhttp3:logging-interceptor:4.9.0'
    }

it will crash when run this code

        try {
            JodaTimeAndroid.init(context)

            val httpClient = OkHttpClient.Builder()
                .addNetworkInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
                .build()
            client = GraphClient.build(
                context,
                BuildConfig.SHOPIFY_SHOP_DOMAIN,
                BuildConfig.SHOPIFY_API_KEY
            ) {
                this.httpClient = httpClient
                this.httpCache(File(context.cacheDir, "/http")) {
                    this.cacheMaxSizeBytes = 1024 * 1024 * 10
                    this.defaultCachePolicy =
                        HttpCachePolicy.Default.CACHE_FIRST.expireAfter(20, TimeUnit.MINUTES)
                }
            }
        } catch (t: Throwable) {
            t.printStackTrace()
        }

The exception is java.lang.NoSuchMethodError: No static method create(Lokhttp3/internal/io/FileSystem;Ljava/io/File;IIJ)Lokhttp3/internal/cache/DiskLruCache; in class Lokhttp3/internal/cache/DiskLruCache; or its super classes (declaration of 'okhttp3.internal.cache.DiskLruCache' appears in /data/app/com.xxx.xxx-LJaR5pwAQuLp9OygATCHIg==/base.apk!classes3.dex)

how to deal with it?

@keepmovingljzy
Copy link
Author

keepmovingljzy commented Feb 26, 2021

it will ok when I use okhttp 3.12.0
My shopify sdk is 7.0.0

@PiotrWpl
Copy link

Hi,

the issue here is that DiskLruCache is an internal class that shouldn't be used by the Shopify SDK, and it seems that API for it has changed in okhttp 4.0+
Shopify team should stop using it, or update to support new API.

But as a workaround, You can either write your own implementation of the cache by extending ResponseCacheStore class or disable the cache, by removing:

this.httpCache(File(context.cacheDir, "/http")) {
                    this.cacheMaxSizeBytes = 1024 * 1024 * 10
                    this.defaultCachePolicy =
                        HttpCachePolicy.Default.CACHE_FIRST.expireAfter(20, TimeUnit.MINUTES)
                }

@keepmovingljzy
Copy link
Author

keepmovingljzy commented Apr 21, 2021

thank you very much! @PiotrWpl

@TimoPtr
Copy link

TimoPtr commented Apr 22, 2021

since everything is internal in okhttp I had to create a java class

public class CompactConfigurator {
  private static final int VERSION = 99991;
  private static final int ENTRY_HEADERS = 0;
  private static final int ENTRY_BODY = 1;
  private static final int ENTRY_COUNT = 2;

  public static void configure(@NotNull GraphClient.Config config, @NotNull File directory, long maxSize, @NotNull Function1 <? super HttpCacheConfig, Unit> configure) {
    config.httpCache$buy3_release(new CompatCache(directory, maxSize), configure);
  }

  private static class CompatCache implements ResponseCacheStore {

    CompatCache(File directory, long maxSize) {
      cache = new DiskLruCache(FileSystem.SYSTEM, directory, VERSION, ENTRY_COUNT, maxSize, TaskRunner.INSTANCE);
    }

    private final DiskLruCache cache;

    @Override
    public @Nullable ResponseCacheRecord cacheRecord(@NotNull String s) throws IOException {
      DiskLruCache.Snapshot snapshot = cache.get(s);
      if (snapshot == null) return null;

      return new ResponseCacheRecord() {
        @Override
        public @NotNull Source headerSource() {
          return snapshot.getSource(ENTRY_HEADERS);
        }

        @Override
        public @NotNull Source bodySource() {
          return snapshot.getSource(ENTRY_BODY);
        }

        @Override
        public void close() {
          snapshot.close();
        }
      };
    }

    @Override
    public @Nullable ResponseCacheRecordEditor cacheRecordEditor(@NotNull String s) throws IOException {
      DiskLruCache.Editor editor = cache.edit(s);
      if (editor == null) return null;

      return new ResponseCacheRecordEditor() {
        @Override
        public @NotNull Sink headerSink() {
          return editor.newSink(ENTRY_HEADERS);
        }

        @Override
        public @NotNull Sink bodySink() {
          return editor.newSink(ENTRY_BODY);
        }

        @Override
        public void abort() throws IOException {
          editor.abort();
        }

        @Override
        public void commit() throws IOException {
          editor.commit();
        }
      };
    }

    @Override
    public void delete() throws IOException {
      cache.delete();
    }

    @Override
    public void remove(@NotNull String s) throws IOException {
      cache.remove(s);
    }
  }
}

That does the same thing as what Shopify does. But now there are other issues :

  1. HttpDate is missing (simple fix copy previous java impl from old okhttp version)
  2. HttpHeaders does not expose varyHeaders and that's an issue where I'm blocked at the moment because there are already a HttpHeaders class in the aar of okhttp.

@TimoPtr
Copy link

TimoPtr commented Apr 22, 2021

It seems like the only solutions are:

  1. wait for Shopify to fix this
  2. don't use cache

@Faves
Copy link

Faves commented Oct 10, 2022

Any update about this ?

Because of some bug with Android O devices, i must use a recent version of okhttp (at least 3.9.1) : square/okhttp#3438

Because of some incompatibility between mobile-buy-sdk-android and okhttp 4.x (cf first comment of this issue describe by keepmovingljzy), i use okhttp 3.14.9.

But i encounter an issue reported many times by crashlytics with this version :
okhttp3.internal.cache.DiskLruCache.checkNotClosed
Fatal Exception: java.lang.IllegalStateException: cache is closed
at okhttp3.internal.cache.DiskLruCache.checkNotClosed(DiskLruCache.java:645)
at okhttp3.internal.cache.DiskLruCache.remove(DiskLruCache.java:607)
at com.shopify.buy3.internal.cache.DiskLruCacheStore.remove(DiskLruCacheStore.kt:99)
at com.shopify.buy3.internal.cache.HttpCache.removeQuietly(HttpCache.kt:72)
at com.shopify.buy3.internal.GraphHttpResultCallback.purge(RealGraphCall.kt:337)
at com.shopify.buy3.internal.GraphHttpResultCallback.onResponse(RealGraphCall.kt:321)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:174)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
at java.lang.Thread.run(Thread.java:1012)

I cannot use solution proposed by PiotrWpl and TimoPtr to implement ResponseCacheStore because of ResponseCacheStore is internal.
I prefere to not modify lib mobile-buy-sdk-android.

Coult it be possible to Shopify to fix this by used the last version of okhttp (or at least okhttp 4.x) ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants