diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd0fda49194971a56b4f997a2081c3dd1a9822b0
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.olm;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * Helper class dedicated to serialization mechanism (template method pattern).
+ */
+abstract class CommonSerializeUtils {
+    private static final String LOG_TAG = "CommonSerializeUtils";
+
+    /**
+     * Kick off the serialization mechanism.
+     * @param aOutStream output stream for serializing
+     * @throws IOException exception
+     */
+    protected void serializeObject(ObjectOutputStream aOutStream) throws IOException {
+        aOutStream.defaultWriteObject();
+
+        // generate serialization key
+        String key = OlmUtility.getRandomKey();
+
+        // compute pickle string
+        StringBuffer errorMsg = new StringBuffer();
+        String pickledData = serializeDataWithKey(key, errorMsg);
+
+        if(null == pickledData) {
+            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg));
+        } else {
+            aOutStream.writeObject(key);
+            aOutStream.writeObject(pickledData);
+        }
+    }
+
+    /**
+     * Kick off the deserialization mechanism.
+     * @param aInStream input stream
+     * @throws IOException exception
+     * @throws ClassNotFoundException exception
+     */
+    protected void deserializeObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
+        aInStream.defaultReadObject();
+        StringBuffer errorMsg = new StringBuffer();
+
+        String key = (String) aInStream.readObject();
+        String pickledData = (String) aInStream.readObject();
+
+        if(TextUtils.isEmpty(key)) {
+            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key");
+
+        } else if(TextUtils.isEmpty(pickledData)) {
+            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
+
+        } else if(!createNewObjectFromSerialization()) {
+            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
+
+        } else if(!initWithSerializedData(pickledData, key, errorMsg)) {
+            releaseObjectFromSerialization(); // prevent memory leak
+            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg));
+
+        } else {
+            Log.d(LOG_TAG,"## readObject(): success");
+        }
+    }
+
+    protected abstract String serializeDataWithKey(String aKey, StringBuffer aErrorMsg);
+    protected abstract boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg);
+    protected abstract boolean createNewObjectFromSerialization();
+    protected abstract void releaseObjectFromSerialization();
+}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java
index 876e6511349deb85583c73ecc55440f29c9aae0c..1345a5043e827b361cace28573a9bf2caa715858 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java
@@ -32,7 +32,7 @@ import java.io.Serializable;
  * OlmAccount provides APIs to retrieve the Olm keys.
  *<br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>.
  */
-public class OlmAccount implements Serializable {
+public class OlmAccount extends CommonSerializeUtils implements Serializable {
     private static final long serialVersionUID = 3497486121598434824L;
     private static final String LOG_TAG = "OlmAccount";
 
@@ -71,21 +71,7 @@ public class OlmAccount implements Serializable {
      * @throws IOException exception
      */
     private void writeObject(ObjectOutputStream aOutStream) throws IOException {
-        aOutStream.defaultWriteObject();
-
-        // generate serialization key
-        String key = OlmUtility.getRandomKey();
-
-        // compute pickle string
-        StringBuffer errorMsg = new StringBuffer();
-        String pickledData = serializeDataWithKey(key, errorMsg);
-
-        if(null == pickledData) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg));
-        } else {
-            aOutStream.writeObject(key);
-            aOutStream.writeObject(pickledData);
-        }
+        serializeObject(aOutStream);
     }
 
     /**
@@ -95,28 +81,17 @@ public class OlmAccount implements Serializable {
      * @throws ClassNotFoundException exception
      */
     private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
-        aInStream.defaultReadObject();
-        StringBuffer errorMsg = new StringBuffer();
-
-        String key = (String) aInStream.readObject();
-        String pickledData = (String) aInStream.readObject();
-
-        if(TextUtils.isEmpty(key)) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key");
-
-        } else if(TextUtils.isEmpty(pickledData)) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
-
-        } else if(!createNewAccount()) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
+        deserializeObject(aInStream);
+    }
 
-        } else if(!initWithSerializedData(pickledData, key, errorMsg)) {
-            releaseAccount(); // prevent memory leak
-            throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg));
+    @Override
+    protected boolean createNewObjectFromSerialization() {
+        return createNewAccount();
+    }
 
-        } else {
-            Log.d(LOG_TAG,"## readObject(): success");
-        }
+    @Override
+    protected void releaseObjectFromSerialization() {
+        releaseAccount();
     }
 
     /**
@@ -128,7 +103,8 @@ public class OlmAccount implements Serializable {
      * @param aErrorMsg error message description
      * @return pickled base64 string if operation succeed, null otherwise
      */
-    private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
+    @Override
+    protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
         String pickleRetValue = null;
 
         // sanity check
