How to use GWT-RequestFactory in Android SyncAdapter (always getting ValidationTool-Error)

I have a question about using GWT-RequestFactory in Android. As a starting point, I used the code from "Create a AppEngine connected Android-Project" -Wizard (info: http://code.google.com/intl/de-DE/eclipse/docs/appengine_connected_android.html ) and it worked big.

But now in my case, I want to expand this application to use the local ContentProvider with SQLite, and SyncService with SyncAdapter - to synchronize data from ContentProvider with AppEngine using RequestFactory. Now my problem is this: I can call

MyRequestFactory requestFactory = Util.getRequestFactory(mContext, MyRequestFactory.class); 

in any operation I want and will receive an instance of MyRequestFactory. (Note: Util is a class created by the wizard.) But if I try to make the same call from my SyncAdapter, I get java.lang.RuntimeException: RequestFactory ValidationTool must be run for com.hotool.client.MyRequestFactory RequestFactory type ".

Perhaps for your information: the Util.getRequestFacory method looks like this:

 /** * Creates and returns an initialized {@link RequestFactory} of the given * type. */ public static <T extends RequestFactory> T getRequestFactory( Context context, Class<T> factoryClass) { T requestFactory = RequestFactorySource.create(factoryClass); SharedPreferences prefs = getSharedPreferences(context); String authCookie = prefs.getString(Util.AUTH_COOKIE, null); String uriString = Util.getBaseUrl(context) + RF_METHOD; URI uri; try { uri = new URI(uriString); } catch (URISyntaxException e) { Log.w(TAG, "Bad URI: " + uriString, e); return null; } requestFactory.initialize(new SimpleEventBus(), new AndroidRequestTransport(uri, authCookie)); return requestFactory; } 

The error occurs in RequestFactorySource , which is located in requestfactory-client.jar. I think this may be a Class-Loader problem, but tried to figure it out without success.

I tried using ValidationTool, but it didnโ€™t help in the first place, and secondly, I found that the classes created by ValidationTool already exist (possibly due to annotation processing, as indicated here: http://code.google.com / p / google-web-toolkit / wiki / RequestFactoryInterfaceValidation )

Does anyone have any ideas what might cause this?

Many thanks and best wishes.

Marcus Neuenschwander

+6
source share
1 answer

You are right, this is a problem with the loader class.

This happens in requestfactory-client.jar, here is the corresponding source:

 class InProcessRequestFactory extends AbstractRequestFactory { //... public InProcessRequestFactory(Class<? extends RequestFactory> requestFactoryInterface) { this.requestFactoryInterface = requestFactoryInterface; deobfuscator = Deobfuscator.Builder.load(requestFactoryInterface, Thread.currentThread().getContextClassLoader()).build(); } //... } 

and

 public class Deobfuscator { //... public static class Builder { public static Builder load(Class<?> clazz, ClassLoader resolveClassesWith) { Throwable ex; try { Class<?> found; try { // Used by the server found = Class.forName(clazz.getName() + GENERATED_SUFFIX, false, resolveClassesWith); } catch (ClassNotFoundException ignored) { // Used by JRE-only clients found = Class.forName(clazz.getName() + GENERATED_SUFFIX_LITE, false, resolveClassesWith); } Class<? extends Builder> builderClass = found.asSubclass(Builder.class); Builder builder = builderClass.newInstance(); return builder; } catch (ClassNotFoundException e) { throw new RuntimeException("The RequestFactory ValidationTool must be run for the " + clazz.getCanonicalName() + " RequestFactory type"); } catch (InstantiationException e) { ex = e; } catch (IllegalAccessException e) { ex = e; } throw new RuntimeException(ex); } //... } 

The problem is that Thread.currentThread (). It seems that getContextClassLoader () returns a null value when called from the sync adapter on Android, because the sync adapter thread is created by the system, not your application.

I solved this by manually calling setContextClassLoader in the onPerformSync method before creating the requestfactory instance:

 @Override public void onPerformSync(final Account account, Bundle extras, String authority, final ContentProviderClient provider, final SyncResult syncResult) { Thread.currentThread().setContextClassLoader(mContext.getClassLoader()); // ... MyRequestFactory requestFactory = Util.getRequestFactory(mContext, MyRequestFactory.class, acsidToken); // ... } 

Hope this makes sense. Andreas

+4
source

Source: https://habr.com/ru/post/901012/


All Articles