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
17.03k stars 6.03k forks source link

Cannot get generated Android client to work, DexException because of apache http client #4069

Open mortenhn1981 opened 8 years ago

mortenhn1981 commented 8 years ago

Hi.

Been testing the mobil generated clients (swift, objc, android/java) objective c and swift works great, but i have not been able to get android to work. First i used the client with the apache.http client dependency, but android kept refusing to install the test app i created to a device because of the internal apache http client. I then tried the Volly version, but to my suprise it still depends on the apache http client, at least the version im getting generated from the swagger codegen, so i have the same problem, i cannot make android studio build the test app to a device-

Then i tried the java one with the okhttp-gson but i cant even get android studio to work with it, i must be doing something wrong. I dont know if its me but it seems very hard to get the Swagger codegen to generate anything that can work with android studio and build to a device in a test project.

When trying to deploy my test app to device, with the Android/Volly client i get this error:

"Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.
> com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK META-INF/LICENSE
    File1: C:\Users\morten.nielsen\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpmime\4.5.2\22b4c53dd9b6761024258de8f9240c3dce6ea368\httpmime-4.5.2.jar
    File2: C:\Users\morten.nielsen\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpclient-android\4.3.3\39ba75b570e5f1535356e8a1bf920b1c6cc83a9a\httpclient-android-4.3.3.jar
    File3: C:\Users\morten.nielsen\.gradle\caches\modules-2\files-2.1\org.apache.httpcomponents\httpcore\4.4.4\b31526a230871fbe285fbcbe2813f9c0839ae9b0\httpcore-4.4.4.jar"

If i ignore the license file like this:

"        packagingOptions {
            exclude 'META-INF/DEPENDENCIES.txt'
            exclude 'META-INF/LICENSE.txt'
            exclude 'META-INF/NOTICE.txt'
            exclude 'META-INF/NOTICE'
            exclude 'META-INF/LICENSE'
            exclude 'META-INF/DEPENDENCIES'
            exclude 'META-INF/notice.txt'
            exclude 'META-INF/license.txt'
            exclude 'META-INF/dependencies.txt'
            exclude 'META-INF/LGPL2.1'
        }"

i get this error:

"Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexException: Multiple dex files define Lorg/apache/http/Consts;"

Im using the latest version of swagger-codegen to date

im using this command line tool to generate it: java -jar swagger-codegen-cli.jar generate -i [path] -l android --library=volley -o /var/tmp/android/volley/

I dont know what the problem is, i use the generated client in a complete empty project with an empty activity. only thing i have done with the Android/Volly is to add it to my test project as a module and sync/build and run on device.

Im also getting the dependency warnings: Warning: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: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.

wing328 commented 8 years ago

@mortenhn1981 thanks for reporting the issue. Which version of Swagger Codegen are you using? Have you tried the latest master to generate Android API client (volley)?

mortenhn1981 commented 8 years ago

@wing328 thank you for your reply.

java -jar swagger-codegen-cli.jar version

Gives me this result: "2.2.2-SNAPSHOT"

wing328 commented 8 years ago

@mortenhn1981 the auto-generated API client comes with an auto-generated README.md, which contains installation instruction. Did you follow that or installing the SDK/API client via other approaches?

wing328 commented 8 years ago

I definitely use the Android SDK (volley) with Android Studio 2.0 myself before and didn't encounter the issue you mentioned above.

mortenhn1981 commented 8 years ago

@wing328

I must admit that i totally missed the REDME.md. I just went through the steps with the Android/volly library and im still getting the same error.

"Error:Execution failed for task ':app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexException: Multiple dex files define Lorg/apache/http/Consts;"

BUT i also went through the steps with the okhttp-gson java library and that is working great, just made my request and no problem at all.

As far as i can see the android/volly still have the apache.http client as a dependency and that is the reason why i cant get that to build. As far as i understand it clashes with the internal httpclient.

wing328 commented 8 years ago

@mortenhn1981 glad to hear that okhttp-gson client is working for you. Is there by any chance you're using other libraries, which have a dependency on apache.http client?

For volley, I think we better off removing apache.http client as a dependency.

mortenhn1981 commented 8 years ago

@wing328 i have been testing in completly empty and newly created projects to be sure that i was not poluting any result i may get. One empty project for the Swagger Android library and a different empty project for the java one, so only thing contained is what the Swagger.IO project brings to the party :)

Ive searched alot on this issue and did not find alot of info, so i dont know if im the only one having this problem, or if the Android package is just not being used by that many yet.

Anyway the java one is working really well and as planed in a Android project, so you could consider cutting down development time and remove the Android one and rename the Java one to something like Java/Android :) but that is just my two cent.

Thanks for working on this great project, i think its really powerful and awesomely useful!

Isanderthul commented 8 years ago

So I had a similar problem, but it was at the start of my project, what I ended up doing was removing some of the dependencies, which I figured out were competing with other libraries I was using in my file app/build.gradle

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
 ...
    compile('io.swagger:swagger-java-client:1.2.3-TT') {
        exclude group: 'org.json', module: 'json'
        exclude group: 'org.apache.oltu.oauth2', module: 'org.apache.oltu.oauth2.common'
        changing = true
    }
...
}
Isanderthul commented 8 years ago

just as an aside I think it is better to use pickfirst instead of exclude

    packagingOptions {
        pickFirst 'META-INF/DEPENDENCIES.txt'
        pickFirst 'META-INF/LICENSE.txt'
        pickFirst 'META-INF/NOTICE.txt'
        pickFirst 'META-INF/NOTICE'
        pickFirst 'META-INF/LICENSE'
        pickFirst 'META-INF/DEPENDENCIES'
        pickFirst 'META-INF/notice.txt'
        pickFirst 'META-INF/license.txt'
        pickFirst 'META-INF/dependencies.txt'
        pickFirst 'META-INF/LGPL2.1'
    }