@@ -154,7 +130,8 @@ public class OlmAccount implements Serializable {
      * @param aErrorMsg error message description
      * @return true if operation succeed, false otherwise
      */
-    private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
+    @Override
+    protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
         boolean retCode = false;
         String jniError;
 
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
index 501d660e24707250145ced80ca7dba45547685fc..6f275079466e1c17a79689b5b2779ba48edfa211 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
@@ -34,7 +34,7 @@ import java.io.Serializable;
  *
  * <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>.
  */
-public class OlmInboundGroupSession implements Serializable {
+public class OlmInboundGroupSession extends CommonSerializeUtils implements Serializable {
     private static final long serialVersionUID = -772028491251653253L;
     private static final String LOG_TAG = "OlmInboundGroupSession";
 
@@ -139,21 +139,7 @@ public class OlmInboundGroupSession implements Serializable {
      * @throws IOException exception
      */
     private void writeObject(ObjectOutputStream aOutStream) throws IOException {
-        aOutStream.defaultWriteObject();
-
-        // generate serialization key
-        String key = OlmUtility.getRandomKey();
-
-        // compute pickle string
-        StringBuffer errorMsg = new StringBuffer();
-        String pickledData = serializeDataWithKey(key, errorMsg);
-
-        if(null == pickledData) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_SERIALIZATION, String.valueOf(errorMsg));
-        } else {
-            aOutStream.writeObject(key);
-            aOutStream.writeObject(pickledData);
-        }
+        serializeObject(aOutStream);
     }
 
     /**
@@ -163,28 +149,17 @@ public class OlmInboundGroupSession implements Serializable {
      * @throws ClassNotFoundException exception
      */
     private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
-        aInStream.defaultReadObject();
-        StringBuffer errorMsg = new StringBuffer();
-
-        String key = (String) aInStream.readObject();
-        String pickledData = (String) aInStream.readObject();
-
-        if(TextUtils.isEmpty(key)) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key");
-
-        } else if(TextUtils.isEmpty(pickledData)) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
-
-        } else if(!createNewSession()) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
+        deserializeObject(aInStream);
+    }
 
-        } else if(!initWithSerializedData(pickledData, key, errorMsg)) {
-            releaseSession(); // prevent memory leak
-            throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, String.valueOf(errorMsg));
+    @Override
+    protected boolean createNewObjectFromSerialization() {
+        return createNewSession();
+    }
 
-        } else {
-            Log.d(LOG_TAG,"## readObject(): success");
-        }
+    @Override
+    protected void releaseObjectFromSerialization() {
+        releaseSession();
     }
 
     /**
@@ -196,7 +171,8 @@ public class OlmInboundGroupSession implements Serializable {
      * @param aErrorMsg error message description
      * @return pickled base64 string if operation succeed, null otherwise
      */
-    private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
+    @Override
+    protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
         String pickleRetValue = null;
 
         // sanity check
@@ -228,7 +204,8 @@ public class OlmInboundGroupSession implements Serializable {
      * @param aErrorMsg error message description
      * @return true if operation succeed, false otherwise
      */
-    private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
+    @Override
+    protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
         boolean retCode = false;
         String jniError;
 
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java
index 37f89ea43d72dd8f9dd05653bc16f4fcedefc54b..5b59362f9a37c824cff71735d9206df0be939243 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java
@@ -32,7 +32,7 @@ import java.io.Serializable;
  *
  * <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>.
  */
-public class OlmOutboundGroupSession implements Serializable {
+public class OlmOutboundGroupSession extends CommonSerializeUtils implements Serializable {
     private static final long serialVersionUID = -3133097431283604416L;
     private static final String LOG_TAG = "OlmOutboundGroupSession";
 
@@ -65,21 +65,7 @@ public class OlmOutboundGroupSession implements Serializable {
      * @throws IOException exception
      */
     private void writeObject(ObjectOutputStream aOutStream) throws IOException {
-        aOutStream.defaultWriteObject();
-
-        // generate serialization key
-        String key = OlmUtility.getRandomKey();
-
-        // compute pickle string
-        StringBuffer errorMsg = new StringBuffer();
-        String pickledData = serializeDataWithKey(key, errorMsg);
-
-        if(null == pickledData) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_SERIALIZATION, String.valueOf(errorMsg));
-        } else {
-            aOutStream.writeObject(key);
-            aOutStream.writeObject(pickledData);
-        }
+        serializeObject(aOutStream);
     }
 
     /**
@@ -89,28 +75,17 @@ public class OlmOutboundGroupSession implements Serializable {
      * @throws ClassNotFoundException exception
      */
     private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
-        aInStream.defaultReadObject();
-        StringBuffer errorMsg = new StringBuffer();
-
-        String key = (String) aInStream.readObject();
-        String pickledData = (String) aInStream.readObject();
-
-        if(TextUtils.isEmpty(key)) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key");
-
-        } else if(TextUtils.isEmpty(pickledData)) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
-
-        } else if(!createNewSession()) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
+        deserializeObject(aInStream);
+    }
 
