swagger-api / swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.
http://swagger.io
Apache License 2.0
16.91k stars 6.03k forks source link

[Client:Android] HttpClient Timeout or Dependency Issues #4300

Open tgraupmann opened 7 years ago

tgraupmann commented 7 years ago
Description

I'm using the Swagger Android export to autogenerate the structures and client code for a REST API. I made a tool to apply some JAVA syntax fixes to get the Android Studio project to compile. I have some Gradle compile issues (upgrade, and dependency) that I apply so that the APK can be created. And then when using the EndPoint, I'm getting timeouts and the client doesn't appear to connect at all. This could either be a client, or dependency issue.

Swagger-codegen version

I'm using the online editor so maybe 2.0? http://editor.swagger.io/#/

Swagger declaration file content or url

In the Swagger editor, load the URL: https://polling.arena.razerzone.com/swagger/docs/v1

Command line used for generation

Generate Client for Android.

Steps to reproduce
  1. Load the url in the editor.

  2. Generate the Android Client.

  3. Unzip and open the project in Android Studio.

  4. Upgrade gradle when prompted.

  5. I've made a temporary Windows.Form tool that you run on the root Android project directory to fix the enum and Object syntax errors.

https://github.com/tgraupmann/SwaggerAndroidClientFixer

  1. Add an Android app module with an Activity and reference the library. Here's some Gradle info for the build tools and target API versions.
android {
    compileSdkVersion 23
    buildToolsVersion '23.0.2'
    defaultConfig {
        minSdkVersion 14
        targetSdkVersion 23
  1. Rebuild the project.

  2. At this point Gradle warnings will appear. Are these warnings important?

Warning:Dependency org.apache.httpcomponents:httpclient:4.5.2 is ignored for debug as it may be conflicting with the internal version provided by Android.
Warning:Dependency org.apache.httpcomponents:httpclient:4.5.2 is ignored for release as it may be conflicting with the internal version provided by Android.
Warning:Dependency org.apache.httpcomponents:httpclient:4.5.2 is ignored for debugAndroidTest as it may be conflicting with the internal version provided by Android.
Warning:Dependency org.apache.httpcomponents:httpclient:4.5.2 is ignored for debug as it may be conflicting with the internal version provided by Android.
Warning:Dependency org.apache.httpcomponents:httpclient:4.5.2 is ignored for release as it may be conflicting with the internal version provided by Android.
  1. Hit Run which will display Gradle errors. What's the best way to resolve these errors?
Error:Execution failed for task ':swaggerapp:transformResourcesWithMergeJavaResForDebug'.
> com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK META-INF/LICENSE
    File1: C:\Users\timot\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpclient-android\4.3.3\39ba75b570e5f1535356e8a1bf920b1c6cc83a9a\httpclient-android-4.3.3.jar
    File2: C:\Users\timot\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.4\b31526a230871fbe285fbcbe2813f9c0839ae9b0\httpcore-4.4.4.jar
    File3: C:\Users\timot\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpmime\4.5.2\22b4c53dd9b6761024258de8f9240c3dce6ea368\httpmime-4.5.2.jar
  1. Is this Gradle setting the best way to deal with the above error?
android {
    packagingOptions {
        exclude 'META-INF/LICENSE'
    }
}
  1. Using the above fix, what’s the best way to resolve these errors?
Error:Execution failed for task ':swaggerapp:transformResourcesWithMergeJavaResForDebug'.
> com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK META-INF/DEPENDENCIES
    File1: C:\Users\timot\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.4\b31526a230871fbe285fbcbe2813f9c0839ae9b0\httpcore-4.4.4.jar
    File2: C:\Users\timot\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpmime\4.5.2\22b4c53dd9b6761024258de8f9240c3dce6ea368\httpmime-4.5.2.jar
  1. Is this Gradle setting the best way to deal with the above error?
android {
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
    }
}
  1. The following activity code should use the Swagger Android client. The expected result would be a 200 status with an error message about needing a client API key. Instead I get a timeout.
package com.example.swaggerapp;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

import io.swagger.client.api.LookupsControlEndpointApi;
import io.swagger.client.model.ResponseOutputModelListGamingServerRegionModel;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Handler handler = new Handler();
        handler.post(new Runnable() {
            @Override
            public void run() {
                LookupsControlEndpointApi apiInstance = new LookupsControlEndpointApi();
                try {
                    Log.d(TAG, "*** Invoke: lookupsGamingServerRegions");
                    ResponseOutputModelListGamingServerRegionModel result = apiInstance.lookupsGamingServerRegions();
                    Log.d(TAG, "*** Got Result: lookupsGamingServerRegions");
                    System.out.println(result);
                } catch (Exception e) {
                    Log.d(TAG, "*** Exception: lookupsGamingServerRegions");
                    Toast.makeText(MainActivity.this, "Exception when calling LookupsControlEndpointApi#lookupsGamingServerRegions", Toast.LENGTH_LONG).show();
                    e.printStackTrace();
                }
            }
        });

    }
}
  1. Given that the client runs, the Android Client gets a timeout unable to connect to the REST services. Is this caused by the fixes above?