Isanderthul commented 8 years ago

To check dependencies ./gradlew app:dependencies

gsantner commented 7 years ago

It would be a lot better if the generated swagger client could be just included just by specifing it as a gradle subproject. Deploying to a local maven repository and so on makes it quite unmaintanable and the way around is really not needed.

wing328 commented 7 years ago

@gsantner may I know if you've time to contribute the enhancement?

sdetweil commented 7 years ago

is there a reasonable fix for a non gradle wizard?? I have the javascript client (and server) working fine.. now I want to make a mobile app. but I can't get past this redundant library packaging problem

the gradlew app:dependencies doesn't show the httpclient problem, but the dex converter hits it..

can't even run the test app in the generated code.

but in the long term I want to use the generated library (dll/jar/aar, whatever), as a lib in my android, xamarin/... app, using visual or android studio which don't use gradle or maven

Isanderthul commented 7 years ago

@sdetweil I agree the process is extremely difficult, and a barrier to using swagger-codegen. Do you mind sharing your dependencies? I think this needs to be further worked on to make a tutorial or blog on how to solve these. I have found the reward of using swagger-codegen far outweighs these problems. When I started I struggled greatly with documentation and how to get it working.

wing328 commented 7 years ago

@mortenhn1981 @Isanderthul @gsantner @sdetweil thanks for sharing more with this particular issue. I think we can work together to make the Android (volley) API client better.

I started with https://github.com/swagger-api/swagger-codegen/pull/4384 (merged) to improve the code quality of Android (volley) API client a bit. Let me know if you've any feedback.

Next, I wonder if you guys can adding the following to the build.gradle in your project to see if it fixes the dependency issue:

android{
 useLibrary  'org.apache.http.legacy'
}

Ref: http://stackoverflow.com/a/32065636/677735

cc @tgraupmann who has been doing some work in the Android API client.

gconst02 commented 7 years ago

This might serve as a temporary fix until HttpClient dependency is removed:

Have a project with minSdkVersion 14, targetSdkVersion 25 and Android/Volley client. Initially got the error above:

Error:Execution failed for task ':app:transformClassesWithDexForRelease'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexException: Multiple dex files define Lorg/apache/http/Consts;

Then added in my main project build.gradle (seems too many methods):

android {
...
multiDexEnabled true
}

and get

Error:Execution failed for task ':app:transformClassesWithJarMergingForRelease'.
> com.android.build.api.transform.TransformException: java.util.zip.ZipException: duplicate entry: org/apache/http/MessageConstraintException.class

To temporarily fix it I changed in the build.gradle of the Volley client:

dependencies {
...
     compile "org.apache.httpcomponents:httpclient-android:$httpclient_version"
...
}

with

dependencies {
...
    compile "cz.msebera.android:httpclient:4.4.1.2"
...
}

More here: https://hc.apache.org/httpcomponents-client-4.5.x/android-port.html and https://github.com/smarek/httpclient-android/wiki/Project-Introduction

Now the release apk is compiled but left with a bunch of warnings:

Warning: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.
gsantner commented 7 years ago

I used the listed commands here (https://github.com/froodyapp/froody-extras/blob/master/server/swagger-generation.txt) to generate the android client. Used it in one of my apps ((https://github.com/froodyapp/froody-android). Works, and without apache http dependency.

sytolk commented 7 years ago

@wing328 instead of trying to do Android Volley client "better". Why not focus on better retrofit2 client for Android? I can contribute for this but I don`t know why its need to have OAuth2 and dependency to Apache Oltu (this will not work for Android) its have Basic Auth included I think its wrong Client to support two Auth methods. Its better to switch the Authorization.

wing328 commented 7 years ago

@sytolk I've been recommending Java retrofit2/okhttp-gson client for Android. Previously I suggested simply sunsetting the Android generator as it would make our life easier to maintain one Java API client generator to generate a client that works on both Java and Android. But there are demands to use Android volley in the API client and that's why we keep the Android generator.

dependency to Apache Oltu (this will not work for Android)

I didn't know that.

I think its wrong Client to support two Auth methods. Its better to switch the Authorization.

Can you please elaborate a bit more on "switch the Authorization"?

sytolk commented 7 years ago

@wing328 I have define in my RestService swagger annotation:

@ApiOperation(
          value = "Get a UserConfiguration resource."
          ,authorizations = @Authorization(value = "basic")
  )

And I have expect that in client I will have code generated for Basic Authorization only. There is no reason that I have Apache Oltu included like dependency. I have view the template and there is no switch like: if(isBasic).. else if(isOAuth)

wing328 commented 7 years ago

@sytolk right. Do you mind opening a new issue to track this?

sytolk commented 7 years ago

Issue: https://github.com/swagger-api/swagger-codegen/issues/5273 @wing328 I cannot find official Gitter channel to swagger-codegen ?

red61wjt commented 6 years ago

If you are using the volley client, which is the default, then you can remove 2 of the dependencies from the generated pom file

<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpcore</artifactId>
  <version>${httpcomponents-httpcore-version}</version>
</dependency>
<dependency>
  <groupId>org.apache.httpcomponents</groupId>
  <artifactId>httpclient-android</artifactId>
  <version>${httpcomponents-httpclient-version}</version>
</dependency>

You only need httpmime

this change fixed the duplicate class issue for me