JetBrains / lets-plot-kotlin

Grammar of Graphics for Kotlin
https://lets-plot.org/kotlin/
MIT License
444 stars 38 forks source link

"Duplicate class .. found in modules ..." triggered by appcompat and lets-plot-common libraries #21

Closed descent2oblivion closed 2 years ago

descent2oblivion commented 4 years ago

I am using the kotlin lets plot api, which works 100% on jupyter and in standalone apps,

however I'm trying to use it on an android app and at the moment to build I get a bunch of errors that say like this

Duplicate class kotlin.ArrayIntrinsicsKt found in modules jetified-kotlin-stdlib-1.3.72.jar (org.jetbrains.kotlin:kotlin-stdlib:1.3.72) and jetified-lets-plot-common-1.3.1.jar (org.jetbrains.lets-plot:lets-plot-common:1.3.1)

and

Duplicate class org.jetbrains.annotations.TestOnly found in modules jetified-annotations-13.0.jar (org.jetbrains:annotations:13.0) and jetified-lets-plot-common-1.3.1.jar (org.jetbrains.lets-plot:lets-plot-common:1.3.1)

I understand that I have to choose only one of the libraries to be compiled, but if I remove lets-plot from the gradle the project renders unusable at 'grafica.kt'

My question is:

Can I remove 'org.jetbrains.kotlin:kotlin-stdlib:1.3.72' and 'org.jetbrains:annotations:13.0' safely? and If so, how can I do this?

Thanks in advance!

Project description: User inputs two numbers and the app displays a plot of them

I've opened the same issue at :

https://youtrack.jetbrains.com/issue/KT-39737

where I've attached a sample project

Plot_app.zip

alshan commented 4 years ago

Can I remove 'org.jetbrains.kotlin:kotlin-stdlib:1.3.72' and 'org.jetbrains:annotations:13.0' safely? and If so, how can I do this?

Hi, did you try this?

I can also suggest to download lets-plot-common-1.4.2.jar from https://bintray.com/beta/#/jetbrains/lets-plot-maven/lets-plot-jars/1.4.2?tab=overview and remove Kotlin from the archive like: zip -d lets-plot-common-1.4.2.jar kotlin/\* then try to build Android app with this jar. If this works we can start publishing no-Kotlin jar along with the current artifacts.

ilya-g commented 4 years ago

It looks like lets-plot-common.jar artifact is an uber-jar that bundles classes from all of its dependencies, including kotlin-stdlib. This approach can cause problems in certain environments, for example in the modular Java environment on the module path or in Android apps as described above.

Consider providing your main artifact lets-plot-api that lists all its dependencies as plain dependencies instead of bundling them, and provide an uber-jar if needed as a distinct artifact variant or a separate artifact.

descent2oblivion commented 4 years ago

Hi! I've excluded 'org.jetbrains:annotations:13.0' safely using this code in the build.gradle (:app)

configurations{
    implementation.exclude(group: "org.jetbrains", module: "annotations")
}

Download lets-plot-common-1.4.2.jar ... and remove Kotlin from the archive

Doing so breaks the lib and at build time I get the followng error

\grafica.kt: (4, 18): Unresolved reference: datalore

I've created a repo of the project as is at this moment:

https://github.com/descent2oblivion/plot-app

alshan commented 4 years ago

@descent2oblivion I've done what @ilya-g suggested. Could you try upgrading to lets-plot-kotlin-api 0.0.22-SNAPSHOT ? It depends on lets-plot-common 1.4.3-SNAPSHOT which is clear from Kotlin and other external dependencies.

descent2oblivion commented 4 years ago

@alshan I've done it and it works fine now. I'm figuring how to render the plot, my current plan is to use the exportToHTML function and render the result in a WebView.

Thanks for the help!

alshan commented 4 years ago

Yes, exportToHTML will work, especially if you need all in iFrame.

Alternatively, if you need several plots on one page you can generate the header and the plot JS separately, as shown here https://github.com/JetBrains/lets-plot-kotlin/blob/28628688a1adc0619e9a8568ee0670082d8fdd28/demo/browser/src/main/kotlin/frontendContextDemo/BrowserDemoFrontendContext.kt

This is if you generate static HTML page and then show it in WebView. If you inject JS dynamically you will have to replace all PlotHtmlHelper.getStaticXXX with PlotHtmlHelper.getDynamicXXX equivalents.

descent2oblivion commented 4 years ago

Hi! Thanks for the support, the app now works 100%

I'm sharing screens of it:

Screenshot_20200701-215801 Screenshot_20200701-215812

I've updated the repo too

https://github.com/descent2oblivion/plot-app

alshan commented 4 years ago

Hi again! The latest Kotlin api snapshot (0.0.26-SNAPSHOT) is built with compileOnly dependency on lets-plot-image-export jar which is dependent on Batik transcoder (See build.gradle).

Could you check please if your android app would have any building problems with this snapshot?

Cool shot BTW ): lets-plot-android

descent2oblivion commented 4 years ago

Hey there! Glad to see you! Sure I've already updated the app to use:

org.jetbrains.lets-plot:lets-plot-kotlin-api:0.0.26-SNAPSHOT

And the app performs fine, I think I noticed that the plot generation time decreased like 1-2 seconds for plots generated after the first one (or maybe it's just me)

And thanks! I'm working on translations (es/en/ru) to publish it sometime near :)

Screenshot_20200804-180914

I hope you are doing great! Best regards :)

alshan commented 4 years ago

time decreased like 1-2 seconds for plots generated after the first one

Might be because JS lib is being loaded with the 1st plot and then cached.