Friday, June 13, 2014

groovy Closures memoization

Memoization (if you don't know already) is technique that groovy closure can use and remember the result of its invocation for a specific set of inputs. It to this by internally caching the result.
This is quite common technique to speed up recursive algorithms (Usually you will use maps for this).

Groovy support memoization through it's .memoize() method.
The first invocation is doing actual work and and subsequent invocation is pulling result from cache.
If you run this program, you will see something like this as output:


Test without memoization:
Adding 1 and 3 took 1540 msec with result 4.
Adding 1 and 3 took 1500 msec with result 4.
Adding 1 and 3 took 1501 msec with result 4.
Adding 1 and 3 took 1500 msec with result 4.
Adding 1 and 3 took 1500 msec with result 4.
Test with memoization:
Adding 1 and 3 took 1500 msec with result 4.
Adding 1 and 3 took 0 msec with result 4.
Adding 1 and 3 took 0 msec with result 4.
Adding 1 and 3 took 1 msec with result 4.
Adding 1 and 3 took 0 msec with result 4.


As you can see there is quite a difference between two test. It goes without saying that your closures should return same result for same parameters.
addTwoNumbers = {int a, b ->
    //simulate some lengthy calculation
    Thread.sleep(1500)
    a + b
}
println("Test without memoization:")
def testItWithoutMemoization(a, b) {
    long start = System.currentTimeMillis()
    long result = addTwoNumbers(a, b)

    println("Adding $a and $b took " +
            "${System.currentTimeMillis() - start} " +
            "msec with result $result.")
}

testItWithoutMemoization(1, 3)
testItWithoutMemoization(1, 3)
testItWithoutMemoization(1, 3)
testItWithoutMemoization(1, 3)
testItWithoutMemoization(1, 3)

addTwoNumbersWithMem = addTwoNumbers.memoize()

println("Test with memoization:")
def testItWithMemoization(a, b) {
    long start = System.currentTimeMillis()
    long result = addTwoNumbersWithMem(a, b)

    println("Adding $a and $b took " +
            "${System.currentTimeMillis() - start} " +
            "msec with result $result.")
}

testItWithMemoization(1, 3)
testItWithMemoization(1, 3)
testItWithMemoization(1, 3)
testItWithMemoization(1, 3)
testItWithMemoization(1, 3)

Tuesday, June 10, 2014

Grails - dataBind in Service Layer

Here is quick tip how you can use dataBind grails command outside of grails controller.
import org.codehaus.groovy.grails.web.metaclass.BindDynamicMethod

class DataBinder {

    private static BindDynamicMethod bindDynamicMethod = new BindDynamicMethod()

    /**
     * make the controller bindData method statically available, e.g. for service layer use
     * implemented as closure to allow static import emulating controller layer bindData usage 1:1
     */
    static Closure bindData = { Object[] args ->
        bindDynamicMethod.invoke(args ? args[0] : null, BindDynamicMethod.METHOD_SIGNATURE, args)
    }
}

//usage
class TestBind {
    public void intermediateNotification(Map params) {
        Test test = new Test()
        DataBinder.bindData(test, params)
        test.save()    
    }
}

Friday, June 6, 2014

Android remote logger - send logs to server

I want to show you simple implementation of remote logger for Android. This can be used for sendings logs from your app to server (backend).

public final class Logger {

    public static final String DISPATCHER_REPORT_URI = App.getDispatcherUri() + "/vidLog/report";

    private static final int CAPACITY = 10;
    private static final String APPLICATION_LOG_TAG = "YourApp";
    private static List<String> logs = new Vector<String>(CAPACITY);
   
    public synchronized static void r(String msg) {

        if (logs.size() + 1 > CAPACITY) {
            flushRemote();
        }

        logs.add(buildLog(msg));
    }

    public synchronized static void flushRemote() {
        final String formattedLogs = collectAndFormatLogs();

        Runnable sendLogs = new Runnable() {
            @Override
            public void run() {
                HttpHelper.doPostRequest(YOUR_SERVER_URI, "APP_LOG", formattedLogs);
            }
        };
        new Thread(sendLogs).start();

        logs.clear();
    }

    private static String collectAndFormatLogs() {
        String logsFormatted = "";
        for (String log : logs) {
            logsFormatted += log + "\n";
        }
        return logsFormatted;
    }

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");

    private static String buildLog(String msg) {
        return sdf.format(new Date()) +
                " REMOTE " +
                APPLICATION_LOG_TAG + " " +
                msg;
    }

}
//Usage
Logger.r("first message");
Logger.r("second message");

//When CAPACITY is exceeded logs will be flushed automatically.
Logger.flushRemote();

Save context in Android Application class

If you are tired of always passing application context through your classes in Android, you can try something like this. In this way you will store your application context in Application class as static field and you can access this field from anywhere.
public class App extends Application {

  private static Context context;

  @Override
  public void onCreate() {
   super.onCreate();
   context = this;

   /* other stuf */
  }

  public static Context getContext() {
   return context;
  }

}