Android Open Source - Webby Webby Service






From Project

Back to project page Webby.

License

The source code is released under:

MIT License

If you think the Android project Webby listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.swampmobile.webby.services;
/*  w  w w  .ja  v  a 2  s  .com*/
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.swampmobile.webby.Webby;
import com.swampmobile.webby.requests.WebbyRequest;
import com.swampmobile.webby.requests.WebbyResponse;
import com.swampmobile.webby.util.cache.DataCache;
import com.swampmobile.webby.util.cache.DataCache.CacheReadException;
import com.swampmobile.webby.util.cache.DataCache.CacheWriteException;
import com.swampmobile.webby.util.cache.FlatFileDataCache;
import com.swampmobile.webby.util.logging.WebbyLog;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class WebbyService extends Service
{
    private static final String TAG = "WebbyService";

    private final int MAX_EXECUTION_THREADS = 3;

    private boolean isCreated = false;

    private WebbyServiceBinder webbyServiceBinder;

    private LinkedHashSet<WebbyRequest> requestQueue; // chose LinkedHashSet because it prevents duplicates but also preserves insertion order (like a queue + set)
    private Object requestLock = new Object();

    private RequestConsumerThread requestConsumerThread;
    private ExecutorService executorService;

    private DataCache cache;
    private Object cacheLock = new Object();

    public WebbyService()
    {
        webbyServiceBinder = new WebbyServiceBinder(this);

        // Setup queue of requests
        requestQueue = new LinkedHashSet<WebbyRequest>();

        // Setup consumer thread to process new requests from queue
        requestConsumerThread = new RequestConsumerThread();
        executorService = Executors.newFixedThreadPool(MAX_EXECUTION_THREADS);
    }

    /**
     * Adds a WebbyRequest to the queue of pending requests.  If the given request is already
     * queue'd, then the request is not added to the queue for a 2nd time.
     *
     * @param request
     */
    public void addRequest(WebbyRequest request)
    {
        synchronized(requestLock)
        {
            WebbyLog.d(TAG, "Adding request to Webby queue.");
            WebbyLog.d(TAG, " - was request already in queue? " + (requestQueue.contains(request) ? "YES" : "No"));

            // Queue up the request
            requestQueue.add(request);

            requestLock.notifyAll();
        }
    }

    @Override
    public void onCreate()
    {
        WebbyLog.i(TAG, "onCreate()");

        super.onCreate();

        isCreated = true;

        cache = new FlatFileDataCache(getApplicationContext());

        requestConsumerThread = new RequestConsumerThread();
        requestConsumerThread.start();
    }

    @Override
    public void onDestroy()
    {
        WebbyLog.i(TAG, "onDestroy()");

        isCreated = false;

        synchronized(requestLock)
        {
            requestLock.notifyAll(); // Allow any threads monitoring requests to kill themselves
        }

        requestConsumerThread = null;

        super.onDestroy();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return webbyServiceBinder;
    }


    public static class WebbyServiceBinder extends Binder
    {
        private WebbyService service;

        public WebbyServiceBinder(WebbyService service)
        {
            this.service = service;
        }

        public WebbyService getService()
        {
            return service;
        }
    }


    /**
     * Consumer thread.
     *
     * Pulls requests out of the WebbyService's requestQueue and submits them for
     * execution.  The RequestConsumerThread is alive as long as the WebbyService
     * and waits until new requests are submitted.
     *
     * @author Matt
     *
     */
    private class RequestConsumerThread extends Thread
    {
        @Override
        public void run()
        {
            while(WebbyService.this.isCreated)
            {
                synchronized(requestLock)
                {
                    // Send each queue'd request to the executor service to run
                    Iterator<WebbyRequest> iterator = requestQueue.iterator();
                    WebbyRequest request;
                    WebbyRequestContainerThread requestContainer;
                    if(requestQueue.size() > 0)
                    {
                        request = iterator.next();
                        iterator.remove();
                        requestContainer = new WebbyRequestContainerThread( request );

                        WebbyLog.d(TAG, "Submitting request for execution.");
                        executorService.execute(requestContainer);
                    }

                    requestLock.notifyAll();

                    // Wait until someone adds more requests to the queue
                    try {
                        if(requestQueue.size() == 0)
                            requestLock.wait();
                    } catch (InterruptedException e) {
                        // don't care, just loop around again
                    }
                }
            }
        }
    }

    /**
     * All WebbyRequests are wrapped in a WebbyRequestContainerThread.  This container will
     * execute its WebbyRequest, write results to a cache, and then alert any listeners of
     * the WebbyRequest result.
     *
     * @author Matt
     *
     */
    private class WebbyRequestContainerThread extends Thread
    {
        private WebbyRequest request;

        public WebbyRequestContainerThread(WebbyRequest request)
        {
            this.request = request;
        }

        @Override
        public void run()
        {
            executeRequest();

            writeDataToCache();

            broadcastWebbyEvent();
        }

        private void executeRequest()
        {
            // If this service is still in existence
            if(isCreated)
            {
                // If we want a cached value, try to load from cache
                WebbyLog.d(TAG, "Trying to retrieve resource from cache.");
                if(cache.containsItem(request.getUri()) && cache.isYoungerThan(request.getUri(), request.getRefreshDuration()))
                {
                    WebbyLog.d(TAG, "Cache has resource, obtaining.");
                    JsonParser parser = new JsonParser();
                    JsonElement data;

                    // Read data from cache
                    try {
                        synchronized(cacheLock)
                        {
                            data = parser.parse( cache.readFromCacheSync(request.getUri()) );
                            request.setData(data);
                            request.setIsDataFromCache(true);
                        }
                    } catch (JsonSyntaxException e) {
                        WebbyLog.e(TAG, "Error reading data from cache.", e);
                    } catch (CacheReadException e) {
                        WebbyLog.e(TAG, "Error reading data from cache.", e);
                    }
                }
                else
                {
                    WebbyLog.d(TAG, "Item not yet in cache.");
                }

                // If we didn't read data from cache, execute request
                if(request.getData() == null)
                {
                    WebbyLog.d(TAG, "Running a request");
                    request.run();
                    request.setIsDataFromCache(false);
                    WebbyLog.d(TAG, "Request has completed. Successful? " + request.wasSuccessful());
                    if(!request.wasSuccessful())
                    {
                        WebbyLog.d(TAG, " - Exception: " + request.getException());
                        request.getException().printStackTrace();
                    }
                }
            }
        }

        private void writeDataToCache()
        {
            // If this Service is still in existence, and our data is fresh from the server,
            // then write this data to the cache.
            if(isCreated && request.wasSuccessful() && !request.isDataFromCache())
            {
                synchronized(cacheLock)
                {
                    WebbyLog.d(TAG, "Writing item to cache");
                    try {
                        cache.writeToCacheSync(request.getUri(), request.getData().toString());
                    } catch (CacheWriteException e) {
                        WebbyLog.e(TAG, "Could not write web service resource to cache.", e);
                    }
                }
            }
        }

        private void broadcastWebbyEvent()
        {
            // If this service is still in existence
            if(isCreated)
            {
                synchronized(requestLock)
                {
                    WebbyResponse event;
                    if(request.wasSuccessful())
                    {
                        event = new WebbyResponse(request.getUri(), request.getStatusCode(), request.getStatusPhrase(), request.getData(), request.isDataFromCache());
                    }
                    else
                    {
                        event = new WebbyResponse(request.getUri(), request.getStatusCode(), request.getStatusPhrase(), request.getData(), request.getException());
                    }
                    Webby.getBus().post(event);
                }
            }
        }
    }
}




Java Source Code List

com.swampmobile.webby.WebbyManager.java
com.swampmobile.webby.Webby.java
com.swampmobile.webby.examples.activities.MainActivity.java
com.swampmobile.webby.examples.activities.WebbyActivity.java
com.swampmobile.webby.examples.activities.WebbyFragmentActivity.java
com.swampmobile.webby.examples.apis.FeedzillaApi.java
com.swampmobile.webby.examples.fragments.WebbyFragment.java
com.swampmobile.webby.examples.requests.TestWebbyRequest.java
com.swampmobile.webby.requests.WebbyRequest.java
com.swampmobile.webby.requests.WebbyResponse.java
com.swampmobile.webby.services.WebbyService.java
com.swampmobile.webby.util.cache.DataCache.java
com.swampmobile.webby.util.cache.FlatFileDataCache.java
com.swampmobile.webby.util.logging.WebbyLog.java
com.swampmobile.webby.util.time.Duration.java