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

HAPI Structures, Java11, and Android API levels #1627

Open
jingtang10 opened this issue Sep 23, 2022 · 8 comments · Fixed by #1616
Open

HAPI Structures, Java11, and Android API levels #1627

jingtang10 opened this issue Sep 23, 2022 · 8 comments · Fixed by #1616
Assignees
Labels
P1 High priority issue type:process Create or improve processes

Comments

@jingtang10
Copy link
Collaborator

This is an issue @vitorpamplona raised in the process of implementing #1403.

PR #1603 introduces new dependencies such as CQL evalutor, CQL engine, and CQL translator. They use HAPI version 6.0.1 which is compiled using Java11. There are certain Java11 APIs that are not available on older Android versions, especially pre Android API 26. For example, java.lang.reflect.Method.getParameterCount().

As a result, with this PR, the workflow library will crash on Android API level 24. Please note, however, that although the API java.lang.reflect.Method.getParameterCount() is used in HAPI, we do not invoke code paths in HAPI using this API through our usage in the FHIR Engine and SDC library. Only in the workflow library in this PR. In other words, when I tested the FHIR Engine and SDC library with HAPI 6 on Android API level 24, there's no crash caused by the missing of this API.

Android API levels 26+ support Java11 APIs. So the above PR works fine in Android API 26+. This means that we will need to update the min api level for the workflow library to API 26.

At the moment, our gradle files are written so that all libraries share the same min api level. This will need to be changed so we do not raise API level above 24 for users of FHIR engine and SDC library.

cc: @joiskash

@jingtang10 jingtang10 added the type:process Create or improve processes label Sep 23, 2022
@jingtang10
Copy link
Collaborator Author

See related issue: hapifhir/hapi-fhir#3690

Under this issue, let's create a PR to diverge the Engine and SDC API level from workflow API level.

@jingtang10 jingtang10 linked a pull request Sep 23, 2022 that will close this issue
7 tasks
@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Sep 23, 2022

A few more learnings from this process: MinSDK 26 is the sweet spot. It offers enough runtime API to support all of the test cases in this project while removing desugaring which doubles the compilation speed. It's a win-win. We could go down to 24 with desugaring in the engine + SDC and keep the workflow on 26. I don't think this project works with <= 23 anymore (we haven't been testing for such low SDKs).

Issues that can be resolved with current Desugaring lib

Uses of java.time by this project, by HAPI 6, and by Caffeine require MinSDK 26 or Desugaring w/ 24, which provides a workable subset of java.time and a fixed ConcurrentHashMap for caching solutions.

The version of Kotlin's Stdlib must match the desugaring + minSDK strategy as well. This link provides good information to choose correctly when migrating.

Issues that can be resolved with newer Desugaring

The version of the desugaring library (com.android.tools:desugar_jdk_libs) indicates what API methods will be available. The version we use is quite old 1.1.5, but updating to 2.0.0 while on min SDK 24 triggers RuntimeExceptions on android.content.pm.PackageParser$PackageParserException at PackageParser.java for the data capture module. We can't update this lib until we solve this issue.

Issues that cannot be resolved with Desugaring but can be fixed by minSDK 26

CQLEngine 2.0, HAPI-fhir-base 5 and some versions of Jackson (2.13.2) make use of java.lang.reflect.Method.getParameterCount() which is not available before 26. We have overridden those Jackson versions with corrected versions, but it might come back. For example, the use of hapi-fhir-base's PropertyModifyingHelper will crash the app on runtime.

Right now this means that the workflow module absolutely requires min SDK 26.

java.nio.file, which is now frequently used by HAPI, is not available before 26. This doesn't break our test cases yet, but with NPM Package Manager (@ktarasenko) being based on filesystem, we can expect heavy use of this new API in the near future.

Issues that cannot be resolved by us.

HAPI's dependency Caffeine 3.0 is not compatible with Android due to the widespread use of JEP-264: Platform Logging API's System.getLogger to redirect logs to slf4. System.getLogger is not provided by either desugaring or newer versions of the SDK. For now, we have to force Caffeine ~2.9

CQLTranslator is graciously helping us by forcing the use of Woodstox for now. The default XmlFactory provided by Jackson calls a Streaming API for XML (StAX) javax.xml.stream.XMLInputFactory.newFactory function that does not exist on Android: javax.xml.stream.XMLInputFactory.newFactory

Uses of java.util.Optional.isEmpty() in any dependent library will only work on SDK 33+

Uses of java.util.List.toArray(java.util.function.IntFunction) will not work on any Android version.

@jingtang10
Copy link
Collaborator Author

jingtang10 commented Sep 23, 2022

thanks for the excellent write-up vitor. i've created #1628.

@vitorpamplona
Copy link
Collaborator

vitorpamplona commented Sep 25, 2022

After some deeper analysis, I can say that the HAPI dependencies we use (base + structures + validators + resources) are fully compliant with SDK 26

They are not compliant with 24, even with desugaring on.

Here are the problems:

[ERROR] ~/hapi-fhir-base/../../BundleUtil.java:299: Undefined reference: String String.join(CharSequence, Iterable)
[ERROR] ~/hapi-fhir-base/../../TimeoutManager.java: Undefined reference: java.time.Duration
[ERROR] ~/hapi-fhir-base/../../TimeoutManager.java: Undefined reference: java.time.Duration
[ERROR] ~/hapi-fhir-base/../../TimeoutManager.java:53: Undefined reference: long java.time.Duration.toMillis()
[ERROR] ~/hapi-fhir-base/../../TimeoutManager.java:58: Undefined reference: long java.time.Duration.toMillis()
[ERROR] ~/hapi-fhir-base/../../TimeoutManager.java:72: Undefined reference: long java.time.Duration.toMillis()
[ERROR] ~/hapi-fhir-base/../../PropertyModifyingHelper.java:77: Undefined reference: int java.lang.reflect.Method.getParameterCount()
[ERROR] ~/hapi-fhir-base/../../DateUtils.java:109: Undefined reference: ThreadLocal ThreadLocal.withInitial(java.util.function.Supplier)
[ERROR] ~/hapi-fhir-base/../../RequestPartitionId.java: Undefined reference: java.time.LocalDate
[ERROR] ~/hapi-fhir-base/../../RequestPartitionId.java:102: Undefined reference: java.time.LocalDate

@Tarun-Bhardwaj Tarun-Bhardwaj added the P1 High priority issue label Oct 18, 2022
@Tarun-Bhardwaj
Copy link

@vitorpamplona , can this issue be closed since the related PR is already merged?
CC: @jingtang10

@vitorpamplona
Copy link
Collaborator

Yep. This was solved

@vitorpamplona
Copy link
Collaborator

@Tarun-Bhardwaj I would turn this into a schedule of MinSDK changes. The issues discussed here go away with minSDK 26 (we are sticking to 24 right now). At some point in the future, the engine will have to move to 26. The earliest we can commit to a date, the better the developer experience using the SDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P1 High priority issue type:process Create or improve processes
Projects
Status: In Progress
Development

Successfully merging a pull request may close this issue.

3 participants