sleep
sleep

Reputation: 4954

Bizarre behaviour when using Apache Commons lib in Android

I'm using commons-lang3-3.0.1.jar, in order to utilise the StrSubstitutor class. Check this out...

The following code is called in from my SyncAdapter, it crashes constructing the StrSubstitutor:

public static String makeGetPlansQueryString(Bundle params)
{
    Map<String, String> valuesMap = new HashMap<String, String>();

    valuesMap.put(REQUEST_PARAM_APIUSERNAME, API_USERNAME);
    valuesMap.put(REQUEST_PARAM_APIPASSWORD, API_PASSWORD);
    //... etc. etc.

    String xmlTemplate = VendApplication.getContext().getString(R.string.XMLREQUEST_GET_PLANS);
    StrSubstitutor subst = new StrSubstitutor(valuesMap); // <-- Crashes in here.
    return subst.replace(xmlTemplate);
}

Error output:

    11-02 14:36:08.439: ERROR/AndroidRuntime(9244): FATAL EXCEPTION: SyncAdapterThread-1
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244): java.lang.ExceptionInInitializerError
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     at com.conducthq.android.vend.webapi.WebAPIRequestHelper.makeGetPlansQueryString(WebAPIRequestHelper.java:68)
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     at com.conducthq.android.vend.webapi.WebAPIClient.createHTTPRequest(WebAPIClient.java:121)
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     at com.conducthq.android.vend.webapi.WebAPIClient.processRequest(WebAPIClient.java:55)
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     at com.conducthq.android.vend.webapi.SyncAdapter.onPerformSync(SyncAdapter.java:39)
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:163)
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244): Caused by: java.lang.ExceptionInInitializerError
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     at org.apache.commons.lang3.text.StrMatcher.stringMatcher(StrMatcher.java:206)
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     at org.apache.commons.lang3.text.StrSubstitutor.<clinit>(StrSubstitutor.java:112)
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     ... 5 more
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244): Caused by: java.lang.NullPointerException
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     at org.apache.commons.lang3.StringUtils.<clinit>(StringUtils.java:717)
    11-02 14:36:08.439: ERROR/AndroidRuntime(9244):     ... 7 more

If I add this one line to my HomeActivity (launched on app start), the above code works perfectly:

StrSubstitutor sub = new StrSubstitutor(new HashMap<String, String>());

Weird right? How does this line affect different code running on a different thread at a different point in time? Any Android gurus out there that can shed some light on this? Is there some weird Android JAR loading bug I don't know about? @_@

I'm using Android 2.1 SDK on a LG-P350. I've reproduced this behaviour with the super simple example code from the Apache Commons API doc on StrSubstitutor: http://commons.apache.org/lang/api-3.0.1/org/apache/commons/lang3/text/StrSubstitutor.html

Upvotes: 3

Views: 1164

Answers (1)

Jens
Jens

Reputation: 17077

Your crash is in the static initializer of StringUtils where it attempts to get the context class loader from the current thread - in an apparent attempt to obtain the java.text.Normalizer$Form class. So yes, it's some funky issue with getContextClassLoader() returning null.

Update

The error is apparently mentioned in this bug, so I guess you could just forcibly set the context class loader and you should be fine.

Thread.currentThread().setContextClassLoader(this.getClassLoader());

Upvotes: 3

Related Questions