[Android] java.lang.NoSuchMethodError: No static method decodeBase64 when fetching Patient resource
issue
I'm building a personal health info app on Android using Android Studio.
When trying a test to fetch a patient data from https://fhirtest.uhn.ca/, it fails on error:
java.lang.NoSuchMethodError: No static method decodeBase64(Ljava/lang/String;)[B in class Lorg/apache/commons/codec/binary/Base64; or its super classes (declaration of 'org.apache.commons.codec.binary.Base64' appears in /system/framework/org.apache.http.legacy.boot.jar) at org.hl7.fhir.r4.model.Base64BinaryType.parse(Base64BinaryType.java:61) at org.hl7.fhir.r4.model.Base64BinaryType.parse(Base64BinaryType.java:38) at org.hl7.fhir.r4.model.PrimitiveType.fromStringValue(PrimitiveType.java:79) at org.hl7.fhir.r4.model.PrimitiveType.setValueAsString(PrimitiveType.java:135) at ca.uhn.fhir.parser.ParserState$PrimitiveState.attributeValue(ParserState.java:1288) at ca.uhn.fhir.parser.ParserState.attributeValue(ParserState.java:66) at ca.uhn.fhir.parser.JsonParser.parseChildren(JsonParser.java:1047) at ca.uhn.fhir.parser.JsonParser.parseChildren(JsonParser.java:952) at ca.uhn.fhir.parser.JsonParser.parseChildren(JsonParser.java:1035) at ca.uhn.fhir.parser.JsonParser.parseChildren(JsonParser.java:1016) at ca.uhn.fhir.parser.JsonParser.parseChildren(JsonParser.java:952) at ca.uhn.fhir.parser.JsonParser.doParseResource(JsonParser.java:183) at ca.uhn.fhir.parser.JsonParser.doParseResource(JsonParser.java:165) at ca.uhn.fhir.parser.BaseParser.parseResource(BaseParser.java:668) at ca.uhn.fhir.parser.BaseParser.parseResource(BaseParser.java:653) at ca.uhn.fhir.rest.client.impl.BaseClient$ResourceResponseHandler.invokeClient(BaseClient.java:578) at ca.uhn.fhir.rest.client.impl.BaseClient$ResourceResponseHandler.invokeClient(BaseClient.java:530) at ca.uhn.fhir.rest.client.impl.BaseClient.invokeClient(BaseClient.java:380) at ca.uhn.fhir.rest.client.impl.GenericClient.doReadOrVRead(GenericClient.java:134) at ca.uhn.fhir.rest.client.impl.GenericClient.access$2600(GenericClient.java:66) at ca.uhn.fhir.rest.client.impl.GenericClient$ReadInternal.execute(GenericClient.java:1535) at com.dtc.patientportalmobil.MyFhirHelper.searchPatient(MyFhirHelper.java:383) at com.dtc.patientportalmobil.HealthCenterFragment$MyAsyncTask.doInBackground(HealthCenterFragment.java:312) at com.dtc.patientportalmobil.HealthCenterFragment$MyAsyncTask.doInBackground(HealthCenterFragment.java:286) at android.os.AsyncTask$2.call(AsyncTask.java:333) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:245)Â at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)Â at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)Â at java.lang.Thread.run(Thread.java:764)Â
My code snippet
Patient patient = client.read().resource(Patient.class).withId(id).execute();
Environment (please complete the following information):
- HAPI FHIR Version 3.8.0 hapi-fhirandroid:3.8.0 hapi-fhir-structures-r4:3.8.0
- OS: Android
Additional context Not every patient ID causes the error. And my guess is hapi-fhir-structures-r4 include the library commons-codec-1.11.jar, but Android's base framework include an old version commons-codec, which causes the conflict.
I can confirm the cause of the issue, run into another related issue:
As fhir.core uses Base64.isBase64 from commons-codec 1.5+ and Android still ships with 1.3? (no android expert) this will break the android build at runtime if used with Binary resources. Possible solution would be to replace the usage of this method by another library in fhir.core in the checkValidBase64() method of the Base64BinaryType classes.
@patrick-werner is that the only thing from commons-codec that is used in HAPI FHIR?
The JPA server also uses commons-codec, but obviously that's not a concern here since I sure hope nobody's running that on Android. :)
I don't believe there are any other hapi-fhir-base uses of commons-codec aside from Base64 verification, parsing, and serializing in the datatype objects.
I guess it would be feasible to extract simply that part of the code and embed it into the model class or a util class to make it easier shippable for Android?
@jkiddo yes. Or switch Base64 handling to a extra library.