diff --git a/openbis-ipad/source/core-plugins/ipad-ui-ylab/1/dss/reporting-plugins/ipad-read-service-v1/ipad_read.py b/openbis-ipad/source/core-plugins/ipad-ui-ylab/1/dss/reporting-plugins/ipad-read-service-v1/ipad_read.py
index 265c01d67eaaacba353512fefbd15b2acaa807f4..46709252f755a49d3bd4e9e14bb4536dcf30d459 100644
--- a/openbis-ipad/source/core-plugins/ipad-ui-ylab/1/dss/reporting-plugins/ipad-read-service-v1/ipad_read.py
+++ b/openbis-ipad/source/core-plugins/ipad-ui-ylab/1/dss/reporting-plugins/ipad-read-service-v1/ipad_read.py
@@ -1,3 +1,7 @@
+from ch.systemsx.cisd.openbis.ipad.v2.server import IRequestHandler, AbstractRequestHandler, ClientPreferencesRequestHandler, RootRequestHandler
+from ch.systemsx.cisd.openbis.ipad.v2.server import DrillRequestHandler, NavigationRequestHandler, DetailRequestHandler
+from ch.systemsx.cisd.openbis.ipad.v2.server import EmptyDataRequestHandler, IpadServiceUtilities
+from ch.systemsx.cisd.openbis.ipad.v2.server import IRequestHandlerFactory, RequestHandlerDispatcher
 from ch.systemsx.cisd.openbis.dss.generic.shared.api.internal.v1 import MaterialIdentifierCollection
 from ch.systemsx.cisd.openbis.generic.shared.basic.dto import MaterialIdentifier
 from com.fasterxml.jackson.databind import ObjectMapper 
@@ -13,17 +17,17 @@ import codecs
 
 def json_encoded_value(coll):
 	"""Utility function for converting a list into a json-encoded list"""
-	return ObjectMapper().writeValueAsString(coll)
+	return IpadServiceUtilities.jsonEncodedValue(coll)
 
 def json_empty_list():
   """Utility function to return an json-encoded empty list"""
-  return json_encoded_value([])
+  return IpadServiceUtilities.jsonEmptyList()
 
 def json_empty_dict():
   """Utility function to return an json-encoded empty dictionary"""
-  return json_encoded_value({})
+  return IpadServiceUtilities.jsonEmptyDict()
 
-class RequestHandler(object):
+class RequestHandler(IRequestHandler):
 	"""Abstract superclass for the handlers for concrete requests like ROOT.
 
 	This superclass defines behavior common to all requests.
@@ -156,7 +160,10 @@ class RequestHandler(object):
 			elif 'ENZYME' == sample.getSampleType():
 				self.enzymes.append(sample)
 			elif 'WESTERN_BLOTTING' == sample.getSampleType():
-				self.westernBlottings.append(sample)		
+				self.westernBlottings.append(sample)
+
+	def processRequest(self):
+		self.process_request()
 
 class ClientPreferencesRequestHandler(object):
 	"""Abstract superclass for the handlers for CLIENT_PREFS request.
@@ -733,21 +740,29 @@ class YeastLabDetailRequestHandler(DetailRequestHandler):
 		self.add_rows(yeasts_to_dict(self.yeasts, {}, True))
 		self.add_rows(bacterias_to_dict(self.bacterias, True))
 		self.add_rows(enzymes_to_dict(self.enzymes, True))
-		self.add_rows(westernBlottings_to_dict(self.westernBlottings, True))	  
+		self.add_rows(westernBlottings_to_dict(self.westernBlottings, True))
+
+class NavigationRequestHandlerFactory(IRequestHandlerFactory):
+	def createRequestHandler(self, parameters, builder, searchService):
+		return YeastLabNavigationRequestHandler(parameters, builder)
+		
+class RootRequestHandlerFactory(IRequestHandlerFactory):
+	def createRequestHandler(self, parameters, builder, searchService):
+		return YeastLabRootRequestHandler(parameters, builder)
+		
+class DrillRequestHandlerFactory(IRequestHandlerFactory):
+	def createRequestHandler(self, parameters, builder, searchService):
+		return YeastLabDrillRequestHandler(parameters, builder)
+
+class DetailRequestHandlerFactory(IRequestHandlerFactory):
+	def createRequestHandler(self, parameters, builder, searchService):
+		return YeastLabDetailRequestHandler(parameters, builder)
 			
 
 def aggregate(parameters, builder):
-	request_key = parameters.get('requestKey')
-	if 'CLIENT_PREFS' == request_key:
-		handler = YeastLabClientPreferencesRequestHandler(parameters, builder)
-	elif 'NAVIGATION' == request_key:
-		handler = YeastLabNavigationRequestHandler(parameters, builder)
-	elif 'ROOT' == request_key:
-		handler = YeastLabRootRequestHandler(parameters, builder)
-	elif 'DRILL' == request_key:
-		handler = YeastLabDrillRequestHandler(parameters, builder)
-	elif 'DETAIL' == request_key:
-		handler = YeastLabDetailRequestHandler(parameters, builder)
-	else:		
-		handler = EmptyDataRequestHandler(parameters, builder)
-	handler.process_request()		
+	dispatcher = RequestHandlerDispatcher()
+	dispatcher.navigationRequestHandlerFactory = NavigationRequestHandlerFactory()
+	dispatcher.rootRequestHandlerFactory = RootRequestHandlerFactory()
+	dispatcher.drillRequestHandlerFactory = DrillRequestHandlerFactory()
+	dispatcher.detailRequestHandlerFactory = DetailRequestHandlerFactory()
+	dispatcher.dispatch(parameters, builder, searchService)
diff --git a/openbis-ipad/source/core-plugins/ipad-ui-ylab/1/dss/reporting-plugins/ipad-read-service-v1/lib/ipad-framework.jar b/openbis-ipad/source/core-plugins/ipad-ui-ylab/1/dss/reporting-plugins/ipad-read-service-v1/lib/ipad-framework.jar
new file mode 100644
index 0000000000000000000000000000000000000000..6d1202283a8a4d4ace2bf876be1ac6491bb0f53c
Binary files /dev/null and b/openbis-ipad/source/core-plugins/ipad-ui-ylab/1/dss/reporting-plugins/ipad-read-service-v1/lib/ipad-framework.jar differ
diff --git a/openbis-ipad/source/objc/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate b/openbis-ipad/source/objc/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate
index 190a8d6a5280e1750d429bf5d2bcbb4c2d0efc89..a3746f963ddbef37afa88defad1c6f50aef7cf9d 100644
Binary files a/openbis-ipad/source/objc/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate and b/openbis-ipad/source/objc/Research/BisMac.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/openbis-ipad/source/objc/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate b/openbis-ipad/source/objc/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate
index 80f19f774dc24f2636224863e1fe98139b407ec4..f5a65d0eb717d901ec0c2838a0ffb35147539b1b 100644
Binary files a/openbis-ipad/source/objc/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate and b/openbis-ipad/source/objc/openBIS/openBIS.xcodeproj/project.xcworkspace/xcuserdata/cramakri.xcuserdatad/UserInterfaceState.xcuserstate differ