11-30 11:33:52.769 18605-18605/com.example.swaggerapp I/art: Late-enabling -Xcheck:jni
11-30 11:33:52.859 18605-18605/com.example.swaggerapp W/System: ClassLoader referenced unknown path: /data/app/com.example.swaggerapp-1/lib/arm
11-30 11:33:52.863 18605-18605/com.example.swaggerapp I/InstantRun: Instant Run Runtime started. Android package is com.example.swaggerapp, real application class is null.
11-30 11:33:54.058 18605-18605/com.example.swaggerapp W/System: ClassLoader referenced unknown path: /data/app/com.example.swaggerapp-1/lib/arm
11-30 11:33:54.211 18605-18719/com.example.swaggerapp D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
11-30 11:33:54.285 18605-18605/com.example.swaggerapp D/MainActivity: *** Invoke: lookupsGamingServerRegions
11-30 11:33:54.312 18605-18738/com.example.swaggerapp W/System: ClassLoader referenced unknown path: /system/framework/tcmclient.jar
11-30 11:34:24.292 18605-18605/com.example.swaggerapp D/MainActivity: *** Exception: lookupsGamingServerRegions
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err: java.util.concurrent.TimeoutException
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at com.android.volley.toolbox.RequestFuture.doGet(RequestFuture.java:121)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at com.android.volley.toolbox.RequestFuture.get(RequestFuture.java:97)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at io.swagger.client.ApiInvoker.invokeAPI(ApiInvoker.java:381)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at io.swagger.client.api.LookupsControlEndpointApi.lookupsGamingServerRegions(LookupsControlEndpointApi.java:620)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at com.example.swaggerapp.MainActivity$1.run(MainActivity.java:30)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at android.os.Handler.handleCallback(Handler.java:739)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at android.os.Looper.loop(Looper.java:148)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5461)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
11-30 11:34:24.325 18605-18605/com.example.swaggerapp W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
11-30 11:34:24.326 18605-18605/com.example.swaggerapp I/Choreographer: Skipped 1805 frames!  The application may be doing too much work on its main thread.
11-30 11:34:24.347 18605-18719/com.example.swaggerapp I/OpenGLRenderer: Initialized EGL, version 1.4
11-30 11:34:24.372 18605-18719/com.example.swaggerapp D/mali_winsys: new_window_surface returns 0x3000
11-30 11:34:24.521 18605-18719/com.example.swaggerapp D/mali_winsys: new_window_surface returns 0x3000
11-30 11:34:24.566 18605-18719/com.example.swaggerapp V/RenderScript: 0xb7d04990 Launching thread(s), CPUs 2
Related issues

https://github.com/swagger-api/swagger-codegen/issues/4279 https://github.com/swagger-api/swagger-codegen/issues/4278

Suggest a Fix

I need insight to what might be happening.

I'm using a tool to make syntax fixes when I should fix the raw export templates.

From debugging, it looks like the Swagger client puts a request in the queue and waits for the request to complete. The request might not actually happen...

wing328 commented 7 years ago

@tgraupmann can you try using the Java API client instead to see if it works better for you?

https://github.com/swagger-api/swagger-codegen/wiki/FAQ#how-can-i-generate-an-android-sdk

tgraupmann commented 7 years ago

I can confirm that the JAVA exported code when imported into Android Studio and run on Windows works as expected.

I will attempt on Android to do further testing...

Found that the JAVA export uses okhttp1 and needed to upgrade to okhttp3. But after that I'm seeing responses on Android.

The Client methods need to be called from a Thread to avoid a networking on main thread exception.

I automated the JAVA source fixes to upgrade to okhttp3 in another Windows.Forms app. https://github.com/tgraupmann/SwaggerJavaClientFixer

Progress...

tgraupmann commented 7 years ago

These are the changes that I made to make the Swagger JAVA client work on Android. https://github.com/tgraupmann/SwaggerJavaExportFixes/commit/908d7dbf4ebd30087ecb7dc5387b0893de70843b

The https://github.com/tgraupmann/SwaggerJavaClientFixer automates fixing the JAVA source.

Editing the Gradle build and adding the SwaggerApp module was done manually.

tgraupmann commented 7 years ago

I ran into some JSON date parsing issues related to: http://stackoverflow.com/questions/21839143/jodatime-string-yyyy-mm-ddthhmmss-z-to-datetime

I altered io.swagger.client.JSON.java to use the suggested DateTime parser.

    @Override
    public DateTime read(JsonReader in) throws IOException {
        switch (in.peek()) {
            case NULL:
                in.nextNull();
                return null;
            default:
                String date = in.nextString();
                //return formatter.parseDateTime(date); //old
                return DateTime.parse(date, ISODateTimeFormat.dateTimeParser());
        }
    }