-        } else if(!initWithSerializedData(pickledData, key, errorMsg)) {
-            releaseSession(); // prevent memory leak
-            throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, String.valueOf(errorMsg));
+    @Override
+    protected boolean createNewObjectFromSerialization() {
+        return createNewSession();
+    }
 
-        } else {
-            Log.d(LOG_TAG,"## readObject(): success");
-        }
+    @Override
+    protected void releaseObjectFromSerialization() {
+        releaseSession();
     }
 
     /**
@@ -122,7 +97,8 @@ public class OlmOutboundGroupSession implements Serializable {
      * @param aErrorMsg error message description
      * @return pickled base64 string if operation succeed, null otherwise
      */
-    private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
+    @Override
+    protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
         String pickleRetValue = null;
 
         // sanity check
@@ -148,7 +124,8 @@ public class OlmOutboundGroupSession implements Serializable {
      * @param aErrorMsg error message description
      * @return true if operation succeed, false otherwise
      */
-    private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
+    @Override
+    protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
         boolean retCode = false;
         String jniError;
 
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
index 9377838985487e6e51c1e4dba0eb5e38ce40e074..ffc899a8d5bc894020309e5e11f9133a5fda1b99 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
@@ -32,7 +32,7 @@ import java.io.Serializable;
  * From this step on, messages can be exchanged by using {@link #encryptMessage(String)} and {@link #decryptMessage(OlmMessage)}.
  * <br><br>Detailed implementation guide is available at <a href="http://matrix.org/docs/guides/e2e_implementation.html">Implementing End-to-End Encryption in Matrix clients</a>.
  */
-public class OlmSession implements Serializable {
+public class OlmSession extends CommonSerializeUtils implements Serializable {
     private static final long serialVersionUID = -8975488639186976419L;
     private static final String LOG_TAG = "OlmSession";
 
@@ -54,21 +54,7 @@ public class OlmSession implements Serializable {
      * @throws IOException exception
      */
     private void writeObject(ObjectOutputStream aOutStream) throws IOException {
-        aOutStream.defaultWriteObject();
-
-        // generate serialization key
-        String key = OlmUtility.getRandomKey();
-
-        // compute pickle string
-        StringBuffer errorMsg = new StringBuffer();
-        String pickledData = serializeDataWithKey(key, errorMsg);
-
-        if(null == pickledData) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SERIALIZATION, String.valueOf(errorMsg));
-        } else {
-            aOutStream.writeObject(key);
-            aOutStream.writeObject(pickledData);
-        }
+        serializeObject(aOutStream);
     }
 
     /**
@@ -78,28 +64,17 @@ public class OlmSession implements Serializable {
      * @throws ClassNotFoundException exception
      */
     private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException {
-        aInStream.defaultReadObject();
-        StringBuffer errorMsg = new StringBuffer();
-
-        String key = (String) aInStream.readObject();
-        String pickledData = (String) aInStream.readObject();
-
-        if(TextUtils.isEmpty(key)) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key");
-
-        } else if(TextUtils.isEmpty(pickledData)) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle");
-
-        } else if(!createNewSession()) {
-            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION);
+        deserializeObject(aInStream);
+    }
 
-        } else if(!initWithSerializedData(pickledData, key, errorMsg)) {
-            releaseSession(); // prevent memory leak
-            throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, String.valueOf(errorMsg));
+    @Override
+    protected boolean createNewObjectFromSerialization() {
+        return createNewSession();
+    }
 
-        } else {
-            Log.d(LOG_TAG,"## readObject(): success");
-        }
+    @Override
+    protected void releaseObjectFromSerialization() {
+        releaseSession();
     }
 
     /**
@@ -111,7 +86,8 @@ public class OlmSession implements Serializable {
      * @param aErrorMsg error message description
      * @return pickled base64 string if operation succeed, null otherwise
      */
-    private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
+    @Override
+    protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) {
         String pickleRetValue = null;
 
         // sanity check
@@ -137,7 +113,8 @@ public class OlmSession implements Serializable {
      * @param aErrorMsg error message description
      * @return true if operation succeed, false otherwise
      */
-    private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
+    @Override
+    protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) {
         boolean retCode = false;
         String jniError;