diff --git a/ipaacalib/cpp/CMakeLists.txt b/ipaacalib/cpp/CMakeLists.txt
index 688725b7a861ba801a9b2fd3b1f73c67f78b87cb..2f6243105a687126e0ef5e586c78e04507b4b0e7 100644
--- a/ipaacalib/cpp/CMakeLists.txt
+++ b/ipaacalib/cpp/CMakeLists.txt
@@ -13,6 +13,9 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIPAACA_DEBUG_MESSAGES")
 #  !! NOTE: at the moment required in any ipaaca cpp project in Windows !!
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIPAACA_EXPOSE_FULL_RSB_API")
 
+## use the following line to enable building mock IUs (FakeIU)
+#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIPAACA_BUILD_MOCK_OBJECTS")
+
 # find cmake modules locally too
 set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules )
 
diff --git a/ipaacalib/cpp/build.properties b/ipaacalib/cpp/build.properties
index b3fc60b1bde07852dd520ae90e3f491771ce32f8..7eaaa9bdcb2851bae4780e6705ed08f054e0b1be 100644
--- a/ipaacalib/cpp/build.properties
+++ b/ipaacalib/cpp/build.properties
@@ -4,4 +4,6 @@ resource.path=${shared.resources}/;
 rebuild.list=
 publish.resolver=asap.sftp.publish
 dist.dir=../../dist
+deps.dir=../../deps
+test.binary=testipaaca
 
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h b/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h
index e0a26c13e7e668977d5e86daea651a3ac5ec54ff..f5e4476bf447dc078f95af09af8fc42fc380605c 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-buffers.h
@@ -44,7 +44,7 @@ IPAACA_HEADER_EXPORT class IUStore: public std::map<std::string, boost::shared_p
 {
 };
 /// Store for RemotePushIUs (used in InputBuffer)
-IPAACA_HEADER_EXPORT class RemotePushIUStore: public std::map<std::string, boost::shared_ptr<RemotePushIU> > // TODO genericize to all remote IU types
+IPAACA_HEADER_EXPORT class RemotePushIUStore: public std::map<std::string, boost::shared_ptr<RemotePushIU> >
 {
 };
 
@@ -142,7 +142,6 @@ IPAACA_HEADER_EXPORT class IUEventHandler {//{{{
 	public:
 		IPAACA_HEADER_EXPORT IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category);
 		IPAACA_HEADER_EXPORT IUEventHandler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories);
-		//void call(Buffer* buffer, const std::string& uid, bool local, IUEventType event_type, const std::string& category);
 		IPAACA_HEADER_EXPORT void call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category);
 	typedef boost::shared_ptr<IUEventHandler> ptr;
 };//}}}
@@ -160,7 +159,6 @@ IPAACA_HEADER_EXPORT class Buffer { //: public boost::enable_shared_from_this<Bu
 	friend class CallbackIUCommission;
 	friend class CallbackIUResendRequest;
 	protected:
-		//Lock _handler_lock;
 		IPAACA_MEMBER_VAR_EXPORT std::string _uuid;
 		IPAACA_MEMBER_VAR_EXPORT std::string _basename;
 		IPAACA_MEMBER_VAR_EXPORT std::string _unique_name;
@@ -174,7 +172,6 @@ IPAACA_HEADER_EXPORT class Buffer { //: public boost::enable_shared_from_this<Bu
 		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name="undef") = 0;
 		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef") = 0;
 		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") = 0;
-//		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual void _send_iu_resendrequest(IUInterface* iu, revision_t revision, const std::string& writer_name="undef") = 0;
 		IPAACA_HEADER_EXPORT void _allocate_unique_name(const std::string& basename, const std::string& function);
 		IPAACA_HEADER_EXPORT inline Buffer(const std::string& basename, const std::string& function) {
 			_allocate_unique_name(basename, function);
@@ -228,7 +225,6 @@ IPAACA_HEADER_EXPORT class Buffer { //: public boost::enable_shared_from_this<Bu
 		 *
 		 */
 		IPAACA_HEADER_EXPORT void register_handler(IUEventHandlerFunction function, IUEventType event_mask = IU_ALL_EVENTS, const std::string& category="");
-		//_IPAACA_ABSTRACT_ virtual void add(boost::shared_ptr<IUInterface> iu) = 0;
 		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual boost::shared_ptr<IUInterface> get(const std::string& iu_uid) = 0;
 		IPAACA_HEADER_EXPORT _IPAACA_ABSTRACT_ virtual std::set<boost::shared_ptr<IUInterface> > get_ius() = 0;
 
@@ -253,7 +249,6 @@ IPAACA_HEADER_EXPORT class OutputBuffer: public Buffer { //, public boost::enabl
 	friend class OutputBufferRsbAdaptor;
 	protected:
 	protected:
-		//OutputBufferRsbAdaptor _rsb;
 		IPAACA_MEMBER_VAR_EXPORT IUStore _iu_store;
 		IPAACA_MEMBER_VAR_EXPORT Lock _iu_id_counter_lock;
 #ifdef IPAACA_EXPOSE_FULL_RSB_API
@@ -263,29 +258,23 @@ IPAACA_HEADER_EXPORT class OutputBuffer: public Buffer { //, public boost::enabl
 		IPAACA_HEADER_EXPORT rsb::Informer<rsb::AnyType>::Ptr _get_informer(const std::string& category);
 #endif
 	protected:
-		// informing functions
 		IPAACA_HEADER_EXPORT void _send_iu_link_update(IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name="undef") _IPAACA_OVERRIDE_;
 		IPAACA_HEADER_EXPORT void _publish_iu_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name) _IPAACA_OVERRIDE_;
-
 		IPAACA_HEADER_EXPORT void _send_iu_payload_update(IUInterface* iu, bool is_delta, revision_t revision, const std::map<std::string,  PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name="undef") _IPAACA_OVERRIDE_;
 		IPAACA_HEADER_EXPORT void _send_iu_commission(IUInterface* iu, revision_t revision, const std::string& writer_name) _IPAACA_OVERRIDE_;
-		//IPAACA_HEADER_EXPORT void _send_iu_resendrequest(IUInterface* iu, revision_t revision, const std::string& writer_name);
-		// remote access functions
-		// _remote_update_links(IULinkUpdate)
-		// _remote_update_payload(IUPayloadUpdate)
-		// _remote_commit(protobuf::IUCommission)
 		IPAACA_HEADER_EXPORT void _publish_iu(boost::shared_ptr<IU> iu);
-
+		/// mark and send IU retraction on own IU (removal from buffer is in remove(IU))
 		IPAACA_HEADER_EXPORT void _retract_iu(boost::shared_ptr<IU> iu);
+		/// mark and send retraction for all unretracted IUs (without removal, used in ~OutputBuffer)
+		IPAACA_HEADER_EXPORT void _retract_all_internal();
 	protected:
 		/// \b Note: constructor is protected. Use create()
 		IPAACA_HEADER_EXPORT OutputBuffer(const std::string& basename, const std::string& channel=""); // empty string auto-replaced with __ipaaca_static_option_default_channel
 		IPAACA_HEADER_EXPORT void _initialize_server();
 	public:
 		IPAACA_HEADER_EXPORT static boost::shared_ptr<OutputBuffer> create(const std::string& basename);
-		IPAACA_HEADER_EXPORT ~OutputBuffer() {
-			IPAACA_IMPLEMENT_ME
-		}
+		/// OutputBuffer destructor will retract all IUs that are still live
+		IPAACA_HEADER_EXPORT ~OutputBuffer();
 		IPAACA_HEADER_EXPORT void add(boost::shared_ptr<IU> iu);
 		IPAACA_HEADER_EXPORT boost::shared_ptr<IU> remove(const std::string& iu_uid);
 		IPAACA_HEADER_EXPORT boost::shared_ptr<IU> remove(boost::shared_ptr<IU> iu);
@@ -308,12 +297,11 @@ IPAACA_HEADER_EXPORT class InputBuffer: public Buffer { //, public boost::enable
 	friend class IU;
 	friend class RemotePushIU;
 	friend class InputBufferRsbAdaptor;
-		//InputBufferRsbAdaptor _rsb;
 #ifdef IPAACA_EXPOSE_FULL_RSB_API
 	protected:
 		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, rsb::ListenerPtr> _listener_store;
 		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, rsb::patterns::RemoteServerPtr> _remote_server_store;
-		IPAACA_MEMBER_VAR_EXPORT RemotePushIUStore _iu_store;  // TODO genericize
+		IPAACA_MEMBER_VAR_EXPORT RemotePushIUStore _iu_store;
 		IPAACA_HEADER_EXPORT rsb::patterns::RemoteServerPtr _get_remote_server(const std::string& unique_server_name);
 		IPAACA_HEADER_EXPORT rsb::ListenerPtr _create_category_listener_if_needed(const std::string& category);
 		IPAACA_HEADER_EXPORT void _handle_iu_events(rsb::EventPtr event);
@@ -362,8 +350,6 @@ IPAACA_HEADER_EXPORT class InputBuffer: public Buffer { //, public boost::enable
 		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::set<std::string>& category_interests);
 		/// Create InputBuffer from name and vector of category interests
 		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::vector<std::string>& category_interests);
-		// /// Create InputBuffer from name and initializer_list of category interests
-		// IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::initializer_list<std::string>& category_interests);
 		/// Convenience function: create InputBuffer from name and one category interest
 		IPAACA_HEADER_EXPORT static boost::shared_ptr<InputBuffer> create(const std::string& basename, const std::string& category_interest1);
 		/// Convenience function: create InputBuffer from name and two category interests [DEPRECATED]
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h b/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h
index 42e4f1024d5e37feba5b932bd4695f80185fc99a..e91b9c31b966b34c9100aa64b403d5199f3d073f 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-definitions.h
@@ -49,9 +49,6 @@
 #error "Please do not include this file directly, use ipaaca.h instead"
 #endif
 
-// LAST FIXME LAST
-//typedef boost::shared_ptr<rapidjson::Document> JsonDocPtr;
-
 typedef uint32_t revision_t;
 
 /// Type of the IU event. Realized as an integer to enable bit masks for filters. One of: IU_ADDED, IU_COMMITTED, IU_DELETED, IU_RETRACTED, IU_UPDATED, IU_LINKSUPDATED, IU_MESSAGE
@@ -139,7 +136,7 @@ IPAACA_HEADER_EXPORT class IUPublishedError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUPublishedError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUPublishedError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUPublishedError() {
 			_description = "IUPublishedError";
 		}
 };//}}}
@@ -148,16 +145,25 @@ IPAACA_HEADER_EXPORT class IUCommittedError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUCommittedError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUCommittedError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUCommittedError() {
 			_description = "IUCommittedError";
 		}
 };//}}}
+/// IU had already been retracted
+IPAACA_HEADER_EXPORT class IURetractedError: public Exception//{{{
+{
+	public:
+		IPAACA_HEADER_EXPORT inline ~IURetractedError() throw() { }
+		IPAACA_HEADER_EXPORT inline IURetractedError() {
+			_description = "IURetractedError";
+		}
+};//}}}
 /// Remote IU update failed because it had been modified in the mean time
 IPAACA_HEADER_EXPORT class IUUpdateFailedError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUUpdateFailedError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUUpdateFailedError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUUpdateFailedError() {
 			_description = "IUUpdateFailedError";
 		}
 };//}}}
@@ -166,7 +172,7 @@ IPAACA_HEADER_EXPORT class IUResendRequestFailedError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUResendRequestFailedError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUResendRequestFailedError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUResendRequestFailedError() {
 			_description = "IUResendRequestFailedError";
 		}
 };//}}}
@@ -175,7 +181,7 @@ IPAACA_HEADER_EXPORT class IUReadOnlyError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUReadOnlyError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUReadOnlyError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUReadOnlyError() {
 			_description = "IUReadOnlyError";
 		}
 };//}}}
@@ -184,7 +190,7 @@ IPAACA_HEADER_EXPORT class IUAlreadyInABufferError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUAlreadyInABufferError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUAlreadyInABufferError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUAlreadyInABufferError() {
 			_description = "IUAlreadyInABufferError";
 		}
 };//}}}
@@ -193,7 +199,7 @@ IPAACA_HEADER_EXPORT class IUUnpublishedError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUUnpublishedError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUUnpublishedError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUUnpublishedError() {
 			_description = "IUUnpublishedError";
 		}
 };//}}}
@@ -202,7 +208,7 @@ IPAACA_HEADER_EXPORT class IUAlreadyHasAnUIDError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUAlreadyHasAnUIDError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUAlreadyHasAnUIDError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUAlreadyHasAnUIDError() {
 			_description = "IUAlreadyHasAnUIDError";
 		}
 };//}}}
@@ -211,7 +217,7 @@ IPAACA_HEADER_EXPORT class IUAlreadyHasAnOwnerNameError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~IUAlreadyHasAnOwnerNameError() throw() { }
-		IPAACA_HEADER_EXPORT inline IUAlreadyHasAnOwnerNameError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline IUAlreadyHasAnOwnerNameError() {
 			_description = "IUAlreadyHasAnOwnerNameError";
 		}
 };//}}}
@@ -220,7 +226,7 @@ IPAACA_HEADER_EXPORT class UUIDGenerationError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~UUIDGenerationError() throw() { }
-		IPAACA_HEADER_EXPORT inline UUIDGenerationError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline UUIDGenerationError() {
 			_description = "UUIDGenerationError";
 		}
 };//}}}
@@ -229,7 +235,7 @@ IPAACA_HEADER_EXPORT class NotImplementedError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~NotImplementedError() throw() { }
-		IPAACA_HEADER_EXPORT inline NotImplementedError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline NotImplementedError() {
 			_description = "NotImplementedError";
 		}
 };//}}}
@@ -238,7 +244,7 @@ IPAACA_HEADER_EXPORT class PayloadTypeConversionError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~PayloadTypeConversionError() throw() { }
-		IPAACA_HEADER_EXPORT inline PayloadTypeConversionError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline PayloadTypeConversionError() {
 			_description = "PayloadTypeConversionError";
 		}
 };//}}}
@@ -247,7 +253,7 @@ IPAACA_HEADER_EXPORT class PayloadAddressingError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~PayloadAddressingError() throw() { }
-		IPAACA_HEADER_EXPORT inline PayloadAddressingError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline PayloadAddressingError() {
 			_description = "PayloadAddressingError";
 		}
 };//}}}
@@ -256,7 +262,7 @@ IPAACA_HEADER_EXPORT class JsonParsingError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~JsonParsingError() throw() { }
-		IPAACA_HEADER_EXPORT inline JsonParsingError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline JsonParsingError() {
 			_description = "JsonParsingError";
 		}
 };//}}}
@@ -265,7 +271,7 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxyInvalidatedError: public Exception//
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~PayloadEntryProxyInvalidatedError() throw() { }
-		IPAACA_HEADER_EXPORT inline PayloadEntryProxyInvalidatedError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline PayloadEntryProxyInvalidatedError() {
 			_description = "PayloadEntryProxyInvalidatedError";
 		}
 };//}}}
@@ -274,7 +280,7 @@ IPAACA_HEADER_EXPORT class PayloadIteratorInvalidError: public Exception//{{{
 {
 	public:
 		IPAACA_HEADER_EXPORT inline ~PayloadIteratorInvalidError() throw() { }
-		IPAACA_HEADER_EXPORT inline PayloadIteratorInvalidError() { //boost::shared_ptr<IU> iu) {
+		IPAACA_HEADER_EXPORT inline PayloadIteratorInvalidError() {
 			_description = "PayloadIteratorInvalidError";
 		}
 };//}}}
@@ -291,11 +297,18 @@ IPAACA_HEADER_EXPORT class Initializer
 		/// Initialize the backend [DEPRECATED] (old name, use initialize_backend() instead)
 		[[deprecated("Use initialize_backend() instead")]]
 		IPAACA_HEADER_EXPORT static void initialize_ipaaca_rsb_if_needed();
-		/// Explicitly initialize the backend. No effect if already initialized. Automatically called during first Buffer construction.
+		/// Explicitly initialize the backend (usually not required). No effect if already initialized. Automatically called during first Buffer construction.
 		IPAACA_HEADER_EXPORT static void initialize_backend();
 		IPAACA_HEADER_EXPORT static bool initialized();
 		IPAACA_HEADER_EXPORT static void dump_current_default_config();
 	protected:
+		/** Perform rsb pre-setup before the implicit initialization
+		 * (when first instantiating something). Pre-setup includes
+		 * finding the RSB plugin dir, looking through several parent
+		 * directories for a path "deps/lib/rsb*"/plugins. The path
+		 * can also be set directly (env var RSB_PLUGINS_CPP_PATH),
+		 * which disables the automatic search.
+		 */
 		IPAACA_HEADER_EXPORT static void auto_configure_rsb();
 		IPAACA_MEMBER_VAR_EXPORT static bool _initialized;
 };
@@ -323,10 +336,8 @@ IPAACA_HEADER_EXPORT class Initializer
 IPAACA_HEADER_EXPORT class CommandLineOptions {
 	public:
 		IPAACA_HEADER_EXPORT inline CommandLineOptions()
-		//: _unconsumed_argc(0), _unconsumed_argv(nullptr)
 		{ }
 		IPAACA_HEADER_EXPORT inline ~CommandLineOptions() {
-			//if (_unconsumed_argv) delete[] _unconsumed_argv;
 		}
 		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, std::string> param_opts;
 		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, bool> param_set;
@@ -338,13 +349,7 @@ IPAACA_HEADER_EXPORT class CommandLineOptions {
 		IPAACA_HEADER_EXPORT bool is_set(const std::string& o);
 		IPAACA_HEADER_EXPORT void dump();
 	public:
-		//IPAACA_HEADER_EXPORT inline int unconsumed_argc() { return _unconsumed_argc; }
-		//IPAACA_HEADER_EXPORT inline char** unconsumed_argv() { return _unconsumed_argv; }
-	protected:
-		//IPAACA_MEMBER_VAR_EXPORT int _unconsumed_argc;
-		//IPAACA_MEMBER_VAR_EXPORT char** _unconsumed_argv;
-	public:
-	typedef boost::shared_ptr<CommandLineOptions> ptr;
+		typedef boost::shared_ptr<CommandLineOptions> ptr;
 };
 
 /**
@@ -398,7 +403,8 @@ class CommandLineParser {
 		 * The remaining options are packaged into a CommandLineOptions object.
 		 */
 		IPAACA_HEADER_EXPORT CommandLineOptions::ptr parse(int argc, char* const* argv);
-	typedef boost::shared_ptr<CommandLineParser> ptr;
+	public:
+		typedef boost::shared_ptr<CommandLineParser> ptr;
 };
 //}}}
 // in ipaaca-string-utils.cc
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h b/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h
index 0d91d66fcb604b9bea353a8af46ba55b8eec49a3..f490dd9eb6a6d44356c133aa13201423981c7956 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-forwards.h
@@ -53,7 +53,6 @@
  *  forward declarations
  */
 class PayloadDocumentEntry;
-//class PayloadDocumentStore;
 
 class PayloadBatchUpdateLock;
 class PayloadEntryProxy;
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h b/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h
index b5609fde3d2a301c1c76fe9fe1067e74d4f05c4a..311d768a2f537e36b14d02f2bdc665e8efe53048 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-internal.h
@@ -59,8 +59,6 @@
 
 #ifdef IPAACA_EXPOSE_FULL_RSB_API
 
-// ??? ///IPAACA_HEADER_EXPORT inline std::string json_to_string(PayloadDocumentEntry::ptr entry);
-
 IPAACA_HEADER_EXPORT class CallbackIUPayloadUpdate: public rsb::patterns::Server::Callback<IUPayloadUpdate, int> {//{{{
 	protected:
 		IPAACA_MEMBER_VAR_EXPORT Buffer* _buffer;
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h b/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h
index f4fc8fc6044e9c1cd70ca39250f98695a9a1c986..7d7bc93ac2b2ccb909dc4fbe47dfbb3591f8662e 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-ius.h
@@ -95,6 +95,8 @@ IPAACA_HEADER_EXPORT class IUInterface {//{{{
 		IPAACA_HEADER_EXPORT void _add_and_remove_links(const LinkMap& add, const LinkMap& remove) { _links._add_and_remove_links(add, remove); }
 		IPAACA_HEADER_EXPORT void _replace_links(const LinkMap& links) { _links._replace_links(links); }
 	public:
+		/// Return whether IU has been retracted
+		IPAACA_HEADER_EXPORT inline bool retracted() const { return _retracted; }
 		/// Return whether IU has already been published (is in a Buffer).
 		IPAACA_HEADER_EXPORT inline bool is_published() { return (_buffer != 0); }
 		/// Return auto-generated UID string (set during IU construction)
@@ -174,7 +176,6 @@ IPAACA_HEADER_EXPORT class IU: public IUInterface {//{{{
 		IPAACA_HEADER_EXPORT IU(const std::string& category, IUAccessMode access_mode=IU_ACCESS_PUSH, bool read_only=false, const std::string& payload_type="" ); // __ipaaca_static_option_default_payload_type
 	public:
 		IPAACA_HEADER_EXPORT inline ~IU() {
-			//IPAACA_IMPLEMENT_ME
 		}
 		[[deprecated("Please use the new argument order: category, payload_type, read_only")]]
 		IPAACA_HEADER_EXPORT static boost::shared_ptr<IU> create(const std::string& category, IUAccessMode access_mode, bool read_only=false, const std::string& payload_type="" );
@@ -184,9 +185,6 @@ IPAACA_HEADER_EXPORT class IU: public IUInterface {//{{{
 		IPAACA_HEADER_EXPORT void commit() _IPAACA_OVERRIDE_;
 	protected:
 		IPAACA_HEADER_EXPORT virtual void _modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
-
-		//IPAACA_HEADER_EXPORT virtual void _publish_resend(boost::shared_ptr<IU> iu, const std::string& hidden_scope_name);
-
 		IPAACA_HEADER_EXPORT virtual void _modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name = "") _IPAACA_OVERRIDE_;
 	protected:
 		IPAACA_HEADER_EXPORT virtual void _internal_commit(const std::string& writer_name = "");
@@ -217,7 +215,6 @@ IPAACA_HEADER_EXPORT class Message: public IU {//{{{
 		IPAACA_HEADER_EXPORT Message(const std::string& category, IUAccessMode access_mode=IU_ACCESS_MESSAGE, bool read_only=true, const std::string& payload_type="" );
 	public:
 		IPAACA_HEADER_EXPORT inline ~Message() {
-			//IPAACA_IMPLEMENT_ME
 		}
 		[[deprecated("Please use the new argument order: category, payload_type")]]
 		IPAACA_HEADER_EXPORT static boost::shared_ptr<Message> create(const std::string& category, IUAccessMode access_mode, bool read_only=true, const std::string& payload_type="" );
@@ -245,7 +242,6 @@ IPAACA_HEADER_EXPORT class RemotePushIU: public IUInterface {//{{{
 		IPAACA_HEADER_EXPORT static boost::shared_ptr<RemotePushIU> create();
 	public:
 		IPAACA_HEADER_EXPORT inline ~RemotePushIU() {
-			//IPAACA_IMPLEMENT_ME
 		}
 		IPAACA_HEADER_EXPORT inline Payload& payload() _IPAACA_OVERRIDE_ { return _payload; }
 		IPAACA_HEADER_EXPORT inline const Payload& const_payload() const _IPAACA_OVERRIDE_ { return _payload; }
@@ -274,7 +270,6 @@ IPAACA_HEADER_EXPORT class RemoteMessage: public IUInterface {//{{{
 		IPAACA_HEADER_EXPORT static boost::shared_ptr<RemoteMessage> create();
 	public:
 		IPAACA_HEADER_EXPORT inline ~RemoteMessage() {
-			//IPAACA_IMPLEMENT_ME
 		}
 		IPAACA_HEADER_EXPORT inline Payload& payload() _IPAACA_OVERRIDE_ { return _payload; }
 		IPAACA_HEADER_EXPORT inline const Payload& const_payload() const _IPAACA_OVERRIDE_ { return _payload; }
@@ -290,6 +285,7 @@ IPAACA_HEADER_EXPORT class RemoteMessage: public IUInterface {//{{{
 	typedef boost::shared_ptr<RemoteMessage> ptr;
 };//}}}
 
+#ifdef IPAACA_BUILD_MOCK_OBJECTS
 /// Mock IU for testing purposes. [INTERNAL]
 IPAACA_HEADER_EXPORT class FakeIU: public IUInterface {//{{{
 	friend class Buffer;
@@ -318,5 +314,6 @@ IPAACA_HEADER_EXPORT class FakeIU: public IUInterface {//{{{
 	public:
 	typedef boost::shared_ptr<FakeIU> ptr;
 };//}}}
+#endif
 
 #endif
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
index dcf33e81d3d7ecebff94ff721e1e669b1ca0e17d..f346f3f5b80384a12004500cf4e5c869a40f5b83 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca-payload.h
@@ -111,12 +111,6 @@ IPAACA_HEADER_EXPORT template<typename T> void pack_into_json_value(rapidjson::V
 		valueobject.AddMember(key, newv, allocator);
 	}
 }
-/*IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::vector<std::string>&);
-IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::list<std::string>&);
-IPAACA_HEADER_EXPORT template<> void pack_into_json_value(rapidjson::Value&, rapidjson::Document::AllocatorType&, const std::map<std::string, std::string>&);
-*/
-
-// FIXME TODO locking / invalidating proxy on first write of a payload entry
 
 /// Single payload entry wrapping a rapidjson::Document with some conversion glue. Also handles copy-on-write Document cloning. <b>Internal type</b> - users generally do not see this.
 IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{
@@ -125,18 +119,15 @@ IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{
 	public:
 		IPAACA_MEMBER_VAR_EXPORT ipaaca::Lock lock;
 		IPAACA_MEMBER_VAR_EXPORT bool modified;
-		//IPAACA_MEMBER_VAR_EXPORT std::string json_source;
 		IPAACA_MEMBER_VAR_EXPORT rapidjson::Document document;
 		IPAACA_HEADER_EXPORT inline PayloadDocumentEntry(): modified(false) { }
 		IPAACA_HEADER_EXPORT inline ~PayloadDocumentEntry() { }
-		//IPAACA_HEADER_EXPORT PayloadDocumentEntry(const std::string& source): modified(false), json_source(source), {};
 		IPAACA_HEADER_EXPORT std::string to_json_string_representation();
 		IPAACA_HEADER_EXPORT static std::shared_ptr<PayloadDocumentEntry> from_json_string_representation(const std::string& input);
 		IPAACA_HEADER_EXPORT static std::shared_ptr<PayloadDocumentEntry> from_unquoted_string_value(const std::string& input);
 		IPAACA_HEADER_EXPORT static std::shared_ptr<PayloadDocumentEntry> create_null();
 		IPAACA_HEADER_EXPORT std::shared_ptr<PayloadDocumentEntry> clone();
 		IPAACA_HEADER_EXPORT rapidjson::Value& get_or_create_nested_value_from_proxy_path(PayloadEntryProxy* pep);
-		//IPAACA_HEADER_EXPORT void update_json_source();
 	typedef std::shared_ptr<PayloadDocumentEntry> ptr;
 };
 //}}}
@@ -144,22 +135,6 @@ IPAACA_HEADER_EXPORT class PayloadDocumentEntry//{{{
 typedef std::map<std::string, PayloadDocumentEntry::ptr> PayloadDocumentStore;
 
 
-#if 0
-/** \brief Lock to accumulate payload changes into one single update transaction
- *
- */
-IPAACA_HEADER_EXPORT class PayloadBatchUpdateLock: public ipaaca::Lock
-{
-	friend class Payload;
-	protected:
-		Payload* _payload;
-	public:
-		IPAACA_HEADER_EXPORT inline PayloadBatchUpdateLock(): Lock() { }
-		IPAACA_HEADER_EXPORT void on_lock() override;
-		IPAACA_HEADER_EXPORT void on_unlock() override;
-};
-#endif
-
 /** \brief Central class containing the user-set payload of any IUInterface class (IU, Message, RemotePushIU or RemoteMessage)
  *
  * Obtained by calling payload() on any IUInterface derived object. Created during IU creation.
@@ -178,17 +153,11 @@ IPAACA_HEADER_EXPORT class Payload: public Lock //{{{
 	friend class PayloadEntryProxy;
 	friend class PayloadIterator;
 	friend class FakeIU;
-	//friend class PayloadBatchUpdateLock;
 	protected:
 		IPAACA_MEMBER_VAR_EXPORT std::string _owner_name;
-		//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document _json_document;
-		//IPAACA_MEMBER_VAR_EXPORT std::map<std::string, rapidjson::Document> _json_store;
 		IPAACA_MEMBER_VAR_EXPORT PayloadDocumentStore _document_store;
 		IPAACA_MEMBER_VAR_EXPORT boost::weak_ptr<IUInterface> _iu;
-		//IPAACA_MEMBER_VAR_EXPORT PayloadBatchUpdateLock _batch_update_lock;
-		//
 		IPAACA_MEMBER_VAR_EXPORT Lock _payload_operation_mode_lock; //< enforcing atomicity wrt the bool flag below
-		//
 		IPAACA_MEMBER_VAR_EXPORT bool _update_on_every_change; //< true: batch update not active; false: collecting updates (payload locked)
 		IPAACA_MEMBER_VAR_EXPORT std::map<std::string, PayloadDocumentEntry::ptr> _collected_modifications;
 		IPAACA_MEMBER_VAR_EXPORT std::vector<std::string> _collected_removals;
@@ -199,13 +168,11 @@ IPAACA_HEADER_EXPORT class Payload: public Lock //{{{
 		/// inherited from ipaaca::Lock, finishing batch update collection mode
 		IPAACA_HEADER_EXPORT void on_unlock() override;
 	protected:
-		//IPAACA_HEADER_EXPORT ipaaca::Locker&& batch_update() { return std::move(ipaaca::Locker(*this); }
 		IPAACA_HEADER_EXPORT void initialize(boost::shared_ptr<IUInterface> iu);
 		IPAACA_HEADER_EXPORT inline void _set_owner_name(const std::string& name) { _owner_name = name; }
 		IPAACA_HEADER_EXPORT void _remotely_enforced_wipe();
 		IPAACA_HEADER_EXPORT void _remotely_enforced_delitem(const std::string& k);
 		IPAACA_HEADER_EXPORT void _remotely_enforced_setitem(const std::string& k, PayloadDocumentEntry::ptr entry);
-		//IPAACA_HEADER_EXPORT void _internal_replace_all(const std::map<std::string, PayloadDocumentEntry::ptr>& new_contents, const std::string& writer_name="");
 		IPAACA_HEADER_EXPORT void _internal_replace_all(const std::map<std::string, PayloadDocumentEntry::ptr>& new_contents, const std::string& writer_name="");
 		IPAACA_HEADER_EXPORT void _internal_merge(const std::map<std::string, PayloadDocumentEntry::ptr>& contents_to_merge, const std::string& writer_name="");
 		IPAACA_HEADER_EXPORT void _internal_set(const std::string& k, PayloadDocumentEntry::ptr v, const std::string& writer_name="");
@@ -221,11 +188,6 @@ IPAACA_HEADER_EXPORT class Payload: public Lock //{{{
 		IPAACA_HEADER_EXPORT operator std::map<std::string, std::string>();
 		/// remove a single payload entry
 		IPAACA_HEADER_EXPORT inline void remove(const std::string& k) { _internal_remove(k); }
-		// FIXME: json: these two must support a bunch of standard types, not [only] json (users touch them)
-		//  to be more precise: types of map<string, T> with T several interesting things (string, list<string>, etc.)
-		//IPAACA_HEADER_EXPORT inline void set(const std::map<std::string, const rapidjson::Document&>& all_elems) { _internal_replace_all(all_elems); }
-		//IPAACA_HEADER_EXPORT inline void merge(const std::map<std::string, const rapidjson::Document&>& elems_to_merge) { _internal_merge(elems_to_merge); }
-		// legacy / convenience setter
 		/// Legacy / convenience function: set the whole payload map from a map string->string (all JSON types are also set as string, no interpretation)
 		IPAACA_HEADER_EXPORT void set(const std::map<std::string, std::string>& all_elems);
 	protected:
@@ -235,7 +197,7 @@ IPAACA_HEADER_EXPORT class Payload: public Lock //{{{
 	public:
 		[[deprecated("Use operator[] and operator std::string() instead")]]
 		/// Read a single entry as string [DEPRECATED] (use string conversion in PayloadEntryProxy instead)
-		IPAACA_HEADER_EXPORT std::string get(const std::string& k); // DEPRECATED
+		IPAACA_HEADER_EXPORT std::string get(const std::string& k);
 	protected:
 		IPAACA_MEMBER_VAR_EXPORT unsigned long internal_revision;
 		IPAACA_MEMBER_VAR_EXPORT inline void mark_revision_change() { internal_revision++; }
@@ -267,7 +229,6 @@ IPAACA_HEADER_EXPORT class PayloadIterator//{{{
 		IPAACA_MEMBER_VAR_EXPORT Payload* _payload;
 		IPAACA_MEMBER_VAR_EXPORT unsigned long reference_payload_revision;
 		IPAACA_MEMBER_VAR_EXPORT PayloadDocumentStore::iterator raw_iterator;
-		//IPAACA_MEMBER_VAR_EXPORT bool is_end;
 	protected:
 		IPAACA_HEADER_EXPORT PayloadIterator(Payload* payload, PayloadDocumentStore::iterator&& pl_iter ); //, bool is_end);
 	public:
@@ -277,7 +238,6 @@ IPAACA_HEADER_EXPORT class PayloadIterator//{{{
 		IPAACA_HEADER_EXPORT std::shared_ptr<std::pair<std::string, PayloadEntryProxy> > operator->();
 		IPAACA_HEADER_EXPORT bool operator==(const PayloadIterator& ref);
 		IPAACA_HEADER_EXPORT bool operator!=(const PayloadIterator& ref);
-		// constructor to create a new top-most parent proxy (from a payload key)
 };
 //}}}
 
@@ -352,7 +312,7 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxyListDecorator//{{{
  *
  * <code>for (auto val: iu->payload()["my_list"].as_list()) { ... }</code>  // as_list is required to select list-type iteration (value type in iteration remains variant)
  *
- * <code>for (auto k_v_map: iu->payload()["my_map"].as_map()) { ... }</code>  // as_map is required to select map-type iteration (value type in iteration is a pair, second part remains variant)
+ * <code>for (auto k_v_pair: iu->payload()["my_map"].as_map()) { ... }</code>  // as_map is required to select map-type iteration (value type in iteration is a pair, second part remains variant)
  *
  * \b Examples (writing):
  * 
@@ -382,13 +342,9 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 		/// Select list-style iteration for this proxy (to select iterator content type). Will throw if not actually list-type. See example in the class description.
 		IPAACA_HEADER_EXPORT PayloadEntryProxyListDecorator as_list();
 	protected:
-		//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_parent_node;
-		//IPAACA_MEMBER_VAR_EXPORT rapidjson::Document* _json_node;
 		IPAACA_MEMBER_VAR_EXPORT Payload* _payload;
 		IPAACA_MEMBER_VAR_EXPORT std::string _key;
-		//
 		// new json stuff / hierarchical navigation
-		//
 		IPAACA_MEMBER_VAR_EXPORT PayloadEntryProxy* parent; ///< Parent proxy (up to document root -> then null)
 		IPAACA_MEMBER_VAR_EXPORT PayloadDocumentEntry::ptr document_entry; // contains lock and json Doc
 		IPAACA_MEMBER_VAR_EXPORT bool existent; ///< Whether Value exists already (or else 'blindly' navigated)
@@ -397,9 +353,6 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 		IPAACA_MEMBER_VAR_EXPORT std::string addressed_key; ///< Key that was used in map-style access
 		/// currently navigated value in json tree (or a new Null value)
 		IPAACA_MEMBER_VAR_EXPORT rapidjson::Value* json_value; ///< json value that corresponds to the current navigation (or nullptr)
-/*	protected:
-		IPAACA_HEADER_EXPORT void connect_to_existing_parents();
-*/
 	protected:
 		// constructor to create a new top-most parent proxy (from a payload key)
 		IPAACA_HEADER_EXPORT PayloadEntryProxy(Payload* payload, const std::string& key);
@@ -440,7 +393,6 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 			PayloadDocumentEntry::ptr new_entry = document_entry->clone(); // copy-on-write, no lock required
 			rapidjson::Value& newval = new_entry->get_or_create_nested_value_from_proxy_path(this);
 			pack_into_json_value(newval, new_entry->document.GetAllocator(), t);
-			//new_entry->update_json_source();
 			_payload->set(_key, new_entry);
 			return *this;
 		}
@@ -473,11 +425,6 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 		/// Copy value from below other json node, preserving types
 		IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const PayloadEntryProxy& otherproxy);
 		
-		//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const std::string& value);
-		//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(const char* value);
-		//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(double value);
-		//IPAACA_HEADER_EXPORT PayloadEntryProxy& operator=(bool value);
-		
 		/// Conversion to std::string (explicit or implicit)
 		IPAACA_HEADER_EXPORT operator std::string();
 		/// Conversion to long (explicit or implicit)
@@ -513,7 +460,7 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 			}
 			return result;
 		}
-		// FIXME why are these needed again?
+		// TODO maybe remove these deprecated converters later
 		/// [DECPRECATED] use normal type conversion syntax instead
 		[[deprecated("Use operator std::string() instead (i.e. explicit or implicit cast)")]]
 		IPAACA_HEADER_EXPORT std::string to_str();
@@ -527,15 +474,6 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 		/// [DECPRECATED] use normal type conversion syntax instead
 		[[deprecated("Use operator bool() instead (i.e. explicit or implicit cast)")]]
 		IPAACA_HEADER_EXPORT bool to_bool();
-		// getters  (not needed since conversions are enough?)
-		//IPAACA_HEADER_EXPORT template<typename T> T get() { return json_value_cast<T>(json_value); }
-		// setters
-		//IPAACA_HEADER_EXPORT template<typename T> PayloadEntryProxy& set(T t);
-		/*{
-			pack_into_json_value<T>(t);
-			connect_to_existing_parents();
-			_payload->set(key, document_entry->document);
-		}*/
 		/// Append a supported type to a list-type payload value
 		IPAACA_HEADER_EXPORT template<typename T> void push_back(T t)
 		{
@@ -603,18 +541,6 @@ IPAACA_HEADER_EXPORT class PayloadEntryProxy//{{{
 			_payload->set(_key, new_entry);
 		}
 };
-// Available interpretations of payload entries (or children thereof) below.
-//  Usage of standard complex data structures (vector etc.) currently entails
-//  casting all entries to a uniform type (a-priori choice: std::string).
-/*
-IPAACA_HEADER_EXPORT template<> long PayloadEntryProxy::get();
-IPAACA_HEADER_EXPORT template<> double PayloadEntryProxy::get();
-IPAACA_HEADER_EXPORT template<> bool PayloadEntryProxy::get();
-IPAACA_HEADER_EXPORT template<> std::string PayloadEntryProxy::get();
-IPAACA_HEADER_EXPORT template<> std::vector<std::string> PayloadEntryProxy::get();
-IPAACA_HEADER_EXPORT template<> std::list<std::string> PayloadEntryProxy::get();
-IPAACA_HEADER_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get();
-*/
 
 //}}}
 
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca.h b/ipaacalib/cpp/include/ipaaca/ipaaca.h
index 04f62ee0d2b2c45b079747a732007be22451c30e..16d3844a8e0dc7a970c2318512a7ba0b692b10cb 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca.h
+++ b/ipaacalib/cpp/include/ipaaca/ipaaca.h
@@ -67,9 +67,9 @@ IU payload contents: Payload, PayloadEntryProxy
 #define IPAACA_PROTOCOL_VERSION_MINOR         0
 
 /// running release number of ipaaca-c++
-#define IPAACA_CPP_RELEASE_NUMBER             12
+#define IPAACA_CPP_RELEASE_NUMBER             13
 /// date of last release number increment
-#define IPAACA_CPP_RELEASE_DATE     "2015-01-15"
+#define IPAACA_CPP_RELEASE_DATE     "2015-12-04"
 
 #ifndef __FUNCTION_NAME__
 	#ifdef WIN32   // Windows
@@ -209,6 +209,11 @@ IPAACA_MEMBER_VAR_EXPORT extern std::string __ipaaca_static_option_default_chann
 /// Current console log level (defaults to warning), one of: IPAACA_LOG_LEVEL_CRITICAL, IPAACA_LOG_LEVEL_ERROR, IPAACA_LOG_LEVEL_WARNING, IPAACA_LOG_LEVEL_INFO, IPAACA_LOG_LEVEL_DEBUG, IPAACA_LOG_LEVEL_NONE
 IPAACA_MEMBER_VAR_EXPORT extern unsigned int __ipaaca_static_option_log_level;
 
+/// RSB host to connect to (defaults to "" = do not set, use global config)
+IPAACA_MEMBER_VAR_EXPORT extern std::string __ipaaca_static_option_rsb_spread_host;
+/// RSB port to connect to (defaults to "" = do not set, use global config)
+IPAACA_MEMBER_VAR_EXPORT extern std::string __ipaaca_static_option_rsb_spread_port;
+
 IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock();
 
 #ifdef WIN32
@@ -218,6 +223,21 @@ IPAACA_MEMBER_VAR_EXPORT Lock& logger_lock();
 #define LOG_IPAACA_CONSOLE(msg) { ipaaca::Locker logging_locker(ipaaca::logger_lock()); timeval logging_tim; gettimeofday(&logging_tim, NULL); double logging_t1=logging_tim.tv_sec+(logging_tim.tv_usec/1000000.0); std::cout << "[LOG] " << std::setprecision(15) << logging_t1 << " : " << msg << std::endl; }
 #endif
 
+#ifdef WIN32
+#define IPAACA_SIMPLE_TIMER_BEGIN(N) ;
+#define IPAACA_SIMPLE_TIMER_END(N, NAME) LOG_IPAACA_CONSOLE(NAME << " - time elapsed: Windows - IMPLEMENT ME")
+#else
+/// use IPAACA_SIMPLE_TIMER_BEGIN(mysymbol) to start time profiling at a line in code
+/// Several blocks can be defined in the same stack frame if different symbols are chosen
+#define IPAACA_SIMPLE_TIMER_BEGIN(N) struct timeval _ipaaca_timer_tvstart_ ## N; \
+	gettimeofday(&_ipaaca_timer_tvstart_ ## N, NULL);
+/// use IPAACA_SIMPLE_TIMER_END(mysymbol, "message") to print time elapsed since correpsonding _BEGIN
+#define IPAACA_SIMPLE_TIMER_END(N, NAME) struct timeval _ipaaca_timer_tvend_ ## N; \
+	gettimeofday(&_ipaaca_timer_tvend_ ## N, NULL); \
+	long _ipaaca_timer_usecs_ ## N = (_ipaaca_timer_tvend_ ## N.tv_sec*1000000 + _ipaaca_timer_tvend_ ## N.tv_usec) - (_ipaaca_timer_tvstart_ ## N.tv_sec*1000000 + _ipaaca_timer_tvstart_ ## N.tv_usec); \
+	LOG_IPAACA_CONSOLE(NAME << " - ̨́us elapsed: " << _ipaaca_timer_usecs_ ## N)
+#endif
+
 #include <ipaaca/ipaaca-payload.h>
 #include <ipaaca/ipaaca-buffers.h>
 #include <ipaaca/ipaaca-ius.h>
diff --git a/ipaacalib/cpp/include/ipaaca/util/notifier.h b/ipaacalib/cpp/include/ipaaca/util/notifier.h
index c16a4dfc35be4729f4d447d405ac3ea658118be8..52ad449050fc97d279149c13b21e106291d3c603 100644
--- a/ipaacalib/cpp/include/ipaaca/util/notifier.h
+++ b/ipaacalib/cpp/include/ipaaca/util/notifier.h
@@ -3,8 +3,9 @@
  *  "Incremental Processing Architecture
  *   for Artificial Conversational Agents".  
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
diff --git a/ipaacalib/cpp/src/ipaaca-buffers.cc b/ipaacalib/cpp/src/ipaaca-buffers.cc
index 8c99b7d3b2a6db1c952694645bf61e0de70a4ca0..33efa991d9e55533282ca3c22223731574ac736c 100644
--- a/ipaacalib/cpp/src/ipaaca-buffers.cc
+++ b/ipaacalib/cpp/src/ipaaca-buffers.cc
@@ -118,8 +118,6 @@ IPAACA_EXPORT IUEventHandler::IUEventHandler(IUEventHandlerFunction function, IU
 IPAACA_EXPORT void IUEventHandler::call(Buffer* buffer, boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category)
 {
 	if (_condition_met(event_type, category)) {
-		//IUInterface::ptr iu = buffer->get(uid);
-		//if (iu) {
 #if VERBOSE_HANDLERS == 1
 			std::cout << "[" << pthread_self() << " handler ENTER]" << std::endl;
 #endif
@@ -127,7 +125,6 @@ IPAACA_EXPORT void IUEventHandler::call(Buffer* buffer, boost::shared_ptr<IUInte
 #if VERBOSE_HANDLERS == 1
 			std::cout << "[" << pthread_self() << " handler EXIT]" << std::endl;
 #endif
-		//}
 	}
 }
 //}}}
@@ -141,20 +138,19 @@ IPAACA_EXPORT void Buffer::_allocate_unique_name(const std::string& basename, co
 }
 IPAACA_EXPORT void Buffer::register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::set<std::string>& categories)
 {
-	std::cout << "register_handler " << function << " " << event_mask << " " << categories << std::endl;
+	IPAACA_DEBUG("register_handler " << function << " " << event_mask << " " << categories)
 	IUEventHandler::ptr handler = IUEventHandler::ptr(new IUEventHandler(function, event_mask, categories));
 	_event_handlers.push_back(handler);
 }
 IPAACA_EXPORT void Buffer::register_handler(IUEventHandlerFunction function, IUEventType event_mask, const std::string& category)
 {
-	std::cout << "register_handler " << function << " " << event_mask << " " << category << std::endl;
+	IPAACA_DEBUG("register_handler " << function << " " << event_mask << " " << category)
 	IUEventHandler::ptr handler = IUEventHandler::ptr(new IUEventHandler(function, event_mask, category));
 	_event_handlers.push_back(handler);
 }
 IPAACA_EXPORT void Buffer::call_iu_event_handlers(boost::shared_ptr<IUInterface> iu, bool local, IUEventType event_type, const std::string& category)
 {
-	//IPAACA_INFO("handling an event " << ipaaca::iu_event_type_to_str(event_type) << " for IU " << iu->uid())
-	//std::cout << "handling an event " << ipaaca::iu_event_type_to_str(event_type) << " for IU " << iu->uid() << std::endl;
+	//IPAACA_DEBUG("handling an event " << ipaaca::iu_event_type_to_str(event_type) << " for IU " << iu->uid())
 	for (std::vector<IUEventHandler::ptr>::iterator it = _event_handlers.begin(); it != _event_handlers.end(); ++it) {
 		(*it)->call(this, iu, local, event_type, category);
 	}
@@ -165,13 +161,10 @@ IPAACA_EXPORT void Buffer::call_iu_event_handlers(boost::shared_ptr<IUInterface>
 IPAACA_EXPORT CallbackIUPayloadUpdate::CallbackIUPayloadUpdate(Buffer* buffer): _buffer(buffer) { }
 IPAACA_EXPORT CallbackIULinkUpdate::CallbackIULinkUpdate(Buffer* buffer): _buffer(buffer) { }
 IPAACA_EXPORT CallbackIUCommission::CallbackIUCommission(Buffer* buffer): _buffer(buffer) { }
-// dlw
 IPAACA_EXPORT CallbackIUResendRequest::CallbackIUResendRequest(Buffer* buffer): _buffer(buffer) { }
 
 IPAACA_EXPORT boost::shared_ptr<int> CallbackIUPayloadUpdate::call(const std::string& methodName, boost::shared_ptr<IUPayloadUpdate> update)
 {
-	IPAACA_INFO("")
-	//std::cout << "-- Received a modify_payload with " << update->new_items.size() << " keys to merge." << std::endl;
 	IUInterface::ptr iui = _buffer->get(update->uid);
 	if (! iui) {
 		IPAACA_WARNING("Remote InBuffer tried to spuriously write non-existent IU " << update->uid)
@@ -180,13 +173,25 @@ IPAACA_EXPORT boost::shared_ptr<int> CallbackIUPayloadUpdate::call(const std::st
 	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
 	iu->_revision_lock.lock();
 	if ((update->revision != 0) && (update->revision != iu->_revision)) {
-		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid)
-		IPAACA_INFO(" Referred-to revision was " << update->revision << " while local one is " << iu->_revision)
+		IPAACA_WARNING("Remote write operation failed because request was out of date; IU " << update->uid)
+		IPAACA_WARNING(" Referred-to revision was " << update->revision << " while local one is " << iu->_revision)
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->committed()) {
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->retracted()) {
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->committed()) {
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->retracted()) {
 		iu->_revision_lock.unlock();
 		return boost::shared_ptr<int>(new int(0));
 	}
 	if (update->is_delta) {
-		// FIXME FIXME this is an unsolved problem atm: deletes in a delta update are
+		// FIXME TODO this is an unsolved problem atm: deletions in a delta update are
 		// sent individually. We should have something like _internal_merge_and_remove
 		for (std::vector<std::string>::const_iterator it=update->keys_to_remove.begin(); it!=update->keys_to_remove.end(); ++it) {
 			iu->payload()._internal_remove(*it, update->writer_name); //_buffer->unique_name());
@@ -196,7 +201,6 @@ IPAACA_EXPORT boost::shared_ptr<int> CallbackIUPayloadUpdate::call(const std::st
 	} else {
 		iu->payload()._internal_replace_all(update->new_items, update->writer_name); //_buffer->unique_name());
 	}
-	//std::cout << "-- Calling update handler due to remote write." << std::endl;
 	_buffer->call_iu_event_handlers(iu, true, IU_UPDATED, iu->category());
 	revision_t revision = iu->revision();
 	iu->_revision_lock.unlock();
@@ -213,7 +217,19 @@ IPAACA_EXPORT boost::shared_ptr<int> CallbackIULinkUpdate::call(const std::strin
 	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
 	iu->_revision_lock.lock();
 	if ((update->revision != 0) && (update->revision != iu->_revision)) {
-		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid)
+		IPAACA_WARNING("Remote write operation failed because request was out of date; IU " << update->uid)
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->committed()) {
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->retracted()) {
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->committed()) {
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->retracted()) {
 		iu->_revision_lock.unlock();
 		return boost::shared_ptr<int>(new int(0));
 	}
@@ -237,11 +253,14 @@ IPAACA_EXPORT boost::shared_ptr<int> CallbackIUCommission::call(const std::strin
 	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
 	iu->_revision_lock.lock();
 	if ((update->revision() != 0) && (update->revision() != iu->_revision)) {
-		IPAACA_INFO("Remote write operation failed because request was out of date; IU " << update->uid())
+		IPAACA_WARNING("Remote write operation failed because request was out of date; IU " << update->uid())
 		iu->_revision_lock.unlock();
 		return boost::shared_ptr<int>(new int(0));
-	}
-	if (iu->committed()) {
+	} else if (iu->committed()) {
+		iu->_revision_lock.unlock();
+		return boost::shared_ptr<int>(new int(0));
+	} else if (iu->retracted()) {
+		iu->_revision_lock.unlock();
 		return boost::shared_ptr<int>(new int(0));
 	} else {
 	}
@@ -251,7 +270,6 @@ IPAACA_EXPORT boost::shared_ptr<int> CallbackIUCommission::call(const std::strin
 	iu->_revision_lock.unlock();
 	return boost::shared_ptr<int>(new int(revision));
 }
-/** dlw */
 IPAACA_EXPORT boost::shared_ptr<int> CallbackIUResendRequest::call(const std::string& methodName, boost::shared_ptr<protobuf::IUResendRequest> update)
 {
 	IUInterface::ptr iui = _buffer->get(update->uid());
@@ -261,12 +279,8 @@ IPAACA_EXPORT boost::shared_ptr<int> CallbackIUResendRequest::call(const std::st
 	}
 	IU::ptr iu = boost::static_pointer_cast<IU>(iui);
 	if ((update->has_hidden_scope_name() == true)&&(update->hidden_scope_name().compare("") != 0)){
-		//_buffer->call_iu_event_handlers(iu, true, IU_UPDATED, update->hidden_scope_name());
 		revision_t revision = iu->revision();
-
 		_buffer->_publish_iu_resend(iu, update->hidden_scope_name());
-		//iu->_publish_resend(iu, update->hidden_scope_name());
-
 		return boost::shared_ptr<int>(new int(revision));
 	} else {
 		revision_t revision = 0;
@@ -280,25 +294,17 @@ IPAACA_EXPORT boost::shared_ptr<int> CallbackIUResendRequest::call(const std::st
 IPAACA_EXPORT OutputBuffer::OutputBuffer(const std::string& basename, const std::string& channel)
 :Buffer(basename, "OB")
 {
-	//IPAACA_INFO("Entering ...")
 	_id_prefix = _basename + "-" + _uuid + "-IU-";
 	_channel = (channel=="") ? __ipaaca_static_option_default_channel: channel;
 	_initialize_server();
-	//IPAACA_INFO("... exiting.")
 }
 IPAACA_EXPORT void OutputBuffer::_initialize_server()
 {
-	//IPAACA_INFO("Entering ...")
 	_server = getFactory().createLocalServer( Scope( _unique_name ) );
-	//_server = getFactory().createServer( Scope( _unique_name ) );
-	//IPAACA_INFO("Registering methods")
 	_server->registerMethod("updatePayload", Server::CallbackPtr(new CallbackIUPayloadUpdate(this)));
 	_server->registerMethod("updateLinks", Server::CallbackPtr(new CallbackIULinkUpdate(this)));
 	_server->registerMethod("commit", Server::CallbackPtr(new CallbackIUCommission(this)));
-	// dlw
 	_server->registerMethod("resendRequest", Server::CallbackPtr(new CallbackIUResendRequest(this)));
-
-	//IPAACA_INFO("... exiting.")
 }
 IPAACA_EXPORT OutputBuffer::ptr OutputBuffer::create(const std::string& basename)
 {
@@ -362,11 +368,6 @@ IPAACA_EXPORT void OutputBuffer::_send_iu_commission(IUInterface* iu, revision_t
 	informer->publish(data);
 }
 
-
-
-
-
-
 IPAACA_EXPORT void OutputBuffer::add(IU::ptr iu)
 {
 	if (_iu_store.count(iu->uid()) > 0) {
@@ -374,12 +375,14 @@ IPAACA_EXPORT void OutputBuffer::add(IU::ptr iu)
 	}
 	if (iu->is_published()) {
 		throw IUPublishedError();
+	} else if (iu->retracted()) {
+		throw IURetractedError();
 	}
 	if (iu->access_mode() != IU_ACCESS_MESSAGE) {
 		// (for Message-type IUs: do not actually store them)
 		_iu_store[iu->uid()] = iu;
 	}
-	iu->_associate_with_buffer(this); //shared_from_this());
+	iu->_associate_with_buffer(this);
 	_publish_iu(iu);
 }
 
@@ -397,17 +400,14 @@ IPAACA_EXPORT void OutputBuffer::_publish_iu_resend(IU::ptr iu, const std::strin
 	informer->publish(iu_data);
 }
 
-
-
-
 IPAACA_EXPORT Informer<AnyType>::Ptr OutputBuffer::_get_informer(const std::string& category)
 {
 	if (_informer_store.count(category) > 0) {
 		return _informer_store[category];
 	} else {
-		//IPAACA_INFO("Making new informer for category " << category)
+		//IPAACA_INFO("Creating new informer for category " << category << " on channel " << _channel)
 		std::string scope_string = "/ipaaca/channel/" + _channel + "/category/" + category;
-		IPAACA_INFO("Adding informer on " << scope_string)
+		IPAACA_INFO("Creating new informer for " << scope_string)
 
 		Informer<AnyType>::Ptr informer = getFactory().createInformer<AnyType> ( Scope(scope_string));
 		_informer_store[category] = informer;
@@ -433,6 +433,8 @@ IPAACA_EXPORT boost::shared_ptr<IU> OutputBuffer::remove(IU::ptr iu)
 
 IPAACA_EXPORT void OutputBuffer::_retract_iu(IU::ptr iu)
 {
+	if (iu->_retracted) return; // ignore subsequent retractions
+	iu->_retracted = true;
 	Informer<protobuf::IURetraction>::DataPtr data(new protobuf::IURetraction());
 	data->set_uid(iu->uid());
 	data->set_revision(iu->revision());
@@ -440,6 +442,19 @@ IPAACA_EXPORT void OutputBuffer::_retract_iu(IU::ptr iu)
 	informer->publish(data);
 }
 
+IPAACA_EXPORT void OutputBuffer::_retract_all_internal()
+{
+	for (IUStore::iterator it=_iu_store.begin(); it!=_iu_store.end(); ++it) {
+		if (!(it->second->_retracted)) {
+			_retract_iu(it->second);
+		}
+	}
+}
+
+IPAACA_EXPORT OutputBuffer::~OutputBuffer()
+{
+	_retract_all_internal();
+}
 
 //}}}
 
@@ -448,7 +463,6 @@ IPAACA_EXPORT InputBuffer::InputBuffer(const BufferConfiguration& bufferconfigur
 :Buffer(bufferconfiguration.get_basename(), "IB")
 {
 	_channel = bufferconfiguration.get_channel();
-
 	for (std::vector<std::string>::const_iterator it=bufferconfiguration.get_category_interests().begin(); it!=bufferconfiguration.get_category_interests().end(); ++it) {
 		_create_category_listener_if_needed(*it);
 	}
@@ -459,7 +473,6 @@ IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::s
 :Buffer(basename, "IB")
 {
 	_channel = __ipaaca_static_option_default_channel;
-
 	for (std::set<std::string>::const_iterator it=category_interests.begin(); it!=category_interests.end(); ++it) {
 		_create_category_listener_if_needed(*it);
 	}
@@ -470,29 +483,16 @@ IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::v
 :Buffer(basename, "IB")
 {
 	_channel = __ipaaca_static_option_default_channel;
-
 	for (std::vector<std::string>::const_iterator it=category_interests.begin(); it!=category_interests.end(); ++it) {
 		_create_category_listener_if_needed(*it);
 	}
 	_create_category_listener_if_needed(_uuid);
 	triggerResend = false;
 }
-/*IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::initializer_list<std::string>& category_interests)
-:Buffer(basename, "IB")
-{
-	_channel = __ipaaca_static_option_default_channel;
-
-	for (std::initializer_list<std::string>::const_iterator it=category_interests.begin(); it!=category_interests.end(); ++it) {
-		_create_category_listener_if_needed(*it);
-	}
-	_create_category_listener_if_needed(_uuid);
-	triggerResend = false;
-}*/
 IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::string& category_interest1)
 :Buffer(basename, "IB")
 {
 	_channel = __ipaaca_static_option_default_channel;
-
 	_create_category_listener_if_needed(category_interest1);
 	_create_category_listener_if_needed(_uuid);
 	triggerResend = false;
@@ -501,7 +501,6 @@ IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::s
 :Buffer(basename, "IB")
 {
 	_channel = __ipaaca_static_option_default_channel;
-
 	_create_category_listener_if_needed(category_interest1);
 	_create_category_listener_if_needed(category_interest2);
 	_create_category_listener_if_needed(_uuid);
@@ -511,7 +510,6 @@ IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::s
 :Buffer(basename, "IB")
 {
 	_channel = __ipaaca_static_option_default_channel;
-
 	_create_category_listener_if_needed(category_interest1);
 	_create_category_listener_if_needed(category_interest2);
 	_create_category_listener_if_needed(category_interest3);
@@ -522,7 +520,6 @@ IPAACA_EXPORT InputBuffer::InputBuffer(const std::string& basename, const std::s
 :Buffer(basename, "IB")
 {
 	_channel = __ipaaca_static_option_default_channel;
-
 	_create_category_listener_if_needed(category_interest1);
 	_create_category_listener_if_needed(category_interest2);
 	_create_category_listener_if_needed(category_interest3);
@@ -567,7 +564,6 @@ IPAACA_EXPORT InputBuffer::ptr InputBuffer::create(const std::string& basename,
 	return InputBuffer::ptr(new InputBuffer(basename, category_interest1, category_interest2, category_interest3, category_interest4));
 }
 
-
 IPAACA_EXPORT void InputBuffer::set_resend(bool resendActive)
 {
 	triggerResend = resendActive;
@@ -578,21 +574,19 @@ IPAACA_EXPORT bool InputBuffer::get_resend()
 	return triggerResend;
 }
 
-
 IPAACA_EXPORT IUInterface::ptr InputBuffer::get(const std::string& iu_uid)
 {
-	RemotePushIUStore::iterator it = _iu_store.find(iu_uid); // TODO genericize
+	RemotePushIUStore::iterator it = _iu_store.find(iu_uid);
 	if (it==_iu_store.end()) return IUInterface::ptr();
 	return it->second;
 }
 IPAACA_EXPORT std::set<IUInterface::ptr> InputBuffer::get_ius()
 {
 	std::set<IUInterface::ptr> set;
-	for (RemotePushIUStore::iterator it=_iu_store.begin(); it!=_iu_store.end(); ++it) set.insert(it->second); // TODO genericize
+	for (RemotePushIUStore::iterator it=_iu_store.begin(); it!=_iu_store.end(); ++it) set.insert(it->second);
 	return set;
 }
 
-
 IPAACA_EXPORT RemoteServerPtr InputBuffer::_get_remote_server(const std::string& unique_server_name)
 {
 	std::map<std::string, RemoteServerPtr>::iterator it = _remote_server_store.find(unique_server_name);
@@ -608,11 +602,10 @@ IPAACA_EXPORT ListenerPtr InputBuffer::_create_category_listener_if_needed(const
 	if (it!=_listener_store.end()) {
 		return it->second;
 	}
-	//IPAACA_INFO("Creating a new listener for category " << category)
 	std::string scope_string = "/ipaaca/channel/" + _channel + "/category/" + category;
+	IPAACA_INFO("Creating new listener for " << scope_string)
 
 	ListenerPtr listener = getFactory().createListener( Scope(scope_string) );
-	IPAACA_INFO("Adding listener on " << scope_string)
 	HandlerPtr event_handler = HandlerPtr(
 			new EventFunctionHandler(
 				boost::bind(&InputBuffer::_handle_iu_events, this, _1)
@@ -640,7 +633,8 @@ IPAACA_EXPORT void InputBuffer::_trigger_resend_request(EventPtr event) {
 		uid = update->uid();
 		writerName = update->writer_name();
 	} else {
-		std::cout << "_trigger_resend_request: unhandled event type " << type << std::endl;
+		IPAACA_ERROR("_trigger_resend_request: called for unhandled event type " << type)
+		return;
 	}
 
 	if (!writerName.empty()) {
@@ -652,8 +646,6 @@ IPAACA_EXPORT void InputBuffer::_trigger_resend_request(EventPtr event) {
 			boost::shared_ptr<int> result = server->call<int>("resendRequest", update, IPAACA_REMOTE_SERVER_TIMEOUT);
 			if (*result == 0) {
 				throw IUResendRequestFailedError();
-			} else {
-				//std::cout << "revision " << *result << std::endl;
 			}
 		}
 	}
@@ -670,33 +662,24 @@ IPAACA_EXPORT void InputBuffer::_handle_iu_events(EventPtr event)
 			iu->_set_buffer(this);
 			call_iu_event_handlers(iu, false, IU_ADDED, iu->category() );
 		}
-		//IPAACA_INFO( "New RemotePushIU state: " << (*iu) )
 	} else if (type == "ipaaca::RemoteMessage") {
 		boost::shared_ptr<RemoteMessage> iu = boost::static_pointer_cast<RemoteMessage>(event->getData());
-		//_iu_store[iu->uid()] = iu;
-		//iu->_set_buffer(this);
-		//std::cout << "REFCNT after cast, before calling handlers: " << iu.use_count() << std::endl;
 		call_iu_event_handlers(iu, false, IU_MESSAGE, iu->category() );
-		//_iu_store.erase(iu->uid());
 	} else {
 		RemotePushIUStore::iterator it;
 		if (type == "ipaaca::IUPayloadUpdate") {
 			boost::shared_ptr<IUPayloadUpdate> update = boost::static_pointer_cast<IUPayloadUpdate>(event->getData());
-			//IPAACA_INFO("** writer name: " << update->writer_name)
-			std::cout << "writer name " << update->writer_name << std::endl;
 			if (update->writer_name == _unique_name) {
 				return;
 			}
 			it = _iu_store.find(update->uid);
 			if (it == _iu_store.end()) {
 				_trigger_resend_request(event);
-				IPAACA_INFO("Using UPDATED message for an IU that we did not fully receive before")
+				IPAACA_INFO("UPDATED message for an IU that we did not fully receive before")
 				return;
 			}
-
 			it->second->_apply_update(update);
 			call_iu_event_handlers(it->second, false, IU_UPDATED, it->second->category() );
-
 		} else if (type == "ipaaca::IULinkUpdate") {
 			boost::shared_ptr<IULinkUpdate> update = boost::static_pointer_cast<IULinkUpdate>(event->getData());
 			if (update->writer_name == _unique_name) {
@@ -705,13 +688,11 @@ IPAACA_EXPORT void InputBuffer::_handle_iu_events(EventPtr event)
 			it = _iu_store.find(update->uid);
 			if (it == _iu_store.end()) {
 				_trigger_resend_request(event);
-				IPAACA_INFO("Ignoring LINKSUPDATED message for an IU that we did not fully receive before")
+				IPAACA_INFO("LINKSUPDATED message for an IU that we did not fully receive before")
 				return;
 			}
-
 			it->second->_apply_link_update(update);
 			call_iu_event_handlers(it->second, false, IU_LINKSUPDATED, it->second->category() );
-
 		} else if (type == "ipaaca::protobuf::IUCommission") {
 			boost::shared_ptr<protobuf::IUCommission> update = boost::static_pointer_cast<protobuf::IUCommission>(event->getData());
 			if (update->writer_name() == _unique_name) {
@@ -720,36 +701,31 @@ IPAACA_EXPORT void InputBuffer::_handle_iu_events(EventPtr event)
 			it = _iu_store.find(update->uid());
 			if (it == _iu_store.end()) {
 				_trigger_resend_request(event);
-				IPAACA_INFO("Ignoring COMMITTED message for an IU that we did not fully receive before")
+				IPAACA_INFO("COMMITTED message for an IU that we did not fully receive before")
 				return;
 			}
-			//
 			it->second->_apply_commission();
 			it->second->_revision = update->revision();
 			call_iu_event_handlers(it->second, false, IU_COMMITTED, it->second->category() );
-			//
-			//
 		} else if (type == "ipaaca::protobuf::IURetraction") {
 			boost::shared_ptr<protobuf::IURetraction> update = boost::static_pointer_cast<protobuf::IURetraction>(event->getData());
 			it = _iu_store.find(update->uid());
 			if (it == _iu_store.end()) {
-				_trigger_resend_request(event);
 				IPAACA_INFO("Ignoring RETRACTED message for an IU that we did not fully receive before")
 				return;
 			}
-			//
 			it->second->_revision = update->revision();
 			it->second->_apply_retraction();
-			// remove from InputBuffer     FIXME: this is a crossover between retracted and deleted behavior
-			_iu_store.erase(it->first);
-			// and call the handler. IU reference is still valid for this call, although removed from buffer.
-			call_iu_event_handlers(it->second, false, IU_COMMITTED, it->second->category() );
+			auto final_iu_ref = it->second;
+			////// remove from InputBuffer?  FIXME: unclear issue - resolve in ipaaca3
+			////_iu_store.erase(it->first);
+			// and call the handler. IU reference is still valid for this call, even if removed from buffer.
+			call_iu_event_handlers(final_iu_ref, false, IU_RETRACTED, it->second->category() );
 			//
 		} else {
-			std::cout << "(Unhandled Event type " << type << " !)" << std::endl;
+			IPAACA_WARNING("(Unhandled Event type " << type << " !)");
 			return;
 		}
-		//IPAACA_INFO( "New RemotePushIU state: " << *(it->second) )
 	}
 }
 //}}}
diff --git a/ipaacalib/cpp/src/ipaaca-cmdline-parser.cc b/ipaacalib/cpp/src/ipaaca-cmdline-parser.cc
index e08b33ea34b07381ac4b58e5fadced473706f362..4f37698868fc9d945bf09134b71f3ea8f2e4961e 100644
--- a/ipaacalib/cpp/src/ipaaca-cmdline-parser.cc
+++ b/ipaacalib/cpp/src/ipaaca-cmdline-parser.cc
@@ -3,8 +3,9 @@
  *  "Incremental Processing Architecture
  *   for Artificial Conversational Agents".  
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -70,9 +71,7 @@ void CommandLineOptions::dump() {
 	}
 }
 
-//
 // Command line parser implementation
-//
 
 CommandLineParser::CommandLineParser()
 : library_options_handled(true)
@@ -91,6 +90,8 @@ void CommandLineParser::initialize_parser_defaults()
 		add_option("ipaaca-default-channel", 0, true, "default");
 		add_option("ipaaca-enable-logging", 0, true, "WARNING");
 		add_option("rsb-enable-logging", 0, true, "ERROR");
+		add_option("rsb-spread-host", 0, true, ""); // empty = don't set
+		add_option("rsb-spread-port", 0, true, ""); // empty = don't set
 	}
 }
 
@@ -109,6 +110,14 @@ bool CommandLineParser::consume_library_option(const std::string& name, bool exp
 		std::string newch = optarg;
 		IPAACA_DEBUG("Setting default channel " << newch)
 		__ipaaca_static_option_default_channel = newch;
+	} else if (name=="rsb-spread-host") {
+		std::string newhost = optarg;
+		IPAACA_DEBUG("Setting RSB Spread host " << newhost)
+		__ipaaca_static_option_rsb_spread_host = newhost;
+	} else if (name=="rsb-spread-port") {
+		std::string newport = optarg;
+		IPAACA_DEBUG("Setting RSB Spread port " << newport)
+		__ipaaca_static_option_rsb_spread_port = newport;
 	} else if (name=="ipaaca-enable-logging") {
 		std::string level(optarg);
 		if ((level=="NONE") || (level=="SILENT")) {
@@ -173,7 +182,7 @@ void CommandLineParser::add_option(const std::string& optname, char shortoptn, b
 CommandLineOptions::ptr CommandLineParser::parse(int argc, char* const* argv)
 {
 #ifdef WIN32
-	LOG_IPAACA_CONSOLE("IMPLEMENT ME: command line parsing for Windows. (req'd: getopt)")
+	IPAACA_ERROR("IMPLEMENT ME: command line parsing for Windows. (req'd: getopt)")
 	throw NotImplementedError();
 #else
 	IPAACA_DEBUG("")
diff --git a/ipaacalib/cpp/src/ipaaca-fake.cc b/ipaacalib/cpp/src/ipaaca-fake.cc
index c0d27977a0a6574ae9219a3f733a9f1800d7e9a9..a5277ec3e57913b6febf9b70e5b80dc0296e7e5f 100644
--- a/ipaacalib/cpp/src/ipaaca-fake.cc
+++ b/ipaacalib/cpp/src/ipaaca-fake.cc
@@ -31,6 +31,7 @@
  * Excellence Initiative.
  */
 
+#ifdef IPAACA_BUILD_MOCK_OBJECTS
 #include <ipaaca/ipaaca.h>
 
 namespace ipaaca {
@@ -62,4 +63,5 @@ IPAACA_EXPORT inline void FakeIU::_apply_retraction() { }
 
 } // of namespace ipaaca
 
+#endif
 
diff --git a/ipaacalib/cpp/src/ipaaca-internal.cc b/ipaacalib/cpp/src/ipaaca-internal.cc
index 1ce8f5f467648919b4728b2ce2e694447c5ba54c..364ca34596d3cbddfa87ae197f1ce82b7e4cb22e 100644
--- a/ipaacalib/cpp/src/ipaaca-internal.cc
+++ b/ipaacalib/cpp/src/ipaaca-internal.cc
@@ -51,14 +51,9 @@ IPAACA_EXPORT void Initializer::initialize_backend()//{{{
 {
 	if (_initialized) return;
 
-	//IPAACA_INFO("Calling auto_configure_rsb()")
 	auto_configure_rsb();
 
-	// RYT FIXME This configuration stuff has been simply removed in rsb!
-	//ParticipantConfig config = ParticipantConfig::fromConfiguration();
-	//getFactory().setDefaultParticipantConfig(config);
-
-	//IPAACA_INFO("Creating and registering Converters")
+	IPAACA_DEBUG("Creating and registering Converters")
 	boost::shared_ptr<IUConverter> iu_converter(new IUConverter());
 	converterRepository<std::string>()->registerConverter(iu_converter);
 
@@ -84,9 +79,8 @@ IPAACA_EXPORT void Initializer::initialize_backend()//{{{
 	boost::shared_ptr<IntConverter> int_converter(new IntConverter());
 	converterRepository<std::string>()->registerConverter(int_converter);
 
-	//IPAACA_INFO("Initialization complete.")
+	IPAACA_DEBUG("Backend / converter initialization complete.")
 	_initialized = true;
-	//IPAACA_TODO("initialize all converters")
 }//}}}
 IPAACA_EXPORT void Initializer::dump_current_default_config()//{{{
 {
@@ -103,17 +97,23 @@ IPAACA_EXPORT void Initializer::dump_current_default_config()//{{{
 }//}}}
 IPAACA_EXPORT void Initializer::auto_configure_rsb()//{{{
 {
-	// quick hack to iterate through the pwd parents
-	// and find the closest rsb plugin dir
-	//
-	// but only if not yet defined
+	// set RSB host and port iff provided using cmdline arguments
+	if (__ipaaca_static_option_rsb_spread_host!="") {
+		IPAACA_INFO("Overriding RSB Spread host with " << __ipaaca_static_option_rsb_spread_host)
+		setenv("RSB_TRANSPORT_SPREAD_HOST", __ipaaca_static_option_rsb_spread_host.c_str(), 1);
+	}
+	if (__ipaaca_static_option_rsb_spread_port!="") {
+		IPAACA_INFO("Overriding RSB Spread port with " << __ipaaca_static_option_rsb_spread_port)
+		setenv("RSB_TRANSPORT_SPREAD_PORT", __ipaaca_static_option_rsb_spread_port.c_str(), 1);
+	}
+	
 	const char* plugin_path = getenv("RSB_PLUGINS_CPP_PATH");
 	if (!plugin_path) {
 #ifdef WIN32
-		LOG_IPAACA_CONSOLE("WARNING: RSB_PLUGINS_CPP_PATH not set - in Windows it has to be specified.")
+		IPAACA_WARN("WARNING: RSB_PLUGINS_CPP_PATH not set - in Windows it has to be specified.")
 		//throw NotImplementedError();
 #else
-		LOG_IPAACA_CONSOLE("RSB_PLUGINS_CPP_PATH not set; looking here and up to 7 dirs up.")
+		IPAACA_INFO("RSB_PLUGINS_CPP_PATH not set; looking here and up to 7 dirs up.")
 		std::string pathstr = "./";
 		for (int i=0; i<   8 /* depth EIGHT (totally arbitrary..) */  ; i++) {
 			std::string where_str = pathstr+"deps/lib/rsb*/plugins";
@@ -122,7 +122,7 @@ IPAACA_EXPORT void Initializer::auto_configure_rsb()//{{{
 			glob(where, 0, NULL, &g);
 			if (g.gl_pathc>0) {
 				const char* found_path = g.gl_pathv[0];
-				LOG_IPAACA_CONSOLE("Found an RSB plugin dir which will be used automatically: " << found_path)
+				IPAACA_INFO("Found an RSB plugin dir which will be used automatically: " << found_path)
 				setenv("RSB_PLUGINS_CPP_PATH", found_path, 1);
 				break;
 			} // else keep going
@@ -131,7 +131,7 @@ IPAACA_EXPORT void Initializer::auto_configure_rsb()//{{{
 		}
 #endif
 	} else {
-		LOG_IPAACA_CONSOLE("RSB_PLUGINS_CPP_PATH already defined: " << plugin_path)
+		IPAACA_INFO("RSB_PLUGINS_CPP_PATH already defined: " << plugin_path)
 	}
 }//}}}
 
@@ -145,10 +145,7 @@ IPAACA_EXPORT IUConverter::IUConverter()
 
 IPAACA_EXPORT std::string IUConverter::serialize(const AnnotatedData& data, std::string& wire)
 {
-	//std::cout << "serialize" << std::endl;
-	// Ensure that DATA actually holds a datum of the data-type we expect.
 	assert(data.first == getDataType()); // "ipaaca::IU"
-	// NOTE: a dynamic_pointer_cast cannot be used from void*
 	boost::shared_ptr<const IU> obj = boost::static_pointer_cast<const IU> (data.second);
 	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
 	// transfer obj data to pbo
@@ -175,8 +172,6 @@ IPAACA_EXPORT std::string IUConverter::serialize(const AnnotatedData& data, std:
 	for (auto& kv: obj->_payload._document_store) {
 		protobuf::PayloadItem* item = pbo->add_payload();
 		item->set_key(kv.first);
-		//item->set_value( kv.second->to_json_string_representation() );
-		//item->set_type("JSON");
 		IPAACA_DEBUG("Payload type: " << obj->_payload_type)
 		if (obj->_payload_type=="JSON") {
 			item->set_value( kv.second->to_json_string_representation() );
@@ -197,20 +192,16 @@ IPAACA_EXPORT std::string IUConverter::serialize(const AnnotatedData& data, std:
 	pbo->SerializeToString(&wire);
 	switch(obj->access_mode()) {
 		case IU_ACCESS_PUSH:
-			//std::cout << "Requesting to send as ipaaca-iu" << std::endl;
 			return "ipaaca-iu";
 		case IU_ACCESS_MESSAGE:
-			//std::cout << "Requesting to send as ipaaca-messageiu" << std::endl;
 			return "ipaaca-messageiu";
 		default:
-			//std::cout << "Requesting to send as default" << std::endl;
 			return getWireSchema();
 	}
 
 }
 
 IPAACA_EXPORT AnnotatedData IUConverter::deserialize(const std::string& wireSchema, const std::string& wire) {
-	//std::cout << "deserialize" << std::endl;
 	assert(wireSchema == getWireSchema()); // "ipaaca-iu"
 	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
 	pbo->ParseFromString(wire);
@@ -249,7 +240,6 @@ IPAACA_EXPORT AnnotatedData IUConverter::deserialize(const std::string& wireSche
 					ls.insert(pls.targets(j));
 				}
 			}
-			//return std::make_pair(getDataType(), obj);
 			return std::make_pair("ipaaca::RemotePushIU", obj);
 			break;
 			}
@@ -287,12 +277,11 @@ IPAACA_EXPORT AnnotatedData IUConverter::deserialize(const std::string& wireSche
 					ls.insert(pls.targets(j));
 				}
 			}
-			//return std::make_pair(getDataType(), obj);
 			return std::make_pair("ipaaca::RemoteMessage", obj);
 			break;
 			}
 		default:
-			// other cases not handled yet! ( TODO )
+			// no other cases (yet)
 			throw NotImplementedError();
 	}
 }
@@ -307,9 +296,7 @@ IPAACA_EXPORT MessageConverter::MessageConverter()
 
 IPAACA_EXPORT std::string MessageConverter::serialize(const AnnotatedData& data, std::string& wire)
 {
-	// Ensure that DATA actually holds a datum of the data-type we expect.
 	assert(data.first == getDataType()); // "ipaaca::Message"
-	// NOTE: a dynamic_pointer_cast cannot be used from void*
 	boost::shared_ptr<const Message> obj = boost::static_pointer_cast<const Message> (data.second);
 	boost::shared_ptr<protobuf::IU> pbo(new protobuf::IU());
 	// transfer obj data to pbo
@@ -336,8 +323,6 @@ IPAACA_EXPORT std::string MessageConverter::serialize(const AnnotatedData& data,
 	for (auto& kv: obj->_payload._document_store) {
 		protobuf::PayloadItem* item = pbo->add_payload();
 		item->set_key(kv.first);
-		//item->set_value( kv.second->to_json_string_representation() );
-		//item->set_type("JSON");
 		if (obj->_payload_type=="JSON") {
 			item->set_value( kv.second->to_json_string_representation() );
 			item->set_type("JSON");
@@ -361,7 +346,6 @@ IPAACA_EXPORT std::string MessageConverter::serialize(const AnnotatedData& data,
 		case IU_ACCESS_MESSAGE:
 			return "ipaaca-messageiu";
 		default:
-			//std::cout << "Requesting to send as default" << std::endl;
 			return getWireSchema();
 	}
 
@@ -406,7 +390,6 @@ IPAACA_EXPORT AnnotatedData MessageConverter::deserialize(const std::string& wir
 					ls.insert(pls.targets(j));
 				}
 			}
-			//return std::make_pair(getDataType(), obj);
 			return std::make_pair("ipaaca::RemotePushIU", obj);
 			break;
 			}
@@ -443,12 +426,11 @@ IPAACA_EXPORT AnnotatedData MessageConverter::deserialize(const std::string& wir
 					ls.insert(pls.targets(j));
 				}
 			}
-			//return std::make_pair(getDataType(), obj);
 			return std::make_pair("ipaaca::RemoteMessage", obj);
 			break;
 			}
 		default:
-			// other cases not handled yet! ( TODO )
+			// no other cases (yet)
 			throw NotImplementedError();
 	}
 }
@@ -536,7 +518,7 @@ IPAACA_EXPORT IULinkUpdateConverter::IULinkUpdateConverter()
 
 IPAACA_EXPORT std::string IULinkUpdateConverter::serialize(const AnnotatedData& data, std::string& wire)
 {
-	assert(data.first == getDataType()); // "ipaaca::IULinkUpdate"
+	assert(data.first == getDataType());
 	boost::shared_ptr<const IULinkUpdate> obj = boost::static_pointer_cast<const IULinkUpdate> (data.second);
 	boost::shared_ptr<protobuf::IULinkUpdate> pbo(new protobuf::IULinkUpdate());
 	// transfer obj data to pbo
@@ -598,8 +580,7 @@ IPAACA_EXPORT IntConverter::IntConverter()
 
 IPAACA_EXPORT std::string IntConverter::serialize(const AnnotatedData& data, std::string& wire)
 {
-	// Ensure that DATA actually holds a datum of the data-type we expect.
-	assert(data.first == getDataType()); // "int"
+	assert(data.first == getDataType());
 	// NOTE: a dynamic_pointer_cast cannot be used from void*
 	boost::shared_ptr<const int> obj = boost::static_pointer_cast<const int> (data.second);
 	boost::shared_ptr<protobuf::IntMessage> pbo(new protobuf::IntMessage());
diff --git a/ipaacalib/cpp/src/ipaaca-iuinterface.cc b/ipaacalib/cpp/src/ipaaca-iuinterface.cc
index 2c36848cbc6c29df0fc794e31e2927f6689d289e..1ea5975c4c8b3370642ac81a157a89d5e34576d5 100644
--- a/ipaacalib/cpp/src/ipaaca-iuinterface.cc
+++ b/ipaacalib/cpp/src/ipaaca-iuinterface.cc
@@ -70,7 +70,7 @@ IPAACA_EXPORT void IUInterface::_set_uid(const std::string& uid) {
 	_uid = uid;
 }
 
-IPAACA_EXPORT void IUInterface::_set_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) {
+IPAACA_EXPORT void IUInterface::_set_buffer(Buffer* buffer) {
 	if (_buffer) {
 		throw IUAlreadyInABufferError();
 	}
@@ -86,7 +86,7 @@ IPAACA_EXPORT void IUInterface::_set_owner_name(const std::string& owner_name) {
 }
 
 /// set the buffer pointer and the owner names of IU and Payload
-IPAACA_EXPORT void IUInterface::_associate_with_buffer(Buffer* buffer) { //boost::shared_ptr<Buffer> buffer) {
+IPAACA_EXPORT void IUInterface::_associate_with_buffer(Buffer* buffer) {
 	_set_buffer(buffer); // will throw if already set
 	_set_owner_name(buffer->unique_name());
 	payload()._set_owner_name(buffer->unique_name());
diff --git a/ipaacalib/cpp/src/ipaaca-ius.cc b/ipaacalib/cpp/src/ipaaca-ius.cc
index 07caeb65b2ed42aa132b265f75113c3e8bb6a87a..2626302121779f490b2d10d3af03f7e7c0da8e91 100644
--- a/ipaacalib/cpp/src/ipaaca-ius.cc
+++ b/ipaacalib/cpp/src/ipaaca-ius.cc
@@ -62,6 +62,7 @@ IPAACA_EXPORT IU::IU(const std::string& category, IUAccessMode access_mode, bool
 	_read_only = read_only;
 	_access_mode = access_mode;
 	_committed = false;
+	_retracted = false;
 }
 
 IPAACA_EXPORT void IU::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
@@ -70,6 +71,9 @@ IPAACA_EXPORT void IU::_modify_links(bool is_delta, const LinkMap& new_links, co
 	if (_committed) {
 		_revision_lock.unlock();
 		throw IUCommittedError();
+	} else if (_retracted) {
+		_revision_lock.unlock();
+		throw IURetractedError();
 	}
 	_increase_revision_number();
 	if (is_published()) {
@@ -78,27 +82,6 @@ IPAACA_EXPORT void IU::_modify_links(bool is_delta, const LinkMap& new_links, co
 	_revision_lock.unlock();
 }
 
-
-/*
- * IPAACA_EXPORT void IU::_publish_resend(IU::ptr iu, const std::string& hidden_scope_name)
-{
-	//_revision_lock.lock();
-	//if (_committed) {
-	//	_revision_lock.unlock();
-	//	throw IUCommittedError();
-	//}
-	//_increase_revision_number();
-	//if (is_published()) {
-	//IUInterface* iu, bool is_delta, revision_t revision, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name
-	_buffer->_publish_iu_resend(iu, hidden_scope_name);
-	//}
-	//_revision_lock.unlock();
-}
-*/
-
-
-
-
 IPAACA_EXPORT void IU::_modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name)
 {
 	IPAACA_INFO("")
@@ -106,6 +89,9 @@ IPAACA_EXPORT void IU::_modify_payload(bool is_delta, const std::map<std::string
 	if (_committed) {
 		_revision_lock.unlock();
 		throw IUCommittedError();
+	} else if (_retracted) {
+		_revision_lock.unlock();
+		throw IURetractedError();
 	}
 	_increase_revision_number();
 	if (is_published()) {
@@ -134,6 +120,9 @@ IPAACA_EXPORT void IU::_internal_commit(const std::string& writer_name)
 	if (_committed) {
 		_revision_lock.unlock();
 		throw IUCommittedError();
+	} else if (_retracted) {
+		_revision_lock.unlock();
+		throw IURetractedError();
 	}
 	_increase_revision_number();
 	_committed = true;
@@ -186,20 +175,20 @@ void Message::_internal_commit(const std::string& writer_name)
 
 IPAACA_EXPORT RemotePushIU::ptr RemotePushIU::create()
 {
-	RemotePushIU::ptr iu = RemotePushIU::ptr(new RemotePushIU(/* params */));
+	RemotePushIU::ptr iu = RemotePushIU::ptr(new RemotePushIU());
 	iu->_payload.initialize(iu);
 	return iu;
 }
 IPAACA_EXPORT RemotePushIU::RemotePushIU()
 {
-	// nothing
 }
 IPAACA_EXPORT void RemotePushIU::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
 {
 	if (_committed) {
 		throw IUCommittedError();
-	}
-	if (_read_only) {
+	} else if (_retracted) {
+		throw IURetractedError();
+	} else if (_read_only) {
 		throw IUReadOnlyError();
 	}
 	RemoteServerPtr server = boost::static_pointer_cast<InputBuffer>(_buffer)->_get_remote_server(_owner_name);
@@ -219,11 +208,12 @@ IPAACA_EXPORT void RemotePushIU::_modify_links(bool is_delta, const LinkMap& new
 }
 IPAACA_EXPORT void RemotePushIU::_modify_payload(bool is_delta, const std::map<std::string, PayloadDocumentEntry::ptr>& new_items, const std::vector<std::string>& keys_to_remove, const std::string& writer_name)
 {
-	//std::cout << "-- Sending a modify_payload with " << new_items.size() << " keys to merge." << std::endl;
+	IPAACA_DEBUG("Sending a modify_payload with " << new_items.size() << " keys to merge.")
 	if (_committed) {
 		throw IUCommittedError();
-	}
-	if (_read_only) {
+	} else if (_retracted) {
+		throw IURetractedError();
+	} else if (_read_only) {
 		throw IUReadOnlyError();
 	}
 	RemoteServerPtr server = boost::static_pointer_cast<InputBuffer>(_buffer)->_get_remote_server(_owner_name);
@@ -247,6 +237,8 @@ IPAACA_EXPORT void RemotePushIU::commit()
 {
 	if (_read_only) {
 		throw IUReadOnlyError();
+	} else if (_retracted) {
+		throw IURetractedError();
 	}
 	if (_committed) {
 		// Following python version: ignoring multiple commit
@@ -305,13 +297,12 @@ IPAACA_EXPORT void RemotePushIU::_apply_retraction()
 
 IPAACA_EXPORT RemoteMessage::ptr RemoteMessage::create()
 {
-	RemoteMessage::ptr iu = RemoteMessage::ptr(new RemoteMessage(/* params */));
+	RemoteMessage::ptr iu = RemoteMessage::ptr(new RemoteMessage());
 	iu->_payload.initialize(iu);
 	return iu;
 }
 IPAACA_EXPORT RemoteMessage::RemoteMessage()
 {
-	// nothing
 }
 IPAACA_EXPORT void RemoteMessage::_modify_links(bool is_delta, const LinkMap& new_links, const LinkMap& links_to_remove, const std::string& writer_name)
 {
diff --git a/ipaacalib/cpp/src/ipaaca-json.cc b/ipaacalib/cpp/src/ipaaca-json.cc
index dfdd83ee63adc0603c0f9340cd017d33bd14f9e7..2c2d1cd937e3ac0b7187dde5fb649ca276b20689 100644
--- a/ipaacalib/cpp/src/ipaaca-json.cc
+++ b/ipaacalib/cpp/src/ipaaca-json.cc
@@ -31,11 +31,34 @@
  * Excellence Initiative.
  */
 
+/**
+ * \file   ipaaca-json.cc
+ *
+ * \brief Testbed for ipaaca / JSON functionality
+ *
+ * This file is not used in the ipaaca library, but produces
+ * a separate program, if enabled in CMakeLists.txt
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
 #include <ipaaca/ipaaca.h>
-#include <ipaaca/ipaaca-json.h>
 
+#include "rapidjson/document.h"
+#include "rapidjson/prettywriter.h"
+#include "rapidjson/filestream.h"
+
+#include <cstdio>
 #include <iomanip>
 
+// Notes:
+//  - From http://stackoverflow.com/questions/10426924/json-root-element
+//    Actually there are two different JSON specifications. RFC 4627 requires a JSON text to be
+//    an object or an array. ECMA-262, 5th edition, section 15.12 does not impose this restriction.
+
+
+
 using namespace rapidjson;
 using namespace std;
 
@@ -107,6 +130,7 @@ int batch_update_main(int argc, char** argv)//{{{
 }
 //}}}
 
+#ifdef IPAACA_BUILD_MOCK_OBJECTS
 int iterators_main(int argc, char** argv)//{{{
 {
 	std::string json_source("[\n\
@@ -408,6 +432,7 @@ int fakeiu_main(int argc, char** argv)//{{{
 	return 0;
 }
 //}}}
+#endif
 
 int legacy_iu_main(int argc, char** argv)//{{{
 {
diff --git a/ipaacalib/cpp/src/ipaaca-links.cc b/ipaacalib/cpp/src/ipaaca-links.cc
index e0a6229068126ee2004768a040a4327efe8a32b4..33ff812efffa46ec3f7a42cf1bc316d4bef6763b 100644
--- a/ipaacalib/cpp/src/ipaaca-links.cc
+++ b/ipaacalib/cpp/src/ipaaca-links.cc
@@ -87,7 +87,6 @@ IPAACA_EXPORT void SmartLinkMap::_add_and_remove_links(const LinkMap& add, const
 }
 IPAACA_EXPORT void SmartLinkMap::_replace_links(const LinkMap& links)
 {
-	//_links.clear();
 	_links=links;
 }
 IPAACA_EXPORT const LinkSet& SmartLinkMap::get_links(const std::string& key)
diff --git a/ipaacalib/cpp/src/ipaaca-payload.cc b/ipaacalib/cpp/src/ipaaca-payload.cc
index 4047162a7630dc363318f2b4d62fc008e860fdc3..31a02c14b9df21ce6389e78d66532e39727095bf 100644
--- a/ipaacalib/cpp/src/ipaaca-payload.cc
+++ b/ipaacalib/cpp/src/ipaaca-payload.cc
@@ -53,10 +53,8 @@ std::string value_diagnosis(rapidjson::Value* val)
 	if (val->IsArray()) return "array";
 	if (val->IsObject()) return "object";
 	return "other";
-
 }
 
-
 IPAACA_EXPORT std::ostream& operator<<(std::ostream& os, const rapidjson::Value& val)//{{{
 {
 	os << json_value_cast<std::string>(val);
@@ -95,10 +93,10 @@ double strict_numerical_interpretation(const std::string& str)
 	char* endptr;
 	auto s = str_trim(str);
 	const char* startptr = s.c_str();
-	long l = strtod(startptr, &endptr);
+	double d = strtod(startptr, &endptr);
 	if ((*endptr)=='\0') {
 		// everything could be parsed
-		return l;
+		return d;
 	} else {
 		throw PayloadTypeConversionError();
 	}
@@ -126,12 +124,6 @@ IPAACA_EXPORT template<> long json_value_cast(const rapidjson::Value& v)
 	if (v.IsNull()) return 0l;
 	// default: return parse of string version (should always be 0 though?)
 	throw PayloadTypeConversionError();
-	/*
-	rapidjson::StringBuffer buffer;
-	rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
-	v.Accept(writer);
-	return atol(std::string(buffer.GetString()).c_str());
-	*/
 }
 IPAACA_EXPORT template<> int json_value_cast(const rapidjson::Value& v)
 {
@@ -162,7 +154,6 @@ IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v)
 	if (v.IsString()) {
 		std::string s = v.GetString();
 		return !((s=="")||(s=="false")||(s=="False")||(s=="0"));
-		//return ((s=="1")||(s=="true")||(s=="True"));
 	}
 	if (v.IsBool()) return v.GetBool();
 	if (v.IsNull()) return false;
@@ -174,12 +165,6 @@ IPAACA_EXPORT template<> bool json_value_cast(const rapidjson::Value& v)
 	// default: assume "pointer-like" semantics (i.e. objects are TRUE)
 	return true;
 }
-/*
- * std::map<std::string, std::string> result;
-	std::for_each(_document_store.begin(), _document_store.end(), [&result](std::pair<std::string, PayloadDocumentEntry::ptr> pair) {
-			result[pair.first] =  pair.second->document.GetString();
-			});
-			*/
 //}}}
 
 IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, int newvalue)
@@ -206,25 +191,6 @@ IPAACA_EXPORT void pack_into_json_value(rapidjson::Value& valueobject, rapidjson
 {
 	valueobject.SetString(newvalue, allocator);
 }
-/*
-IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::vector<std::string>& newvalue)
-{
-	valueobject.SetArray();
-	for (auto& str: newvalue) {
-		rapidjson::Value sv;
-		sv.SetString(str, allocator);
-		valueobject.PushBack(sv, allocator);
-	}
-}
-IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::list<std::string>& newvalue)
-{
-	IPAACA_IMPLEMENT_ME
-}
-IPAACA_EXPORT template<> void pack_into_json_value(rapidjson::Value& valueobject, rapidjson::Document::AllocatorType& allocator, const std::map<std::string, std::string>& newvalue)
-{
-	IPAACA_IMPLEMENT_ME
-}
-*/
 
 // PayloadDocumentEntry//{{{
 IPAACA_EXPORT std::string PayloadDocumentEntry::to_json_string_representation()
@@ -240,37 +206,25 @@ IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::from_json_string_r
 	if (entry->document.Parse(json_str.c_str()).HasParseError()) {
 		throw JsonParsingError();
 	}
-	//entry->json_source = json_str;
 	return entry;
 }
 IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::from_unquoted_string_value(const std::string& str)
 {
 	PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>();
 	entry->document.SetString(str.c_str(), entry->document.GetAllocator());
-	//entry->update_json_source();
 	return entry;
 }
 
-/// update json_source after a write operation (on newly cloned entries)
-/*
-IPAACA_EXPORT void PayloadDocumentEntry::update_json_source()
-{
-	json_source = to_json_string_representation();
-}
-*/
-
 IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::create_null()
 {
 	PayloadDocumentEntry::ptr entry = std::make_shared<ipaaca::PayloadDocumentEntry>();
-	//entry->json_source = "null"; // rapidjson::Document value is also null implicitly
 	return entry;
 }
 IPAACA_EXPORT PayloadDocumentEntry::ptr PayloadDocumentEntry::clone()
 {
-	//auto entry = PayloadDocumentEntry::from_json_string_representation(this->json_source);
 	auto entry = PayloadDocumentEntry::create_null();
 	entry->document.CopyFrom(this->document, entry->document.GetAllocator());
-	IPAACA_DEBUG("Cloned for copy-on-write, contents: " << entry)
+	IPAACA_DEBUG("PayloadDocumentEntry cloned for copy-on-write, contents: " << entry)
 	return entry;
 }
 IPAACA_EXPORT rapidjson::Value& PayloadDocumentEntry::get_or_create_nested_value_from_proxy_path(PayloadEntryProxy* pep)
@@ -282,6 +236,7 @@ IPAACA_EXPORT rapidjson::Value& PayloadDocumentEntry::get_or_create_nested_value
 	if (pep->addressed_as_array) {
 		IPAACA_DEBUG("Addressed as array with index " << pep->addressed_index)
 		if (! parent_value.IsArray()) {
+			IPAACA_INFO("parent value is not of type Array")
 			throw PayloadAddressingError();
 		} else {
 			long idx = pep->addressed_index;
@@ -292,42 +247,13 @@ IPAACA_EXPORT rapidjson::Value& PayloadDocumentEntry::get_or_create_nested_value
 				throw PayloadAddressingError();
 			}
 		}
-		// for append / push_back? :
-		/*if (parent_value.IsNull()) {
-			wasnull = true;
-			parent_value.SetArray();
-		}
-		if (wasnull || parent_value.IsArray()) {
-			long idx = pep->addressed_index;
-			long s = parent_value.Size();
-			if (idx<s) {
-				// existing element modified
-				parent_value[idx] = *json_value;
-			} else {
-				// implicitly initialize missing elements to null values
-				if (idx>s) {
-					long missing_elements = pep->addressed_index - p;
-					for (int i=0; i<missing_elements; ++i) {
-						parent_value.PushBack(, allocator)
-					}
-				}
-			}
-			if (s == 
-		} else {
-			throw PayloadAddressingError();
-		}*/
 	} else {
 		IPAACA_DEBUG("Addressed as dict with key " << pep->addressed_key)
-		// addressed as object (dict)
-		//rapidjson::Value& parent_value = *(pep->parent->json_value);
 		if (! parent_value.IsObject()) {
-			IPAACA_DEBUG("parent is not of type Object")
+			IPAACA_INFO("parent value is not of type Object")
 			throw PayloadAddressingError();
 		} else {
 			rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
-			//Value key;
-			//key.SetString(pep->addressed_key, allocator);
-			//parent_value.AddMember(key, *json_value, allocator);
 			rapidjson::Value key;
 			key.SetString(pep->addressed_key, allocator);
 			auto it = parent_value.FindMember(key);
@@ -343,72 +269,10 @@ IPAACA_EXPORT rapidjson::Value& PayloadDocumentEntry::get_or_create_nested_value
 		}
 	}
 }
-
 //}}}
 
 // PayloadEntryProxy//{{{
 
- // only if not top-level
-#if 0
-IPAACA_EXPORT void PayloadEntryProxy::connect_to_existing_parents()
-{
-	rapidjson::Document::AllocatorType& allocator = document_entry->document.GetAllocator();
-	PayloadEntryProxy* pep = this;
-	while (!(pep->existent) && pep->parent) { // only if not top-level
-		if (pep->addressed_as_array) {
-			rapidjson::Value& parent_value = *(pep->parent->json_value);
-			if (! parent_value.IsArray()) {
-				throw PayloadAddressingError();
-			} else {
-				long idx = pep->addressed_index;
-				long s = parent_value.Size();
-				if (idx<s) {
-					parent_value[idx] = *json_value;
-				} else {
-					throw PayloadAddressingError();
-				}
-			}
-			/*if (parent_value.IsNull()) {
-				wasnull = true;
-				parent_value.SetArray();
-			}
-			if (wasnull || parent_value.IsArray()) {
-				long idx = pep->addressed_index;
-				long s = parent_value.Size();
-				if (idx<s) {
-					// existing element modified
-					parent_value[idx] = *json_value;
-				} else {
-					// implicitly initialize missing elements to null values
-					if (idx>s) {
-						long missing_elements = pep->addressed_index - p;
-						for (int i=0; i<missing_elements; ++i) {
-							parent_value.PushBack(, allocator)
-						}
-					}
-				}
-				if (s == 
-			} else {
-				throw PayloadAddressingError();
-			}*/
-		} else {
-			// addressed as object (dict)
-			rapidjson::Value& parent_value = *(pep->parent->json_value);
-			if (! parent_value.IsObject()) {
-				throw PayloadAddressingError();
-			} else {
-				Value key;
-				key.SetString(pep->addressed_key, allocator);
-				parent_value.AddMember(key, *json_value, allocator);
-			}
-		}
-		// repeat for next parent in the tree
-		pep = pep->parent;
-	}
-}
-#endif
-
-
 IPAACA_EXPORT PayloadEntryProxy::PayloadEntryProxy(Payload* payload, const std::string& key)
 : _payload(payload), _key(key), parent(nullptr)
 {
@@ -447,11 +311,11 @@ IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](const char* addr_k
 IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](const std::string& addr_key_)
 {
 	if (!json_value) {
-		IPAACA_DEBUG("Invalid json_value!")
+		IPAACA_INFO("Invalid json_value")
 		throw PayloadAddressingError();
 	}
 	if (! json_value->IsObject()) {
-		IPAACA_DEBUG("Expected Object for operator[](string)!")
+		IPAACA_INFO("Expected Object for operator[](string)")
 		throw PayloadAddressingError();
 	}
 	return PayloadEntryProxy(this, addr_key_);
@@ -459,16 +323,16 @@ IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](const std::string&
 IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](size_t addr_idx_)
 {
 	if (!json_value) {
-		IPAACA_DEBUG("Invalid json_value!")
+		IPAACA_INFO("Invalid json_value")
 		throw PayloadAddressingError();
 	}
 	if (! json_value->IsArray()) {
-		IPAACA_DEBUG("Expected Array for operator[](size_t)!")
+		IPAACA_INFO("Expected Array for operator[](size_t)")
 		throw PayloadAddressingError();
 	}
 	long s = json_value->Size();
 	if (addr_idx_>=s) {
-		IPAACA_DEBUG("Array out of bounds!")
+		IPAACA_INFO("Array out of bounds")
 		throw PayloadAddressingError();
 	}
 	return PayloadEntryProxy(this, addr_idx_);
@@ -476,7 +340,7 @@ IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](size_t addr_idx_)
 IPAACA_EXPORT PayloadEntryProxy PayloadEntryProxy::operator[](int addr_idx_)
 {
 	if (addr_idx_ < 0) {
-		IPAACA_DEBUG("Negative index!")
+		IPAACA_INFO("Negative array index")
 		throw PayloadAddressingError();
 	}
 	return operator[]((size_t) addr_idx_);
@@ -490,81 +354,41 @@ IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const PayloadEntry
 	if (valueptr) { // only set if value is valid, keep default null value otherwise
 		newval.CopyFrom(*valueptr, new_entry->document.GetAllocator());
 	}
-	//new_entry->update_json_source();
 	_payload->set(_key, new_entry);
 	return *this;
 }
 
-/*
-IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const std::string& value)
-{
-	//std::cout << "operator=(string)" << std::endl;
-	IPAACA_IMPLEMENT_ME
-	//_payload->set(_key, value);
-	return *this;
-}
-IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(const char* value)
-{
-	//std::cout << "operator=(const char*)" << std::endl;
-	IPAACA_IMPLEMENT_ME
-	//_payload->set(_key, value);
-	return *this;
-}
-IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(double value)
-{
-	//std::cout << "operator=(double)" << std::endl;
-	IPAACA_IMPLEMENT_ME
-	//_payload->set(_key, boost::lexical_cast<std::string>(value));
-	return *this;
-}
-IPAACA_EXPORT PayloadEntryProxy& PayloadEntryProxy::operator=(bool value)
-{
-	//std::cout << "operator=(bool)" << std::endl;
-	IPAACA_IMPLEMENT_ME
-	//_payload->set(_key, boost::lexical_cast<std::string>(value));
-	return *this;
-}
-*/
-
 IPAACA_EXPORT PayloadEntryProxy::operator std::string()
 {
 	return json_value_cast<std::string>(json_value);
-	//PayloadEntryProxy::get<std::string>();
 }
 IPAACA_EXPORT PayloadEntryProxy::operator long()
 {
 	return json_value_cast<long>(json_value);
-	//return PayloadEntryProxy::get<long>();
 }
 IPAACA_EXPORT PayloadEntryProxy::operator double()
 {
 	return json_value_cast<double>(json_value);
-	//return PayloadEntryProxy::get<double>();
 }
 IPAACA_EXPORT PayloadEntryProxy::operator bool()
 {
 	return json_value_cast<bool>(json_value);
-	//return PayloadEntryProxy::get<bool>();
 }
 IPAACA_EXPORT std::string PayloadEntryProxy::to_str()
 {
 	return json_value_cast<std::string>(json_value);
-	//return PayloadEntryProxy::get<std::string>(); 
 }
 IPAACA_EXPORT long PayloadEntryProxy::to_long()
 {
 	return json_value_cast<long>(json_value);
-	//return PayloadEntryProxy::get<long>();
 }
 IPAACA_EXPORT double PayloadEntryProxy::to_float()
 {
 	return json_value_cast<double>(json_value);
-	//return PayloadEntryProxy::get<double>();
 }
 IPAACA_EXPORT bool PayloadEntryProxy::to_bool()
 {
 	return json_value_cast<bool>(json_value);
-	//return PayloadEntryProxy::get<bool>();
 }
 
 IPAACA_EXPORT PayloadEntryProxyMapDecorator PayloadEntryProxy::as_map()
@@ -594,8 +418,8 @@ IPAACA_EXPORT bool PayloadEntryProxy::is_string()
 {
 	return json_value && json_value->IsString();
 }
-/// is_number => whether it is *interpretable* as
-/// a numerical value (i.e. including conversions)
+
+/// is_number => whether it is *interpretable* as a numerical value (i.e. including conversions)
 IPAACA_EXPORT bool PayloadEntryProxy::is_number()
 {
 	if (!json_value) return false;
@@ -615,58 +439,6 @@ IPAACA_EXPORT bool PayloadEntryProxy::is_map()
 	return json_value && json_value->IsObject();
 }
 
-//
-// new stuff for protocol v2
-//
-
-/*
-IPAACA_EXPORT template<> std::string PayloadEntryProxy::get<std::string>()
-{
-	if (!json_value) return "";
-	//IPAACA_INFO( value_diagnosis(json_value) )
-	if (json_value->IsString()) return json_value->GetString();
-	if (json_value->IsNull()) return "";
-	rapidjson::StringBuffer buffer;
-	rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
-	json_value->Accept(writer);
-	return buffer.GetString();
-	
-	//return _payload->get(_key);
-}
-IPAACA_EXPORT template<> long PayloadEntryProxy::get<long>()
-{
-	return atof(operator std::string().c_str());
-}
-IPAACA_EXPORT template<> double PayloadEntryProxy::get<double>()
-{
-	return atol(operator std::string().c_str());
-}
-IPAACA_EXPORT template<> bool PayloadEntryProxy::get<bool>()
-{
-	std::string s = operator std::string();
-	return ((s=="1")||(s=="true")||(s=="True"));
-}
-// complex types
-IPAACA_EXPORT template<> std::list<std::string> PayloadEntryProxy::get<std::list<std::string> >()
-{
-	std::list<std::string> l;
-	l.push_back(PayloadEntryProxy::get<std::string>());
-	return l;
-}
-IPAACA_EXPORT template<> std::vector<std::string> PayloadEntryProxy::get<std::vector<std::string> >()
-{
-	std::vector<std::string> v;
-	v.push_back(PayloadEntryProxy::get<std::string>());
-	return v;
-}
-IPAACA_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::get<std::map<std::string, std::string> >()
-{
-	std::map<std::string, std::string> m;
-	m["__automatic__"] = PayloadEntryProxy::get<std::string>();
-	return m;
-}
-*/
-
 //}}}
 
 // Payload//{{{
@@ -674,19 +446,19 @@ IPAACA_EXPORT template<> std::map<std::string, std::string> PayloadEntryProxy::g
 IPAACA_EXPORT void Payload::on_lock()
 {
 	Locker locker(_payload_operation_mode_lock);
-	IPAACA_DEBUG("Starting batch update mode ...")
+	IPAACA_DEBUG("Starting payload batch update mode ...")
 	_update_on_every_change = false;
 }
 IPAACA_EXPORT void Payload::on_unlock()
 {
 	Locker locker(_payload_operation_mode_lock);
-	IPAACA_DEBUG("... applying batch update with " << _collected_modifications.size() << " modifications and " << _collected_removals.size() << " removals ...")
+	IPAACA_DEBUG("... applying payload batch update with " << _collected_modifications.size() << " modifications and " << _collected_removals.size() << " removals ...")
 	_internal_merge_and_remove(_collected_modifications, _collected_removals, _batch_update_writer_name);
 	_update_on_every_change = true;
 	_batch_update_writer_name = "";
 	_collected_modifications.clear();
 	_collected_removals.clear();
-	IPAACA_DEBUG("... exiting batch update mode.")
+	IPAACA_DEBUG("... exiting payload batch update mode.")
 }
 
 IPAACA_EXPORT void Payload::initialize(boost::shared_ptr<IUInterface> iu)
@@ -696,8 +468,6 @@ IPAACA_EXPORT void Payload::initialize(boost::shared_ptr<IUInterface> iu)
 
 IPAACA_EXPORT PayloadEntryProxy Payload::operator[](const std::string& key)
 {
-	// TODO atomicize
-	//boost::shared_ptr<PayloadEntryProxy> p(new PayloadEntryProxy(this, key));
 	return PayloadEntryProxy(this, key);
 }
 
@@ -824,10 +594,6 @@ IPAACA_EXPORT void Payload::set(const std::map<std::string, std::string>& all_el
 {
 	std::map<std::string, PayloadDocumentEntry::ptr> newmap;
 	for (auto& kv: all_elems) {
-		/*PayloadDocumentEntry::ptr newit = PayloadDocumentEntry::create_null();
-		newit->document.SetString(kv.second, newit->document.GetAllocator());
-		newit->update_json_source();
-		newmap[kv.first] = newit;*/
 		newmap[kv.first] = PayloadDocumentEntry::from_unquoted_string_value(kv.second);
 	}
 	_internal_replace_all(newmap);
@@ -909,7 +675,6 @@ IPAACA_EXPORT PayloadEntryProxyMapIterator::PayloadEntryProxyMapIterator(Payload
 
 IPAACA_EXPORT PayloadEntryProxyMapIterator& PayloadEntryProxyMapIterator::operator++()
 {
-	// prevent increase beyond end() ?
 	raw_iterator++;
 	return *this;
 }
diff --git a/ipaacalib/cpp/src/ipaaca-string-utils.cc b/ipaacalib/cpp/src/ipaaca-string-utils.cc
index d3192fc858aed0814dbde2494ddb822172e98095..2a3b1b5e4a9999ea1374705fa167dc61e2427515 100644
--- a/ipaacalib/cpp/src/ipaaca-string-utils.cc
+++ b/ipaacalib/cpp/src/ipaaca-string-utils.cc
@@ -3,8 +3,9 @@
  *  "Incremental Processing Architecture
  *   for Artificial Conversational Agents".  
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
diff --git a/ipaacalib/cpp/src/ipaaca.cc b/ipaacalib/cpp/src/ipaaca.cc
index 2e7f99510dcb8afda09c5019da4e40c9bce9583a..b475ff6677a705663439c1dc7131c5c465920e86 100644
--- a/ipaacalib/cpp/src/ipaaca.cc
+++ b/ipaacalib/cpp/src/ipaaca.cc
@@ -76,17 +76,8 @@ IPAACA_EXPORT std::string __ipaaca_static_option_default_payload_type("JSON");
 IPAACA_EXPORT std::string __ipaaca_static_option_default_channel("default");
 IPAACA_EXPORT unsigned int __ipaaca_static_option_log_level(IPAACA_LOG_LEVEL_WARNING);
 
-/*
-void init_inprocess_too() {
-	//ParticipantConfig config = getFactory().getDefaultParticipantConfig();
-	ParticipantConfig config = ParticipantConfig::fromFile("rsb.cfg");
-	//ParticipantConfig::Transport inprocess = config.getTransport("inprocess");
-	//inprocess.setEnabled(true);
-	//config.addTransport(inprocess);
-	getFactory().setDefaultParticipantConfig(config);
-}
-*/
-
+IPAACA_EXPORT std::string __ipaaca_static_option_rsb_spread_host("");
+IPAACA_EXPORT std::string __ipaaca_static_option_rsb_spread_port("");
 
 } // of namespace ipaaca
 
diff --git a/ipaacalib/cpp/src/util/notifier.cc b/ipaacalib/cpp/src/util/notifier.cc
index df063512946b1482193e870c203473059445a921..aaca812a4a086cc5b8805072d6fed0005daa4cdf 100644
--- a/ipaacalib/cpp/src/util/notifier.cc
+++ b/ipaacalib/cpp/src/util/notifier.cc
@@ -3,8 +3,9 @@
  *  "Incremental Processing Architecture
  *   for Artificial Conversational Agents".  
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
- *                         CITEC, Bielefeld University   
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
+ *                         (formerly the Sociable Agents Group)
+ *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -29,7 +30,16 @@
  * Forschungsgemeinschaft (DFG) in the context of the German
  * Excellence Initiative.
  */
- 
+
+/**
+ * \file   util/notifier.cc
+ *
+ * \brief Component notification (i.e. module-level introspection).
+ *
+ * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
+ * \date   March, 2015
+ */
+
 #include <ipaaca/util/notifier.h>
 
 namespace ipaaca {
@@ -71,20 +81,19 @@ ComponentNotifier::ptr ComponentNotifier::create(const std::string& componentNam
 
 void ComponentNotifier::handle_iu_event(IUInterface::ptr iu, IUEventType event_type, bool local)
 {
-	//std::cout << "handle_iu_event: got an event" << std::endl;
 	if ((event_type == IU_ADDED) || (event_type == IU_UPDATED) || (event_type == IU_MESSAGE)) {
 		Locker locker(lock);
+		IPAACA_DEBUG("Received a componentNotify")
 		std::string cName = iu->payload()[_IPAACA_COMP_NOTIF_NAME];
 		std::string cState = iu->payload()[_IPAACA_COMP_NOTIF_STATE];
 		if (cName != name) {
-			//std::cout << " handle_iu_event: calling notification handlers" << std::endl;
 			// call all registered notification handlers
 			for (std::vector<IUEventHandlerFunction>::iterator it = _handlers.begin(); it != _handlers.end(); ++it) {
 				(*it)(iu, event_type, local);
 			}
 			// send own info only if the remote component is a newly initialized one
 			if (cState=="new") {
-				//std::cout << " handle_iu_event: Submitting own notification to new remote end" << std::endl;
+				//IPAACA_DEBUG("Submitting own componentNotify for new remote component")
 				submit_notify(_IPAACA_COMP_NOTIF_STATE_OLD);
 			}
 		}
@@ -106,7 +115,7 @@ void ComponentNotifier::submit_notify(const std::string& current_state)
 	iu->payload()[_IPAACA_COMP_NOTIF_SEND_CATS] = send_categories;
 	iu->payload()[_IPAACA_COMP_NOTIF_RECV_CATS] = recv_categories;
 	out_buf->add(iu);
-	//LOG_IPAACA_CONSOLE( "Sending a ComponentNotify: " << name << " " << function << " " << current_state << " " << send_categories << " " << recv_categories )
+	IPAACA_DEBUG( "Sending a componentNotify: " << name << ": " << current_state << " (" << function << ", " << send_categories << ", " << recv_categories << ")" )
 }
 
 void ComponentNotifier::initialize() {
diff --git a/ipaacalib/cpp/test/CMakeLists.txt b/ipaacalib/cpp/test/CMakeLists.txt
index 6a56b612432f325165ffeeb542e002aa06ae4130..6568c8e4fec4dcdd0d8218d611c3ca784a9638a9 100644
--- a/ipaacalib/cpp/test/CMakeLists.txt
+++ b/ipaacalib/cpp/test/CMakeLists.txt
@@ -12,7 +12,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DIPAACA_DEBUG_MESSAGES")
 # find cmake modules locally too
 set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
 
-find_package(Boost COMPONENTS system filesystem thread regex REQUIRED)
+find_package(Boost COMPONENTS system filesystem thread regex unit_test_framework REQUIRED)
 link_directories(${Boost_LIBRARY_DIRS})
 include_directories(${Boost_INCLUDE_DIRS})
 
@@ -20,6 +20,9 @@ find_package(Protobuf REQUIRED)
 link_directories(${PROTOBUF_LIBRARY_DIRS})
 include_directories(${PROTOBUF_INCLUDE_DIRS})
 
+# for boost unit_test to create main()
+add_definitions(-DBOOST_TEST_DYN_LINK)
+
 #set(RSBLIBS rsc rsbcore)
 
 set(LIBS ${LIBS} ipaaca )
@@ -75,3 +78,7 @@ install (
 	ARCHIVE DESTINATION lib
 	)
 
+
+enable_testing()
+add_test(TestIpaacaCpp testipaaca)
+
diff --git a/ipaacalib/cpp/test/src/testipaaca.cc b/ipaacalib/cpp/test/src/testipaaca.cc
index 828136ba81da19eaf49546b225f229788c5ed986..7769f741060a5e27f77ec74368eb7ae3339e4c72 100644
--- a/ipaacalib/cpp/test/src/testipaaca.cc
+++ b/ipaacalib/cpp/test/src/testipaaca.cc
@@ -33,121 +33,90 @@
 #include <ipaaca/ipaaca.h>
 #include <typeinfo>
 
-using namespace ipaaca;
+#define BOOST_TEST_MODULE TestIpaacaCpp
+#include <boost/test/unit_test.hpp>
 
-const char RECV_CATEGORY[] = "WORD";
-const char SEND_CATEGORY[] = "TEXT";
+using namespace ipaaca;
 
-class TextSender {
-	protected:
-		OutputBuffer::ptr _ob;
-		InputBuffer::ptr  _ib;
+class TestReceiver {
 	public:
-		TextSender();
-		void outbuffer_handle_iu_event(IUInterface::ptr iu, IUEventType event_type, bool local);
+		InputBuffer::ptr  _ib;
+		std::string received_info;
+		TestReceiver();
 		void inbuffer_handle_iu_event(IUInterface::ptr iu, IUEventType event_type, bool local);
-		IUInterface::ptr find_last_iu();
-		void publish_text_to_print(const std::string& text, const std::string& parent_iu_uid="");
 };
 
-TextSender::TextSender() {
-	_ob = OutputBuffer::create("TextSenderOut");
-	_ob->register_handler(boost::bind(&TextSender::outbuffer_handle_iu_event, this, _1, _2, _3));
-	_ib = InputBuffer::create("TextSenderIn", RECV_CATEGORY);
-	_ib->register_handler(boost::bind(&TextSender::inbuffer_handle_iu_event, this, _1, _2, _3));
+TestReceiver::TestReceiver()
+{
+	_ib = ipaaca::InputBuffer::create("TestReceiver", "cppTestCategory");
+	_ib->register_handler(boost::bind(&TestReceiver::inbuffer_handle_iu_event, this, _1, _2, _3));
+	received_info = "NOTHING RECEIVED YET";
 }
 
-void TextSender::outbuffer_handle_iu_event(IUInterface::ptr iu, IUEventType event_type, bool local)
+void TestReceiver::inbuffer_handle_iu_event(IUInterface::ptr iu, IUEventType event_type, bool local)
 {
-	std::cout << "(own IU event " << iu_event_type_to_str(event_type) << " " << iu->uid() << ")" << std::endl;
-	if (event_type == IU_UPDATED) {
-		std::set<std::string> parent_uids = iu->get_links("GRIN");
-		if (parent_uids.size() > 0) {
-			std::string parent_uid = *(parent_uids.begin());
-			std::cout << "updating parent ..." << std::endl;
-			std::set<std::string> next_uids = iu->get_links("SUCCESSOR");
-			if (next_uids.size() > 0) {
-				std::string next_uid = *(next_uids.begin());
-				IUInterface::ptr next_iu = _ob->get(next_uid);
-				std::set<std::string> next_letter_grin_links = next_iu->get_links("GRIN");
-				if (next_letter_grin_links.count(parent_uid) == 0) {
-					// next letter belongs to new word
-					IUInterface::ptr parent_iu = _ib->get(parent_uid);
-					parent_iu->payload()["STATE"] = "REALIZED";
-				} else {
-					IUInterface::ptr parent_iu = _ib->get(parent_uid);
-					parent_iu->payload()["STATE"] = "STARTED";
-				}
-			} else {
-				// there are no more letters, this is the end of the final word
-				IUInterface::ptr parent_iu = _ib->get(parent_uid);
-				parent_iu->payload()["STATE"] = "REALIZED";
-			}
-			std::cout << " ... done." << std::endl;
+	if (event_type == IU_ADDED) {
+		received_info = (std::string) iu->payload()["word"];
+		{
+			ipaaca::Locker locker(iu->payload());
+			iu->payload()["replyVector"] = std::vector<double> { 1.0, 2.0, 3.0 };
+			iu->payload()["replyComment"] = "OK";
 		}
-	} else {
 	}
 }
 
-void TextSender::inbuffer_handle_iu_event(IUInterface::ptr iu, IUEventType event_type, bool local)
-{
-	if (event_type == IU_LINKSUPDATED) {
-		std::cout << "links updated" << std::endl;
-	} else if (event_type == IU_ADDED) {
-		std::string word = iu->payload()["WORD"];
-		std::cout << "Received new word: " << word << std::endl;
-		publish_text_to_print(word, iu->uid());
-	} else if (event_type == IU_RETRACTED) {
-		std::string retracted_uid = iu->uid();
-	} else {
-		std::cout << "(IU event " << iu_event_type_to_str(event_type) << " " << iu->uid() << ")" << std::endl;
-	}
+
+class TestSender {
+	public:
+		OutputBuffer::ptr _ob;
+		std::vector<double> double_vec;
+		std::string comment;
+		long num_replies;
+		TestSender();
+		void publish_one_message();
+		void outbuffer_handle_iu_event(IUInterface::ptr iu, IUEventType event_type, bool local);
+};
+
+TestSender::TestSender() {
+	_ob = OutputBuffer::create("TestSender");
+	_ob->register_handler(boost::bind(&TestSender::outbuffer_handle_iu_event, this, _1, _2, _3));
+	comment = "NO COMMENT YET";
+	num_replies = 0;
 }
 
-IUInterface::ptr TextSender::find_last_iu() {
-	std::set<IUInterface::ptr> ius = _ob->get_ius();
-	for (std::set<IUInterface::ptr>::iterator it = ius.begin(); it!=ius.end(); ++it) {
-		if ((*it)->get_links("SUCCESSOR").size() == 0) return *it;
+void TestSender::outbuffer_handle_iu_event(IUInterface::ptr iu, IUEventType event_type, bool local)
+{
+	if (event_type == IU_UPDATED) {
+		num_replies++;
+		double_vec = iu->payload()["replyVector"];
+		comment = (std::string) iu->payload()["replyComment"];
 	}
-	return IUInterface::ptr();
 }
 
-void TextSender::publish_text_to_print(const std::string& text, const std::string& parent_iu_uid) {
-	IUInterface::ptr previous_iu = find_last_iu();
-	if (previous_iu) {
-		// insert a blank if we already have words in the buffer
-		IU::ptr iu = IU::create( SEND_CATEGORY );
-		iu->payload()["CONTENT"] = " ";
-		_ob->add(iu);
-		previous_iu->add_link( "SUCCESSOR", iu->uid() );
-		iu->add_link( "PREDECESSOR", previous_iu->uid() );
-		if (parent_iu_uid != "") iu->add_link( "GRIN", parent_iu_uid );
-		previous_iu = iu;
-	}
-	for (int i=0; i<text.size(); ++i) {
-		IU::ptr iu = IU::create( SEND_CATEGORY );
-		iu->payload()["CONTENT"] = std::string(1, text.at(i));
-		_ob->add(iu);
-		if (previous_iu) {
-			previous_iu->add_link( "SUCCESSOR", iu->uid() );
-			iu->add_link( "PREDECESSOR", previous_iu->uid() );
-			if (parent_iu_uid != "") iu->add_link( "GRIN", parent_iu_uid );
-		}
-		if (previous_iu) std::cout << "previous IU: " << *previous_iu << std::endl;
-		previous_iu = iu;
-	}
+void TestSender::publish_one_message()
+{
+	ipaaca::IU::ptr iu = ipaaca::IU::create("cppTestCategory");
+	iu->payload()["word"] = "OK";
+	_ob->add(iu);
 }
-	
-int main() {
-	TextSender sender;
+
+BOOST_AUTO_TEST_SUITE (testIpaacaCpp)
+
+
+BOOST_AUTO_TEST_CASE( testIpaacaCpp01 )
+{
+	TestSender sender;
+	TestReceiver receiver;
+	std::cout << "Publishing one message and waiting 1s for replies from other module." << std::endl;
+	sender.publish_one_message();
 	sleep(1);
-	sender.publish_text_to_print("(INIT)");
-	std::cout << "Press Ctrl-C to cancel..." << std::endl;
-	while (true) sleep(1);
+	std::cout << "Checking for changes." << std::endl;
+	BOOST_CHECK( receiver.received_info == "OK" );
+	BOOST_CHECK( sender.num_replies == 1 );
+	BOOST_CHECK( sender.comment == "OK" );
+	BOOST_CHECK( sender.double_vec.size() == 3 );
+	std::cout << "Complete." << std::endl;
 }
 
-int old_main() {
-	std::cerr << "TODO: implement Ipaaca C++ test cases." << std::endl;
-	return 0;
-}
+BOOST_AUTO_TEST_SUITE_END( )
 
diff --git a/ipaacalib/java/.gitignore b/ipaacalib/java/.gitignore
index 8ba77fee38b2e33a59879bea9ace3fe9f7d1f93a..c84f99e34ea3116bd737e7c981c578e46d640a69 100644
--- a/ipaacalib/java/.gitignore
+++ b/ipaacalib/java/.gitignore
@@ -6,3 +6,4 @@ dist
 privateprops
 .project
 .classpath
+/bin/
diff --git a/ipaacalib/java/src/ipaaca/AbstractIU.java b/ipaacalib/java/src/ipaaca/AbstractIU.java
index d79f1622871ec4f960781e6630604e9fe3054510..ba075e527c1054395ed6f965f94f0adac5e5dcc3 100644
--- a/ipaacalib/java/src/ipaaca/AbstractIU.java
+++ b/ipaacalib/java/src/ipaaca/AbstractIU.java
@@ -57,6 +57,7 @@ public abstract class AbstractIU
     protected Payload payload;
     protected String category;
     protected boolean committed = false;
+    protected boolean retracted = false;
     private String uid;
     protected int revision;
     private boolean readOnly = false;
@@ -201,6 +202,11 @@ public abstract class AbstractIU
         return committed;
     }
 
+    public boolean isRetracted()
+    {
+        return retracted;
+    }
+
     public void setBuffer(Buffer buffer)
     {
         this.buffer = buffer;
@@ -218,6 +224,8 @@ public abstract class AbstractIU
 
     public abstract void commit();
 
+    public abstract void retract();
+
     // XXX: might not be valid for all types of IUs
     public abstract void commit(String writerName);
 
diff --git a/ipaacalib/java/src/ipaaca/Buffer.java b/ipaacalib/java/src/ipaaca/Buffer.java
index 02b6b36f7eb190ae64344a53e8a7ce663ca80bad..d8851d4254a917d7d3f464cfd5c12f26fc7df1da 100644
--- a/ipaacalib/java/src/ipaaca/Buffer.java
+++ b/ipaacalib/java/src/ipaaca/Buffer.java
@@ -38,6 +38,8 @@ import java.util.List;
 import java.util.Set;
 import java.util.UUID;
 
+import ipaaca.Initializer;
+
 /**
  * Base class for InputBuffer and OutputBuffer.
  */
@@ -85,6 +87,7 @@ public abstract class Buffer
      */
     public Buffer(String owningComponentName)
     {
+        Initializer.initializeIpaacaRsb();
         this.owningComponentName = owningComponentName;
         uniqueName = "undef-" + uuid;
     }
diff --git a/ipaacalib/cpp/include/ipaaca/ipaaca-json.h b/ipaacalib/java/src/ipaaca/IURetractedException.java
similarity index 53%
rename from ipaacalib/cpp/include/ipaaca/ipaaca-json.h
rename to ipaacalib/java/src/ipaaca/IURetractedException.java
index 30cac6c0594617ea28efd941bee08840b07eac93..b7d4f76c2e4809c731130c7d54103dde2caf5677 100644
--- a/ipaacalib/cpp/include/ipaaca/ipaaca-json.h
+++ b/ipaacalib/java/src/ipaaca/IURetractedException.java
@@ -1,11 +1,10 @@
 /*
  * This file is part of IPAACA, the
  *  "Incremental Processing Architecture
- *   for Artificial Conversational Agents".
+ *   for Artificial Conversational Agents".  
  *
  * Copyright (c) 2009-2015 Social Cognitive Systems Group
- *                         (formerly the Sociable Agents Group)
- *                         CITEC, Bielefeld University
+ *                         CITEC, Bielefeld University   
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
  * http://purl.org/net/ipaaca
@@ -22,7 +21,7 @@
  * You should have received a copy of the LGPL along with this
  * program. If not, go to http://www.gnu.org/licenses/lgpl.html
  * or write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  
  *
  * The development of this software was supported by the
  * Excellence Cluster EXC 277 Cognitive Interaction Technology.
@@ -31,31 +30,25 @@
  * Excellence Initiative.
  */
 
+package ipaaca;
+
 /**
- * \file   ipaaca-json.h
- *
- * \brief Header file for JSON tests. [superfluous]
- *
- * Users should not include this file directly, but use ipaaca.h
- *
- * \author Ramin Yaghoubzadeh (ryaghoubzadeh@uni-bielefeld.de)
- * \date   March, 2015
+ * Error indicating that an IU is immutable because it has been retracted.
+ * 
  */
-
-#ifndef __ipaaca_json_H__
-#define __ipaaca_json_H__
-
-#include "rapidjson/document.h"
-#include "rapidjson/prettywriter.h"
-#include "rapidjson/filestream.h"
-#include <cstdio>
-
-// Notes:
-//  - From http://stackoverflow.com/questions/10426924/json-root-element
-//    Actually there are two different JSON specifications. RFC 4627 requires a JSON text to be
-//    an object or an array. ECMA-262, 5th edition, section 15.12 does not impose this restriction.
-
-
-
-#endif // __IPAACA_JSON_H__
-
+public class IURetractedException extends RuntimeException
+{
+    private static final long serialVersionUID = 1L;
+    private final AbstractIU iu;
+
+    public AbstractIU getIU()
+    {
+        return iu;
+    }
+
+    public IURetractedException(AbstractIU iu)
+    {
+        super("Writing to IU " + iu.getUid() + " failed -- it has been retracted.");
+        this.iu = iu;
+    }
+}
diff --git a/ipaacalib/java/src/ipaaca/Initializer.java b/ipaacalib/java/src/ipaaca/Initializer.java
index 0af784bd8e7051dd1889edb0465ef07add9de566..c2b8c72cb19e9966906008c2fd855691976c5abc 100644
--- a/ipaacalib/java/src/ipaaca/Initializer.java
+++ b/ipaacalib/java/src/ipaaca/Initializer.java
@@ -3,7 +3,7 @@
  *  "Incremental Processing Architecture
  *   for Artificial Conversational Agents".  
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
  *                         CITEC, Bielefeld University   
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
@@ -32,9 +32,12 @@
 
 package ipaaca;
 
+import java.nio.ByteBuffer;
 import ipaaca.protobuf.Ipaaca.IUCommission;
 import ipaaca.protobuf.Ipaaca.IUResendRequest;
+import ipaaca.protobuf.Ipaaca.IURetraction;
 import rsb.converter.ConverterSignature;
+import rsb.converter.ConverterRepository;
 import rsb.converter.DefaultConverterRepository;
 import rsb.converter.ProtocolBufferConverter;
 
@@ -43,34 +46,74 @@ import rsb.converter.ProtocolBufferConverter;
  * @author hvanwelbergen
  * 
  */
-public final class Initializer
-{
-    private Initializer()
-    {
-    }
+public final class Initializer {
+
+    private Initializer() {}
+
     private static volatile boolean initialized = false;
     
-    public synchronized static void initializeIpaacaRsb()
-    {
-        if(initialized)return;
-        DefaultConverterRepository.getDefaultConverterRepository().addConverter(new IntConverter());
-        DefaultConverterRepository.getDefaultConverterRepository().addConverter(
-                new ProtocolBufferConverter<IUCommission>(IUCommission.getDefaultInstance()));
-	// dlw
-	DefaultConverterRepository.getDefaultConverterRepository().addConverter(
-                new ProtocolBufferConverter<IUResendRequest>(IUResendRequest.getDefaultInstance()));
-
-        DefaultConverterRepository.getDefaultConverterRepository().addConverter(
-                new IUConverter(new ConverterSignature("ipaaca-iu", RemotePushIU.class)));
-        DefaultConverterRepository.getDefaultConverterRepository().addConverter(
-         new IUConverter(new ConverterSignature("ipaaca-localiu", LocalIU.class)));
-        DefaultConverterRepository.getDefaultConverterRepository().addConverter(
-                new IUConverter(new ConverterSignature("ipaaca-messageiu", RemoteMessageIU.class)));
-        DefaultConverterRepository.getDefaultConverterRepository().addConverter(
-                new IUConverter(new ConverterSignature("ipaaca-localmessageiu", LocalMessageIU.class)));
+    public synchronized static void initializeIpaacaRsb() {
+        if (initialized)
+            return;
+
+        ConverterRepository<ByteBuffer> dcr =
+            DefaultConverterRepository.getDefaultConverterRepository();
+
+        // for IU revision numbers
+        dcr.addConverter(
+            new IntConverter());
+
+        // IU commit messages
+        dcr.addConverter(
+            new ProtocolBufferConverter<IUCommission>(
+                IUCommission.getDefaultInstance()));
+
+        // IU commit messages
+        dcr.addConverter(
+            new ProtocolBufferConverter<IURetraction>(
+                IURetraction.getDefaultInstance()));
+
+        // IU resend request messages
+        dcr.addConverter(
+            new ProtocolBufferConverter<IUResendRequest>(
+                IUResendRequest.getDefaultInstance()));
+
+        // IUs
+        dcr.addConverter(
+            new IUConverter(
+                new ConverterSignature(
+                    "ipaaca-iu",
+                    RemotePushIU.class)));
+
+        // Local IUs
+        dcr.addConverter(
+            new IUConverter(
+                new ConverterSignature(
+                    "ipaaca-localiu",
+                    LocalIU.class)));
+
+        // Messages
+        dcr.addConverter(
+            new IUConverter(
+                new ConverterSignature(
+                    "ipaaca-messageiu",
+                    RemoteMessageIU.class)));
+
+        // LocalMessages
+        dcr.addConverter(
+            new IUConverter(
+                new ConverterSignature(
+                    "ipaaca-localmessageiu",
+                    LocalMessageIU.class)));
          
-        DefaultConverterRepository.getDefaultConverterRepository().addConverter(new PayloadConverter());
-        DefaultConverterRepository.getDefaultConverterRepository().addConverter(new LinkUpdateConverter());
+        // Payloads
+        dcr.addConverter(
+            new PayloadConverter());
+
+        // LinkUpdates
+        dcr.addConverter(
+            new LinkUpdateConverter());
+
         initialized = true;
     }
 }
diff --git a/ipaacalib/java/src/ipaaca/InputBuffer.java b/ipaacalib/java/src/ipaaca/InputBuffer.java
index ccaabc922935c84a6808678a10c0dad5c0608e05..2a2b17c976de13990e6e53cfe4b0668829090782 100644
--- a/ipaacalib/java/src/ipaaca/InputBuffer.java
+++ b/ipaacalib/java/src/ipaaca/InputBuffer.java
@@ -33,6 +33,7 @@
 package ipaaca;
 
 import ipaaca.protobuf.Ipaaca.IUCommission;
+import ipaaca.protobuf.Ipaaca.IURetraction;
 import ipaaca.protobuf.Ipaaca.IUResendRequest;
 import ipaaca.protobuf.Ipaaca.IULinkUpdate;
 import ipaaca.protobuf.Ipaaca.IUPayloadUpdate;
@@ -441,6 +442,22 @@ public class InputBuffer extends Buffer
                 iu.setRevision(iuc.getRevision());
                 callIuEventHandlers(iuc.getUid(), false, IUEventType.COMMITTED, iu.getCategory());
             }
+            if (event.getData() instanceof IURetraction)
+            {
+                IURetraction iuc = (IURetraction) event.getData();
+                logger.debug("handleIUEvents invoked with an IURetraction: {}", iuc);
+                logger.debug("{}", this.getUniqueName());
+
+                if (!iuStore.containsKey(iuc.getUid()))
+                {
+                    logger.warn("Update message for IU which we did not fully receive before.");
+                }
+                RemotePushIU iu = this.iuStore.get(iuc.getUid());
+                if (iu != null) {
+                    iu.applyRetraction();
+                    callIuEventHandlers(iuc.getUid(), false, IUEventType.RETRACTED, iu.getCategory());
+                }
+            }
         }
     }
 
diff --git a/ipaacalib/java/src/ipaaca/LocalIU.java b/ipaacalib/java/src/ipaaca/LocalIU.java
index 6e87a82484f882a25dddda7e314dfd76ebdb3060..eb4ee552a4efc512992b16b9a10f5d957a422fd4 100644
--- a/ipaacalib/java/src/ipaaca/LocalIU.java
+++ b/ipaacalib/java/src/ipaaca/LocalIU.java
@@ -105,6 +105,10 @@ public class LocalIU extends AbstractIU
 
         synchronized (revisionLock)
         {
+            if (isRetracted())
+            {
+                throw new IURetractedException(this);
+            }
             if (committed)
             {
                 throw new IUCommittedException(this);
@@ -121,6 +125,22 @@ public class LocalIU extends AbstractIU
         }
     }
 
+    private void internalRetract()
+    {
+
+        synchronized (revisionLock)
+        {
+            if (isRetracted())
+                return;
+            increaseRevisionNumber();
+            retracted = true;
+            if (outputBuffer != null)
+            {
+                outputBuffer.sendIURetraction(this);
+            }
+        }
+    }
+
     private void increaseRevisionNumber()
     {
         revision++;
@@ -148,6 +168,10 @@ public class LocalIU extends AbstractIU
     @Override
     void modifyLinks(boolean isDelta, SetMultimap<String, String> linksToAdd, SetMultimap<String, String> linksToRemove, String writerName)
     {
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         if (isCommitted())
         {
             throw new IUCommittedException(this);
@@ -226,6 +250,10 @@ public class LocalIU extends AbstractIU
             {
                 throw new IUCommittedException(this);
             }
+            if (isRetracted())
+            {
+                throw new IURetractedException(this);
+            }
             increaseRevisionNumber();
             if (isPublished())
             {
@@ -249,6 +277,10 @@ public class LocalIU extends AbstractIU
             {
                 throw new IUCommittedException(this);
             }
+            if (isRetracted())
+            {
+                throw new IURetractedException(this);
+            }
             increaseRevisionNumber();
             if (isPublished())
             {
@@ -270,15 +302,29 @@ public class LocalIU extends AbstractIU
     @Override
     public void commit()
     {
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         internalCommit(null);
     }
 
     @Override
     public void commit(String writerName)
     {
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         internalCommit(writerName);
     }
 
+    @Override
+    public void retract()
+    {
+        internalRetract();
+    }
+
     @Override
     void removeFromPayload(Object key, String writer)
     {
@@ -288,6 +334,10 @@ public class LocalIU extends AbstractIU
             {
                 throw new IUCommittedException(this);
             }
+            if (isRetracted())
+            {
+                throw new IURetractedException(this);
+            }
             increaseRevisionNumber();
             if (isPublished())
             {
diff --git a/ipaacalib/java/src/ipaaca/LocalMessageIU.java b/ipaacalib/java/src/ipaaca/LocalMessageIU.java
index bf9c12862d8b8027b8facbb0586f46894d5c2699..1bd5ea34687ebd45d92078aec87cab2429bf65c8 100644
--- a/ipaacalib/java/src/ipaaca/LocalMessageIU.java
+++ b/ipaacalib/java/src/ipaaca/LocalMessageIU.java
@@ -3,7 +3,7 @@
  *  "Incremental Processing Architecture
  *   for Artificial Conversational Agents".  
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
  *                         CITEC, Bielefeld University   
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
diff --git a/ipaacalib/java/src/ipaaca/OutputBuffer.java b/ipaacalib/java/src/ipaaca/OutputBuffer.java
index 818621b07d24b974f7928e3d30fa59126caa5fd7..77f11a070a46b61c3fece8cb90a13caafbd20a14 100644
--- a/ipaacalib/java/src/ipaaca/OutputBuffer.java
+++ b/ipaacalib/java/src/ipaaca/OutputBuffer.java
@@ -1,9 +1,10 @@
+
 /*
  * This file is part of IPAACA, the
  *  "Incremental Processing Architecture
  *   for Artificial Conversational Agents".
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
  *                         CITEC, Bielefeld University
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
@@ -34,6 +35,7 @@ package ipaaca;
 
 import ipaaca.protobuf.Ipaaca;
 import ipaaca.protobuf.Ipaaca.IUCommission;
+import ipaaca.protobuf.Ipaaca.IURetraction;
 import ipaaca.protobuf.Ipaaca.IUResendRequest;
 import ipaaca.protobuf.Ipaaca.IULinkUpdate;
 import ipaaca.protobuf.Ipaaca.IUPayloadUpdate;
@@ -474,7 +476,21 @@ public class OutputBuffer extends Buffer
     protected void sendIUCommission(AbstractIU iu, String writerName)
     {
         IUCommission iuc = Ipaaca.IUCommission.newBuilder().setUid(iu.getUid()).setRevision(iu.getRevision())
-                .setWriterName(iu.getOwnerName() != null ? iu.getOwnerName() : writerName).build();
+                .setWriterName(writerName == null ? iu.getOwnerName() : writerName).build();
+        Informer<Object> informer = getInformer(iu.getCategory());
+        try
+        {
+            informer.send(iuc);
+        }
+        catch (RSBException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    protected void sendIURetraction(AbstractIU iu)
+    {
+        IURetraction iuc = Ipaaca.IURetraction.newBuilder().setUid(iu.getUid()).setRevision(iu.getRevision()).build();
         Informer<Object> informer = getInformer(iu.getCategory());
         try
         {
diff --git a/ipaacalib/java/src/ipaaca/RemoteMessageIU.java b/ipaacalib/java/src/ipaaca/RemoteMessageIU.java
index db69496e6709d9c453c34e2a94cf275f3bd4bedb..a3898a170138a0618d97ed97f2d51d7a3458af6c 100644
--- a/ipaacalib/java/src/ipaaca/RemoteMessageIU.java
+++ b/ipaacalib/java/src/ipaaca/RemoteMessageIU.java
@@ -3,7 +3,7 @@
  *  "Incremental Processing Architecture
  *   for Artificial Conversational Agents".  
  *
- * Copyright (c) 2009-2013 Sociable Agents Group
+ * Copyright (c) 2009-2015 Social Cognitive Systems Group
  *                         CITEC, Bielefeld University   
  *
  * http://opensource.cit-ec.de/projects/ipaaca/
@@ -58,6 +58,12 @@ public class RemoteMessageIU extends AbstractIU
         committed = true;
     }
 
+    @Override
+    public void retract()
+    {
+        log.info("Retracting a RemoteMessage has no effect.");
+    }    
+
     @Override
     public void commit(String writerName)
     {
diff --git a/ipaacalib/java/src/ipaaca/RemotePushIU.java b/ipaacalib/java/src/ipaaca/RemotePushIU.java
index bfb8060403c42031dfbf70c7b8c55eadaf72b334..f58e83c39b820be89909f9a6b0213171602d6d9f 100644
--- a/ipaacalib/java/src/ipaaca/RemotePushIU.java
+++ b/ipaacalib/java/src/ipaaca/RemotePushIU.java
@@ -84,9 +84,9 @@ public class RemotePushIU extends AbstractIU
     }
 
     @Override
-    public void commit()
+    public void retract()
     {
-        commit(null);
+        logger.info("Retracting a RemoteIU has no effect.");
     }
 
     void putIntoPayload(String key, String value, String writer)
@@ -95,6 +95,10 @@ public class RemotePushIU extends AbstractIU
         {
             throw new IUCommittedException(this);
         }
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         if (isReadOnly())
         {
             throw new IUReadOnlyException(this);
@@ -136,6 +140,10 @@ public class RemotePushIU extends AbstractIU
         {
             throw new IUCommittedException(this);
         }
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         if (isReadOnly())
         {
             throw new IUReadOnlyException(this);
@@ -179,9 +187,19 @@ public class RemotePushIU extends AbstractIU
         setRevision(newRevision);
     }
 
+    @Override
+    public void commit()
+    {
+        commit(null);
+    }
+
     @Override
     public void commit(String writerName)
     {
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         if (isReadOnly())
         {
             throw new IUReadOnlyException(this);
@@ -254,6 +272,10 @@ public class RemotePushIU extends AbstractIU
         {
             throw new IUCommittedException(this);
         }
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         if (isReadOnly())
         {
             throw new IUReadOnlyException(this);
@@ -357,6 +379,11 @@ public class RemotePushIU extends AbstractIU
         committed = true;
     }
 
+    public void applyRetraction()
+    {
+        retracted = true;
+    }
+
     @Override
     void removeFromPayload(Object key, String writer)
     {
@@ -364,6 +391,10 @@ public class RemotePushIU extends AbstractIU
         {
             throw new IUCommittedException(this);
         }
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         if (isReadOnly())
         {
             throw new IUReadOnlyException(this);
@@ -403,6 +434,10 @@ public class RemotePushIU extends AbstractIU
         {
             throw new IUCommittedException(this);
         }
+        if (isRetracted())
+        {
+            throw new IURetractedException(this);
+        }
         if (isReadOnly())
         {
             throw new IUReadOnlyException(this);
diff --git a/ipaacalib/java/src/ipaaca/util/BlackboardClient.java b/ipaacalib/java/src/ipaaca/util/BlackboardClient.java
index 6f70e78f922a289a29e2214b3861a0466755a063..ab72262ee99432ee255e6f66d9c341705d03eb3f 100644
--- a/ipaacalib/java/src/ipaaca/util/BlackboardClient.java
+++ b/ipaacalib/java/src/ipaaca/util/BlackboardClient.java
@@ -1,13 +1,5 @@
 package ipaaca.util;
 
-import ipaaca.AbstractIU;
-import ipaaca.HandlerFunctor;
-import ipaaca.IUEventType;
-import ipaaca.InputBuffer;
-import ipaaca.LocalMessageIU;
-import ipaaca.OutputBuffer;
-import ipaaca.protobuf.Ipaaca.IU;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -18,6 +10,13 @@ import java.util.Set;
 
 import com.google.common.collect.ImmutableSet;
 
+import ipaaca.AbstractIU;
+import ipaaca.HandlerFunctor;
+import ipaaca.IUEventType;
+import ipaaca.InputBuffer;
+import ipaaca.LocalMessageIU;
+import ipaaca.OutputBuffer;
+
 /**
  * Client to get/set key value pairs on a Blackboard
  * @author hvanwelbergen
diff --git a/ipaacalib/java/src/ipaaca/util/IpaacaLogger.java b/ipaacalib/java/src/ipaaca/util/IpaacaLogger.java
new file mode 100644
index 0000000000000000000000000000000000000000..d55a46b2471e2a2fa3bc2bd9ef1ae2689a09d06f
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/util/IpaacaLogger.java
@@ -0,0 +1,186 @@
+/*
+ * This file is part of IPAACA, the
+ *  "Incremental Processing Architecture
+ *   for Artificial Conversational Agents".
+ *
+ * Copyright (c) 2009-2016 Social Cognitive Systems Group
+ *                         CITEC, Bielefeld University
+ *
+ * http://opensource.cit-ec.de/projects/ipaaca/
+ * http://purl.org/net/ipaaca
+ *
+ * This file may be licensed under the terms of of the
+ * GNU Lesser General Public License Version 3 (the ``LGPL''),
+ * or (at your option) any later version.
+ *
+ * Software distributed under the License is distributed
+ * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the LGPL for the specific language
+ * governing rights and limitations.
+ *
+ * You should have received a copy of the LGPL along with this
+ * program. If not, go to http://www.gnu.org/licenses/lgpl.html
+ * or write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The development of this software was supported by the
+ * Excellence Cluster EXC 277 Cognitive Interaction Technology.
+ * The Excellence Cluster EXC 277 is a grant of the Deutsche
+ * Forschungsgemeinschaft (DFG) in the context of the German
+ * Excellence Initiative.
+ */
+
+package ipaaca.util;
+
+import ipaaca.LocalMessageIU;
+import ipaaca.OutputBuffer;
+
+import java.util.HashMap;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+
+public class IpaacaLogger {
+
+	private static OutputBuffer ob;
+	private static final Object lock = new Object();
+
+	private static boolean SEND_IPAACA_LOGS = true;
+	private static String MODULE_NAME = "???";
+
+	private static void initializeOutBuffer() {
+		synchronized (lock) {
+			if (ob == null) {
+				ob = new OutputBuffer("LogSender");
+			}
+		}
+	}
+
+	public static void setModuleName(String name) {
+		synchronized (lock) {
+			MODULE_NAME = name;
+		}
+	}
+
+	public static void setLogFileName(String fileName, String logMode) {
+		initializeOutBuffer();
+		LocalMessageIU msg = new LocalMessageIU("log");
+		HashMap<String, String> pl = new HashMap<String, String>();
+		pl.put("cmd", "open_log_file");
+		pl.put("filename", fileName);
+		if (logMode != null) {
+			if (logMode.equals("append") ||
+					logMode.equals("overwrite") ||
+					logMode.equals("timestamp")) {
+				pl.put("existing", logMode);
+			} else {
+
+				return;
+			}
+		}
+		ob.add(msg);
+	}
+
+	public static void sendIpaacaLogs(boolean flag) {
+		synchronized (lock) {
+			SEND_IPAACA_LOGS = flag;
+		}
+	}
+
+	private static void logConsole(String level, String text, float now, String function, String thread) {
+		for(String line: text.split("\n")) {
+			   System.out.println("[" + level + "] " + thread + " " + function + " " + line);
+			   function = StringUtils.leftPad("", function.length(), ' ');
+			   thread = StringUtils.leftPad("", thread.length(), ' ');
+		}
+	}
+
+	private static void logIpaaca(String level, String text, float now, String function, String thread) {
+		initializeOutBuffer();
+		LocalMessageIU msg = new LocalMessageIU("log");
+		HashMap<String, String> pl = new HashMap<String, String>();
+		pl.put("module", MODULE_NAME);
+		pl.put("function", function);
+		pl.put("level", level);
+		pl.put("time", String.format("%.3f", now));
+		pl.put("thread", thread);
+		pl.put("uuid", UUID.randomUUID().toString());
+		pl.put("text", text);
+		msg.setPayload(pl);
+		ob.add(msg);
+	}
+
+	private static String getCallerName() {
+		String function = Thread.currentThread().getStackTrace()[3].getClassName();
+		function += "." + Thread.currentThread().getStackTrace()[3].getMethodName();
+		return function;
+	}
+
+	public static void logError(String msg) {
+		logError(msg, System.currentTimeMillis(), getCallerName());
+	}
+
+	public static void logError(String msg, float now) {
+		logError(msg, now, getCallerName());
+	}
+
+	private static void logError(String msg, float now, String callerName) {
+		String thread = Thread.currentThread().getName();
+		if (SEND_IPAACA_LOGS) {
+			logIpaaca("ERROR", msg, now, callerName, thread);
+		}
+		logConsole("ERROR", msg, now, callerName, thread);
+	}
+
+
+	public static void logWarn(String msg) {
+		logWarn(msg, System.currentTimeMillis(), getCallerName());
+	}
+
+	public static void logWarn(String msg, float now) {
+		logWarn(msg, now, getCallerName());
+	}
+
+	private static void logWarn(String msg, float now, String callerName) {
+		String thread = Thread.currentThread().getName();
+		if (SEND_IPAACA_LOGS) {
+			logIpaaca("WARN", msg, now, callerName, thread);
+		}
+		logConsole("WARN", msg, now, callerName, thread);
+	}
+
+
+	public static void logInfo(String msg) {
+		logInfo(msg, System.currentTimeMillis(), getCallerName());
+	}
+
+	public static void logInfo(String msg, float now) {
+		logInfo(msg, now, getCallerName());
+	}
+
+	private static void logInfo(String msg, float now, String callerName) {
+		String thread = Thread.currentThread().getName();
+		if (SEND_IPAACA_LOGS) {
+			logIpaaca("INFO", msg, now, callerName, thread);
+		}
+		logConsole("INFO", msg, now, callerName, thread);
+	}
+
+
+	public static void logDebug(String msg) {
+		logDebug(msg, System.currentTimeMillis(), getCallerName());
+	}
+
+	public static void logDebug(String msg, float now) {
+		logDebug(msg, now, getCallerName());
+	}
+
+	private static void logDebug(String msg, float now, String callerName) {
+		String thread = Thread.currentThread().getName();
+		if (SEND_IPAACA_LOGS) {
+			logIpaaca("DEBUG", msg, now, callerName, thread);
+		}
+		logConsole("DEBUG", msg, now, callerName, thread);
+	}
+
+}
diff --git a/ipaacalib/java/src/ipaaca/util/communication/FutureIU.java b/ipaacalib/java/src/ipaaca/util/communication/FutureIU.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cd48549a65e6f968ec9b94907743ea59cb546e7
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/util/communication/FutureIU.java
@@ -0,0 +1,84 @@
+package ipaaca.util.communication;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import com.google.common.collect.ImmutableSet;
+
+import ipaaca.AbstractIU;
+import ipaaca.HandlerFunctor;
+import ipaaca.IUEventType;
+import ipaaca.InputBuffer;
+
+/**
+ * Obtain a IU in the future. Usage:<br>
+ * FutureIU fu = FutureIU("componentx", "status", "started"); //wait for componentx to send a message that is it fully started<br>
+ * [Start componentx, assumes that component x will send a message or other iu with status=started in the payload]<br>
+ * AbstractIU iu = fu.take();  //get the actual IU 
+ * @author hvanwelbergen
+ */
+public class FutureIU
+{
+    private final InputBuffer inBuffer;
+    private final BlockingQueue<AbstractIU> queue = new ArrayBlockingQueue<AbstractIU>(1);
+    
+    public FutureIU(String category, String idKey, String idVal)
+    {
+        inBuffer = new InputBuffer("FutureIU", ImmutableSet.of(category));
+        inBuffer.registerHandler(new HandlerFunctor()
+        {
+            @Override
+            public void handle(AbstractIU iu, IUEventType type, boolean local)
+            {
+                String id = iu.getPayload().get(idKey);
+                if (idVal.equals(id))
+                {
+                    queue.offer(iu);                    
+                }
+            }
+        }, ImmutableSet.of(category));
+    }
+
+    /**
+     * Waits (if necessary) for the IU and take it (can be done only once)     
+     */
+    public AbstractIU take() throws InterruptedException
+    {
+        AbstractIU iu;
+        try
+        {
+            iu = queue.take();
+        }
+        finally
+        {
+            inBuffer.close();
+        }
+        return iu;
+    }
+
+    /**
+     * Wait for at most the given time for the IU and take it (can be done only once), return null on timeout    
+     */
+    public AbstractIU take(long timeout, TimeUnit unit) throws InterruptedException
+    {
+        AbstractIU iu;
+        try
+        {
+            iu = queue.poll(timeout, unit);
+        }
+        finally
+        {
+            inBuffer.close();
+        }
+        return iu;
+    }
+    
+    /**
+     * Closes the FutureIU, use only if get is not used.
+     */
+    public void close()
+    {
+        inBuffer.close();
+    }
+}
diff --git a/ipaacalib/java/src/ipaaca/util/communication/FutureIUs.java b/ipaacalib/java/src/ipaaca/util/communication/FutureIUs.java
new file mode 100644
index 0000000000000000000000000000000000000000..2e9ed3b2d482132b93d3b04027b8ed2fcf8576c4
--- /dev/null
+++ b/ipaacalib/java/src/ipaaca/util/communication/FutureIUs.java
@@ -0,0 +1,70 @@
+package ipaaca.util.communication;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import com.google.common.collect.ImmutableSet;
+
+import ipaaca.AbstractIU;
+import ipaaca.HandlerFunctor;
+import ipaaca.IUEventType;
+import ipaaca.InputBuffer;
+
+/**
+ * Obtain multiple future ius on an specific category. Usage:<br>
+ * FutureIUs futures = new FutureIUs(componentx, key);<br>
+ * [make componentx send a IU with key=keyvaluedesired1]<br>
+ * AbstractIU iu = futures.take(keyvaluedesired1);<br>
+ * [make componentx send a IU with key=keyvaluedesired2]
+ * AbstractIU iu = futures.take(keyvaluedesired2);<br>
+ * ...<br>
+ * futures.close();
+ * @author hvanwelbergen
+ */
+public class FutureIUs
+{
+    private final InputBuffer inBuffer;
+    private final Map<String,BlockingQueue<AbstractIU>> resultsMap = Collections.synchronizedMap(new HashMap<>());
+    
+    public FutureIUs(String category, String idKey)
+    {
+        inBuffer = new InputBuffer("FutureIUs", ImmutableSet.of(category));
+        inBuffer.registerHandler(new HandlerFunctor()
+        {
+            @Override
+            public void handle(AbstractIU iu, IUEventType type, boolean local)
+            {
+                String id = iu.getPayload().get(idKey);
+                resultsMap.putIfAbsent(id, new ArrayBlockingQueue<AbstractIU>(1));
+                resultsMap.get(id).offer(iu);
+            }
+        }, ImmutableSet.of(category));
+    }
+    
+    /**
+     * Waits (if necessary) for the IU and take it (can be done only once)     
+     */
+    public AbstractIU take(String idValue) throws InterruptedException
+    {
+        resultsMap.putIfAbsent(idValue, new ArrayBlockingQueue<AbstractIU>(1));
+        return resultsMap.get(idValue).take();
+    }
+    
+    /**
+     * Wait for at most the given time for the IU and take it (can be done only once), return null on timeout        
+     */
+    public AbstractIU take(String idValue, long timeout, TimeUnit unit) throws InterruptedException
+    {
+        resultsMap.putIfAbsent(idValue, new ArrayBlockingQueue<AbstractIU>(1));
+        return resultsMap.get(idValue).poll(timeout, unit);
+    }
+    
+    public void close()
+    {
+        inBuffer.close();
+    }
+}
diff --git a/ipaacalib/java/test/src/ipaaca/util/communication/FutureIUTest.java b/ipaacalib/java/test/src/ipaaca/util/communication/FutureIUTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..bacf3013ca7cbcd7008895992d3cda71cf2fc921
--- /dev/null
+++ b/ipaacalib/java/test/src/ipaaca/util/communication/FutureIUTest.java
@@ -0,0 +1,61 @@
+package ipaaca.util.communication;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Test;
+
+import ipaaca.LocalMessageIU;
+import ipaaca.OutputBuffer;
+
+/**
+ * Unit tests for the FutureIU
+ * @author hvanwelbergen
+ *
+ */
+public class FutureIUTest
+{
+    private final OutputBuffer outBuffer = new OutputBuffer("component1");
+
+    @Test(timeout = 2000)
+    public void testSendBeforeTake() throws InterruptedException
+    {
+        FutureIU fu = new FutureIU("cat1", "status", "started");
+        LocalMessageIU message = new LocalMessageIU("cat1");
+        message.getPayload().put("status", "started");
+        outBuffer.add(message);
+        assertEquals(message.getPayload(), fu.take().getPayload());
+    }
+
+    @Test(timeout = 2000)
+    public void testSendAfterTake() throws InterruptedException
+    {
+        FutureIU fu = new FutureIU("cat1", "status", "started");
+        LocalMessageIU message = new LocalMessageIU("cat1");
+        message.getPayload().put("status", "started");
+        Runnable send = () -> {
+            try
+            {
+                Thread.sleep(1000);
+            }
+            catch (Exception e)
+            {
+                throw new RuntimeException(e);
+            }
+            outBuffer.add(message);
+        };
+        new Thread(send).start();
+        assertEquals(message.getPayload(), fu.take().getPayload());
+    }
+    
+    @Test
+    public void testInvalidKeyValue() throws InterruptedException
+    {
+        FutureIU fu = new FutureIU("cat1", "status", "started");
+        LocalMessageIU message = new LocalMessageIU("cat1");
+        message.getPayload().put("status", "cancelled");
+        assertNull(fu.take(1,TimeUnit.SECONDS));
+    }
+}
diff --git a/ipaacalib/java/test/src/ipaaca/util/communication/FutureIUsTest.java b/ipaacalib/java/test/src/ipaaca/util/communication/FutureIUsTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..87113d047304933708966471df1ba9da93c18a69
--- /dev/null
+++ b/ipaacalib/java/test/src/ipaaca/util/communication/FutureIUsTest.java
@@ -0,0 +1,81 @@
+package ipaaca.util.communication;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.concurrent.TimeUnit;
+
+import org.junit.After;
+import org.junit.Test;
+
+import ipaaca.LocalMessageIU;
+import ipaaca.OutputBuffer;
+
+/**
+ * Unit tests for FutureIUs
+ * @author hvanwelbergen
+ *
+ */
+public class FutureIUsTest
+{
+    private FutureIUs fus = new FutureIUs("cat1","id");
+    private final OutputBuffer outBuffer = new OutputBuffer("component1");
+    
+    @After
+    public void cleanup()
+    {
+        fus.close();
+    }
+    
+    @Test(timeout = 2000)
+    public void testSendBeforeTake() throws InterruptedException
+    {
+        LocalMessageIU message = new LocalMessageIU("cat1");
+        message.getPayload().put("id", "id1");
+        outBuffer.add(message);
+        assertEquals(message.getPayload(), fus.take("id1").getPayload());
+    }
+    
+    @Test(timeout = 2000)
+    public void testSendAfterTake() throws InterruptedException
+    {
+        LocalMessageIU message = new LocalMessageIU("cat1");
+        message.getPayload().put("id", "id1");        
+        Runnable send = () -> {
+            try
+            {
+                Thread.sleep(1000);
+            }
+            catch (Exception e)
+            {
+                throw new RuntimeException(e);
+            }
+            outBuffer.add(message);
+        };
+        new Thread(send).start();
+        assertEquals(message.getPayload(), fus.take("id1").getPayload());    
+    }
+    
+    @Test
+    public void testNonMatchingKeyValue() throws InterruptedException
+    {
+        LocalMessageIU message = new LocalMessageIU("cat1");
+        message.getPayload().put("id", "id2");
+        outBuffer.add(message);
+        assertNull(fus.take("id1", 1,TimeUnit.SECONDS));
+    }
+    
+    @Test
+    public void testMultipleKeyValues() throws InterruptedException
+    {
+        LocalMessageIU message1 = new LocalMessageIU("cat1");
+        message1.getPayload().put("id", "id1");
+        LocalMessageIU message2 = new LocalMessageIU("cat1");
+        message2.getPayload().put("id", "id2");        
+        outBuffer.add(message2);
+        outBuffer.add(message1);
+        
+        assertEquals(message1.getPayload(), fus.take("id1").getPayload());
+        assertEquals(message2.getPayload(), fus.take("id2").getPayload());
+    }
+}
diff --git a/ipaacalib/python/src/ipaaca/__init__.py b/ipaacalib/python/src/ipaaca/__init__.py
index 09321c0bd26070239ee9a44f354e62d5f40eeaff..9314caf9604777bf727e86235693b3c0670275f1 100755
--- a/ipaacalib/python/src/ipaaca/__init__.py
+++ b/ipaacalib/python/src/ipaaca/__init__.py
@@ -4,7 +4,7 @@
 #  "Incremental Processing Architecture
 #   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2014 Social Cognitive Systems Group
+# Copyright (c) 2009-2016 Social Cognitive Systems Group
 #                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
@@ -32,6 +32,9 @@
 
 from __future__ import division, print_function
 
+import os
+import threading
+
 import rsb
 import rsb.converter
 
@@ -44,46 +47,69 @@ from ipaaca.misc import enable_logging, IpaacaArgumentParser
 from ipaaca.payload import Payload
 
 
-def initialize_ipaaca_rsb():
-	''''Register own RSB Converters and initialise RSB from default config file.'''
-	rsb.converter.registerGlobalConverter(
-		ipaaca.converter.IntConverter(
-			wireSchema="int32",
-			dataType=int))
-
-	rsb.converter.registerGlobalConverter(
-		ipaaca.converter.IUConverter(
-			wireSchema="ipaaca-iu",
-			dataType=IU))
-
-	rsb.converter.registerGlobalConverter(
-		ipaaca.converter.MessageConverter(
-			wireSchema="ipaaca-messageiu",
-			dataType=Message))
+__RSB_INITIALIZER_LOCK = threading.Lock()
+__RSB_INITIALIZED = False
 
-	rsb.converter.registerGlobalConverter(
-		ipaaca.converter.IULinkUpdateConverter(
-			wireSchema="ipaaca-iu-link-update",
-			dataType=converter.IULinkUpdate))
 
-	rsb.converter.registerGlobalConverter(
-		ipaaca.converter.IUPayloadUpdateConverter(
-			wireSchema="ipaaca-iu-payload-update",
-			dataType=converter.IUPayloadUpdate))
+def initialize_ipaaca_rsb_if_needed():
+	"""Initialise rsb if not yet initialise.
 
-	rsb.converter.registerGlobalConverter(
-		rsb.converter.ProtocolBufferConverter(
-			messageClass=ipaaca_pb2.IUCommission))
+	   * Register own RSB onverters.
+	   * Initialise RSB from enviroment variables, rsb config file, or
+	     from default values for RSB spread host and port (via
+	     ipaaca.defaults or ipaaca.misc.IpaacaArgumentParser).
+	"""
+	global __RSB_INITIALIZED
+	with __RSB_INITIALIZER_LOCK:
+		if __RSB_INITIALIZED:
+			return
+		else:
+			rsb.converter.registerGlobalConverter(
+				ipaaca.converter.IntConverter(
+					wireSchema="int32",
+					dataType=int))
+		
+			rsb.converter.registerGlobalConverter(
+				ipaaca.converter.IUConverter(
+					wireSchema="ipaaca-iu",
+					dataType=IU))
+		
+			rsb.converter.registerGlobalConverter(
+				ipaaca.converter.MessageConverter(
+					wireSchema="ipaaca-messageiu",
+					dataType=Message))
+		
+			rsb.converter.registerGlobalConverter(
+				ipaaca.converter.IULinkUpdateConverter(
+					wireSchema="ipaaca-iu-link-update",
+					dataType=converter.IULinkUpdate))
+		
+			rsb.converter.registerGlobalConverter(
+				ipaaca.converter.IUPayloadUpdateConverter(
+					wireSchema="ipaaca-iu-payload-update",
+					dataType=converter.IUPayloadUpdate))
+		
+			rsb.converter.registerGlobalConverter(
+				rsb.converter.ProtocolBufferConverter(
+					messageClass=ipaaca_pb2.IUCommission))
+		
+			rsb.converter.registerGlobalConverter(
+				rsb.converter.ProtocolBufferConverter(
+					messageClass=ipaaca_pb2.IUResendRequest))
+		
+			rsb.converter.registerGlobalConverter(
+				rsb.converter.ProtocolBufferConverter(
+					messageClass=ipaaca_pb2.IURetraction))
 
-	rsb.converter.registerGlobalConverter(
-		rsb.converter.ProtocolBufferConverter(
-			messageClass=ipaaca_pb2.IUResendRequest))
+			if ipaaca.defaults.IPAACA_DEFAULT_RSB_SPREAD_HOST is not None:
+				os.environ['RSB_TRANSPORT_SPREAD_HOST'] = str(
+						ipaaca.defaults.IPAACA_DEFAULT_RSB_SPREAD_HOST)
 
-	rsb.converter.registerGlobalConverter(
-		rsb.converter.ProtocolBufferConverter(
-			messageClass=ipaaca_pb2.IURetraction))
+			if ipaaca.defaults.IPAACA_DEFAULT_RSB_SPREAD_PORT is not None:
+				os.environ['RSB_TRANSPORT_SPREAD_PORT'] = str(
+						ipaaca.defaults.IPAACA_DEFAULT_RSB_SPREAD_PORT)
 
-	rsb.__defaultParticipantConfig = rsb.ParticipantConfig.fromDefaultSources()
+			rsb.__defaultParticipantConfig = \
+					rsb.ParticipantConfig.fromDefaultSources()
 
-# Initialise module
-initialize_ipaaca_rsb()
+			__RSB_INITIALIZED = True
diff --git a/ipaacalib/python/src/ipaaca/buffer.py b/ipaacalib/python/src/ipaaca/buffer.py
index c4b75a4450cbd1301717caf94fa36dfb46e8b2f1..6a408341f7991acf8bc19749def7a92648b39ef2 100644
--- a/ipaacalib/python/src/ipaaca/buffer.py
+++ b/ipaacalib/python/src/ipaaca/buffer.py
@@ -4,7 +4,7 @@
 #  "Incremental Processing Architecture
 #   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2014 Social Cognitive Systems Group
+# Copyright (c) 2009-2015 Social Cognitive Systems Group
 #                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
@@ -37,6 +37,9 @@ import threading
 import uuid
 import traceback
 
+import weakref
+import atexit
+
 import rsb
 
 import ipaaca_pb2
@@ -54,6 +57,27 @@ __all__ = [
 
 LOGGER = ipaaca.misc.get_library_logger()
 
+# set of objects to auto-clean on exit, assumes _teardown() method
+TEARDOWN_OBJECTS = set()
+
+def atexit_cleanup_function():
+	'''Function to call at program exit to auto-clean objects.'''
+	global TEARDOWN_OBJECTS
+	for obj_r in TEARDOWN_OBJECTS:
+		obj = obj_r()
+		if obj is not None: # if weakref still valid
+			obj._teardown()
+atexit.register(atexit_cleanup_function)
+
+def auto_teardown_instances(fn):
+	'''Decorator function for object constructors, to add
+	new instances to the object set to auto-clean at exit.'''
+	def auto_teardown_instances_wrapper(instance, *args, **kwargs):
+		global TEARDOWN_OBJECTS
+		fn(instance, *args, **kwargs)
+		TEARDOWN_OBJECTS.add(weakref.ref(instance))
+	return auto_teardown_instances_wrapper
+
 class IUStore(dict):
 	"""A dictionary storing IUs."""
 	def __init__(self):
@@ -133,6 +157,7 @@ class Buffer(object):
 		participant_config -- RSB configuration
 		'''
 		super(Buffer, self).__init__()
+		ipaaca.initialize_ipaaca_rsb_if_needed()
 		self._owning_component_name = owning_component_name
 		self._channel = channel if channel is not None else ipaaca.defaults.IPAACA_DEFAULT_CHANNEL
 		self._participant_config = rsb.ParticipantConfig.fromDefaultSources() if participant_config is None else participant_config
@@ -207,21 +232,33 @@ class InputBuffer(Buffer):
 		self._add_category_listener(str(self._uuid))
 		if category_interests is not None:
 			self.add_category_interests(category_interests)
-
-	def _get_remote_server(self, iu):
+	
+	def _get_remote_server(self, event_or_iu):
 		'''Return (or create, store and return) a remote server.'''
-		_owner = None
-		if hasattr(iu,'owner_name'):
-			_owner = iu.owner_name
-		elif hasattr(iu,'writer_name'):
-			_owner = iu.writer_name
-		if _owner is not None:
-			if _owner in self._remote_server_store:
+		_owner = self._get_owner(event_or_iu)
+		if _owner:
+			try:
 				return self._remote_server_store[_owner]
-			#  TODO remove the str() when unicode is supported (issue #490)
-			remote_server = rsb.createRemoteServer(rsb.Scope(str(_owner)))
-			self._remote_server_store[_owner] = remote_server
-		return remote_server
+			except KeyError:
+				remote_server = rsb.createRemoteServer(rsb.Scope(str(_owner)))
+				self._remote_server_store[_owner] = remote_server
+				return remote_server
+		else:
+			None
+
+	def _get_owner(self, event_or_iu):
+		if hasattr(event_or_iu, 'data'):
+			# is RSB event
+			data = event_or_iu.data
+			if hasattr(data, 'owner_name'):
+				return data.owner_name
+			elif hasattr(data, 'writer_name'):
+				return data.writer_name
+			else:
+				return None
+		else:
+			# is IU
+			return event_or_iu.owner_name
 
 	def _add_category_listener(self, iu_category):
 		'''Create and store a listener on a specific category.'''
@@ -270,9 +307,14 @@ class InputBuffer(Buffer):
 			del self._iu_store[ event.data.uid ]
 		else:
 			if event.data.uid not in self._iu_store:
-				if self._resend_active:
-					# send resend request to remote server
-					self._request_remote_resend(event.data)
+				if (self._resend_active and 
+							not type_ is ipaaca_pb2.IURetraction):
+					# send resend request to remote server, IURetraction is ignored
+					try:
+						self._request_remote_resend(event)
+					except ipaaca.exception.IUResendRequestFailedError:
+						LOGGER.warning('Requesting resend for IU {} failed.'.
+								format(event.data.uid))
 				else:
 					LOGGER.warning("Received an update for an IU which we did not receive before.")
 				return
@@ -283,10 +325,6 @@ class InputBuffer(Buffer):
 				iu._revision = event.data.revision
 				iu._apply_retraction() # for now - just sets the _rectracted flag.
 				self.call_iu_event_handlers(event.data.uid, local=False, event_type=ipaaca.iu.IUEventType.RETRACTED, category=iu.category)
-				# SPECIAL CASE: allow the handlers (which will need to find the IU
-				#  in the buffer) to operate on the IU - then delete it afterwards!
-				# FIXME: for now: retracted == deleted! Think about this later
-				del(self._iu_store[iu.uid])
 			else:
 				if event.data.writer_name == self.unique_name:
 					# Notify only for remotely triggered events;
@@ -325,13 +363,17 @@ class InputBuffer(Buffer):
 		else:
 			self._remove_category_listener(category_interests)
 
-	def _request_remote_resend(self, iu):
-		remote_server = self._get_remote_server(iu)
-		resend_request = ipaaca_pb2.IUResendRequest()
-		resend_request.uid = iu.uid # target iu
-		resend_request.hidden_scope_name = str(self._uuid) # hidden category name
-		remote_revision = remote_server.requestResend(resend_request)
-		if remote_revision == 0:
+	def _request_remote_resend(self, event):
+		remote_server = self._get_remote_server(event)
+		if remote_server:
+			resend_request = ipaaca_pb2.IUResendRequest()
+			resend_request.uid = event.data.uid # target iu
+			resend_request.hidden_scope_name = str(self._uuid) # hidden category name
+			remote_revision = remote_server.requestResend(resend_request)
+			if remote_revision == 0:
+				raise ipaaca.exception.IUResendRequestFailedError()
+		else:
+			# Remote server is not known
 			raise ipaaca.exception.IUResendRequestFailedError()
 
 	def register_handler(self, handler_function, for_event_types=None, for_categories=None):
@@ -364,8 +406,9 @@ class OutputBuffer(Buffer):
 
 	"""An OutputBuffer that holds local IUs."""
 
+	@auto_teardown_instances
 	def __init__(self, owning_component_name, channel=None, participant_config=None):
-		'''Create an Output Buffer.
+		'''Create an OutputBuffer.
 
 		Keyword arguments:
 		owning_component_name -- name of the entity that own this buffer
@@ -382,6 +425,16 @@ class OutputBuffer(Buffer):
 		self._id_prefix = str(owning_component_name)+'-'+str(self._uuid)+'-IU-'
 		self.__iu_id_counter_lock = threading.Lock()
 
+	def _teardown(self):
+		'''OutputBuffer retracts remaining live IUs on teardown'''
+		self._retract_all_internal()
+	def __del__(self):
+		'''Perform teardown (IU retractions) as soon as Buffer is lost.
+		Note that at program exit the teardown might be called
+		twice for live objects (atexit, then del), but the
+		_retract_all_internal method prevents double retractions.'''
+		self._retract_all_internal()
+
 	def _remote_update_links(self, update):
 		'''Apply a remotely requested update to one of the stored IU's links.'''
 		if update.uid not in self._iu_store:
@@ -479,6 +532,8 @@ class OutputBuffer(Buffer):
 			raise ipaaca.exception.IUPublishedError(iu)
 		if iu.buffer is not None:
 			raise ipaaca.exception.IUPublishedError(iu)
+		if iu.retracted:
+			raise ipaaca.exception.IURetractedError(iu)
 		if iu.access_mode != ipaaca.iu.IUAccessMode.MESSAGE:
 			# Messages are not really stored in the OutputBuffer
 			self._iu_store[iu.uid] = iu
@@ -486,12 +541,12 @@ class OutputBuffer(Buffer):
 		self._publish_iu(iu)
 
 	def remove(self, iu=None, iu_uid=None):
-		'''Remove the iu or an IU corresponding to iu_uid from the OutputBuffer, retracting it from the system.'''
+		'''Retracts an IU and removes it from the OutputBuffer.'''
 		if iu is None:
 			if iu_uid is None:
 				return None
 			else:
-				if iu_uid not in self. _iu_store:
+				if iu_uid not in self._iu_store:
 					raise ipaaca.exception.IUNotFoundError(iu_uid)
 				iu = self._iu_store[iu_uid]
 		# unpublish the IU
@@ -505,12 +560,19 @@ class OutputBuffer(Buffer):
 		informer.publishData(iu)
 
 	def _retract_iu(self, iu):
-		'''Retract (unpublish) an IU.'''
+		'''Retract an IU.'''
+		iu._retracted = True
 		iu_retraction = ipaaca_pb2.IURetraction()
 		iu_retraction.uid = iu.uid
 		iu_retraction.revision = iu.revision
 		informer = self._get_informer(iu._category)
 		informer.publishData(iu_retraction)
+	
+	def _retract_all_internal(self):
+		'''Retract all IUs without removal (for Buffer teardown).'''
+		for iu in self._iu_store.values():
+			if not iu._retracted:
+				self._retract_iu(iu)
 
 	def _send_iu_commission(self, iu, writer_name):
 		'''Send IU commission.
diff --git a/ipaacalib/python/src/ipaaca/defaults.py b/ipaacalib/python/src/ipaaca/defaults.py
index 706c714b1d270838f04a84f3cd20dffe432d747c..bf3d0f00d282a90f0c908ecf92f17f7447020b45 100644
--- a/ipaacalib/python/src/ipaaca/defaults.py
+++ b/ipaacalib/python/src/ipaaca/defaults.py
@@ -4,7 +4,7 @@
 #  "Incremental Processing Architecture
 #   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2014 Social Cognitive Systems Group
+# Copyright (c) 2009-2016 Social Cognitive Systems Group
 #                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
@@ -33,6 +33,11 @@
 IPAACA_DEFAULT_CHANNEL = 'default'
 
 IPAACA_LOGGER_NAME = 'ipaaca'
+
 IPAACA_DEFAULT_LOGGING_LEVEL = 'WARNING'
 
 IPAACA_DEFAULT_IU_PAYLOAD_TYPE = 'JSON' # one of ipaaca.iu.IUPayloadType
+
+IPAACA_DEFAULT_RSB_SPREAD_HOST = None
+
+IPAACA_DEFAULT_RSB_SPREAD_PORT = None
diff --git a/ipaacalib/python/src/ipaaca/exception.py b/ipaacalib/python/src/ipaaca/exception.py
index f90a6756ef4f2935004e2b60fd76e14c612f60f4..f3a927d73cc31b44ee2b4880e1778f59616e7e55 100644
--- a/ipaacalib/python/src/ipaaca/exception.py
+++ b/ipaacalib/python/src/ipaaca/exception.py
@@ -4,7 +4,7 @@
 #  "Incremental Processing Architecture
 #   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2014 Social Cognitive Systems Group
+# Copyright (c) 2009-2015 Social Cognitive Systems Group
 #                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
@@ -82,13 +82,21 @@ class IUPublishedError(IpaacaError):
 class IUReadOnlyError(IpaacaError):
 	"""Error indicating that an IU is immutable because it is 'read only'."""
 	def __init__(self, iu):
-		super(IUReadOnlyError, self).__init__('Writing to IU ' + str(iu.uid) + ' failed -- it is read-only.')
+		super(IUReadOnlyError, self).__init__(
+			'Writing to IU ' + str(iu.uid) + ' failed -- it is read-only.')
 
 
 class IUResendRequestFailedError(IpaacaError):
 	"""Error indicating that a remote IU resend failed."""
 	def __init__(self, iu):
-		super(IUResendFailedError, self).__init__('Remote resend failed for IU ' + str(iu.uid) + '.')
+		super(IUResendRequestFailedError, self).__init__(
+			'Remote resend failed for IU ' + str(iu.uid) + '.')
+
+
+class IURetractedError(IpaacaError):
+	"""Error indicating that an IU has been retracted."""
+	def __init__(self, iu):
+		super(IURetractedError, self).__init__('Writing to IU ' + str(iu.uid) + ' failed -- it has been retracted.')
 
 
 class IUUpdateFailedError(IpaacaError):
diff --git a/ipaacalib/python/src/ipaaca/iu.py b/ipaacalib/python/src/ipaaca/iu.py
index fd55bd78a3dc7b15ae248432cbce202331d8323e..66f139fce36b2b97bb21a76c9fa18bd5763e98d3 100644
--- a/ipaacalib/python/src/ipaaca/iu.py
+++ b/ipaacalib/python/src/ipaaca/iu.py
@@ -4,7 +4,7 @@
 #  "Incremental Processing Architecture
 #   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2014 Social Cognitive Systems Group
+# Copyright (c) 2009-2015 Social Cognitive Systems Group
 #                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
@@ -114,7 +114,7 @@ class IUInterface(object):
 			s += k+":'"+unicode(v)+"', "
 		s += "} "
 		s += "links={ "
-		for t,ids in self.get_all_links().items():
+		for t, ids in self.get_all_links().items():
 			s += t+":'"+unicode(ids)+"', "
 		s += "} "
 		s += "}"
@@ -173,9 +173,9 @@ class IUInterface(object):
 		if self._buffer is None:
 			self._payload_type = type
 		else:
-			raise IpaacaException('The IU is already in a buffer, cannot change payload type anymore.')
+			raise ipaaca.exception.IpaacaError('The IU is already in a buffer, cannot change payload type anymore.')
 	payload_type = property(
-		fget=_get_payload_type, 
+		fget=_get_payload_type,
 		fset=_set_payload_type,
 		 doc='Type of the IU payload')
 
@@ -209,7 +209,7 @@ class IUInterface(object):
 		return self._buffer
 	def _set_buffer(self, buffer):
 		if self._buffer is not None:
-			raise IpaacaException('The IU is already in a buffer, cannot move it.')
+			raise ipaaca.exception.IpaacaError('The IU is already in a buffer, cannot move it.')
 		self._buffer = buffer
 	buffer = property(
 			fget=_get_buffer,
@@ -220,7 +220,7 @@ class IUInterface(object):
 		return self._owner_name
 	def _set_owner_name(self, owner_name):
 		if self._owner_name is not None:
-			raise Exception('The IU already has an owner name, cannot change it.')
+			raise ipaaca.exception.IpaacaError('The IU already has an owner name, cannot change it.')
 		self._owner_name = owner_name
 	owner_name = property(
 			fget=_get_owner_name,
@@ -241,7 +241,9 @@ class IU(IUInterface):
 		self._payload = ipaaca.payload.Payload(iu=self)
 
 	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
-		if self.committed:
+		if self._retracted:
+			raise ipaaca.exception.IURetractedError(self)
+		if self._committed:
 			raise ipaaca.exception.IUCommittedError(self)
 		with self.revision_lock:
 			# modify links locally
@@ -258,7 +260,9 @@ class IU(IUInterface):
 
 	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
 		"""Modify the payload: add or remove items from this payload locally and send update."""
-		if self.committed:
+		if self._retracted:
+			raise ipaaca.exception.IURetractedError(self)
+		if self._committed:
 			raise ipaaca.exception.IUCommittedError(self)
 		with self.revision_lock:
 			# set item locally
@@ -279,23 +283,33 @@ class IU(IUInterface):
 		self._revision += 1
 
 	def _internal_commit(self, writer_name=None):
-		if self.committed:
-			raise ipaaca.exception.IUCommittedError(self)
+		if self._committed:
+			return
+		if self._retracted:
+			raise ipaaca.exception.IURetractedError(self)
 		with self.revision_lock:
-			if not self._committed:
-				self._increase_revision_number()
-				self._committed = True
-				if self.buffer is not None:
-					self.buffer._send_iu_commission(self, writer_name=writer_name)
+			self._increase_revision_number()
+			self._committed = True
+			if self.buffer is not None:
+				self.buffer._send_iu_commission(self, writer_name=writer_name)
 
 	def commit(self):
 		"""Commit to this IU."""
 		return self._internal_commit()
 
+	def retract(self):
+		if self._buffer:
+			self._buffer.remove(self)
+			self._buffer = None
+		else:
+			self._retracted = True
+
 	def _get_payload(self):
 		return self._payload
 	def _set_payload(self, new_pl, writer_name=None):
-		if self.committed:
+		if self._retracted:
+			raise ipaaca.exception.IURetractedError(self)
+		if self._committed:
 			raise ipaaca.exception.IUCommittedError(self)
 		with self.revision_lock:
 			self._increase_revision_number()
@@ -316,7 +330,7 @@ class IU(IUInterface):
 
 	def _set_buffer(self, buffer):
 		if self._buffer is not None:
-			raise Exception('The IU is already in a buffer, cannot move it.')
+			raise ipaaca.exception.IpaacaError('The IU is already in a buffer, cannot move it.')
 		self._buffer = buffer
 		self.owner_name = buffer.unique_name
 		self._payload.owner_name = buffer.unique_name
@@ -364,7 +378,9 @@ class Message(IU):
 		if self.is_published:
 			LOGGER.info('Info: modifying a Message after sending has no global effects')
 		else:
-			if self.committed:
+			if self._retracted:
+				raise ipaaca.exception.IURetractedError(self)
+			if self._committed:
 				raise ipaaca.exception.IUCommittedError(self)
 			with self.revision_lock:
 				self._increase_revision_number()
@@ -385,7 +401,7 @@ class Message(IU):
 
 	def _set_buffer(self, buffer):
 		if self._buffer is not None:
-			raise Exception('The IU is already in a buffer, cannot move it.')
+			raise ipaaca.exception.IpaacaError('The IU is already in a buffer, cannot move it.')
 		self._buffer = buffer
 		self.owner_name = buffer.unique_name
 		self._payload.owner_name = buffer.unique_name
@@ -414,7 +430,6 @@ class RemoteMessage(IUInterface):
 		self._category = category
 		self.owner_name = owner_name
 		self._committed = committed
-		self._retracted = False
 		# NOTE Since the payload is an already-existant Payload which we didn't modify ourselves,
 		#  don't try to invoke any modification checks or network updates ourselves either.
 		#  We are just receiving it here and applying the new data.
@@ -481,7 +496,6 @@ class RemotePushIU(IUInterface):
 		self._category = category
 		self.owner_name = owner_name
 		self._committed = committed
-		self._retracted = False
 		# NOTE Since the payload is an already-existant Payload which we didn't modify ourselves,
 		#  don't try to invoke any modification checks or network updates ourselves either.
 		#  We are just receiving it here and applying the new data.
@@ -490,9 +504,11 @@ class RemotePushIU(IUInterface):
 
 	def _modify_links(self, is_delta=False, new_links={}, links_to_remove={}, writer_name=None):
 		"""Modify the links: add or remove item from this payload remotely and send update."""
-		if self.committed:
+		if self._retracted:
+			raise ipaaca.exception.IURetractedError(self)
+		if self._committed:
 			raise ipaaca.exception.IUCommittedError(self)
-		if self.read_only:
+		if self._read_only:
 			raise ipaaca.exception.IUReadOnlyError(self)
 		requested_update = ipaaca.converter.IULinkUpdate(
 				uid=self.uid,
@@ -510,9 +526,11 @@ class RemotePushIU(IUInterface):
 
 	def _modify_payload(self, is_delta=True, new_items={}, keys_to_remove=[], writer_name=None):
 		"""Modify the payload: add or remove item from this payload remotely and send update."""
-		if self.committed:
+		if self._retracted:
+			raise ipaaca.exception.IURetractedError(self)
+		if self._committed:
 			raise ipaaca.exception.IUCommittedError(self)
-		if self.read_only:
+		if self._read_only:
 			raise ipaaca.exception.IUReadOnlyError(self)
 		requested_update = ipaaca.converter.IUPayloadUpdate(
 				uid=self.uid,
@@ -531,30 +549,32 @@ class RemotePushIU(IUInterface):
 
 	def commit(self):
 		"""Commit to this IU."""
-		if self.read_only:
-			raise ipaaca.exception.IUReadOnlyError(self)
 		if self._committed:
-			# ignore commit requests when already committed
 			return
+		if self._retracted:
+			raise ipaaca.exception.IURetractedError(self)
+		if self._read_only:
+			raise ipaaca.exception.IUReadOnlyError(self)
+		commission_request = ipaaca_pb2.IUCommission()
+		commission_request.uid = self.uid
+		commission_request.revision = self.revision
+		commission_request.writer_name = self.buffer.unique_name
+		remote_server = self.buffer._get_remote_server(self)
+		new_revision = remote_server.commit(commission_request)
+		if new_revision == 0:
+			raise ipaaca.exception.IUUpdateFailedError(self)
 		else:
-			commission_request = ipaaca_pb2.IUCommission()
-			commission_request.uid = self.uid
-			commission_request.revision = self.revision
-			commission_request.writer_name = self.buffer.unique_name
-			remote_server = self.buffer._get_remote_server(self)
-			new_revision = remote_server.commit(commission_request)
-			if new_revision == 0:
-				raise ipaaca.exception.IUUpdateFailedError(self)
-			else:
-				self._revision = new_revision
-				self._committed = True
+			self._revision = new_revision
+			self._committed = True
 
 	def _get_payload(self):
 		return self._payload
 	def _set_payload(self, new_pl):
-		if self.committed:
+		if self._retracted:
+			raise ipaaca.exception.IURetractedError(self)
+		if self._committed:
 			raise ipaaca.exception.IUCommittedError(self)
-		if self.read_only:
+		if self._read_only:
 			raise ipaaca.exception.IUReadOnlyError(self)
 		requested_update = ipaaca.converter.IUPayloadUpdate(
 				uid=self.uid,
diff --git a/ipaacalib/python/src/ipaaca/misc.py b/ipaacalib/python/src/ipaaca/misc.py
index 44932d5f47442df1b4ce44c5399a31433a374431..b3bec913534df397dcb44124c9ff23354b0cf04d 100644
--- a/ipaacalib/python/src/ipaaca/misc.py
+++ b/ipaacalib/python/src/ipaaca/misc.py
@@ -4,7 +4,7 @@
 #  "Incremental Processing Architecture
 #   for Artificial Conversational Agents".
 #
-# Copyright (c) 2009-2014 Social Cognitive Systems Group
+# Copyright (c) 2009-2016 Social Cognitive Systems Group
 #                         CITEC, Bielefeld University
 #
 # http://opensource.cit-ec.de/projects/ipaaca/
@@ -124,6 +124,16 @@ class IpaacaArgumentParser(argparse.ArgumentParser):
 			rsb_logger.removeHandler(__GENERIC_NO_LOG_HANDLER)
 			rsb_logger.setLevel(level=values)
 
+	class IpaacaRSBSpreadHost(argparse.Action):
+
+		def __call__(self, parser, namespace, values, option_string=None):
+			ipaaca.defaults.IPAACA_DEFAULT_RSB_SPREAD_HOST = values
+
+	class IpaacaRSBSpreadPort(argparse.Action):
+
+		def __call__(self, parser, namespace, values, option_string=None):
+			ipaaca.defaults.IPAACA_DEFAULT_RSB_SPREADPORT = values
+
 	def __init__(self, prog=None, usage=None, description=None, epilog=None,
 			parents=[], formatter_class=argparse.HelpFormatter,
 			prefix_chars='-', fromfile_prefix_chars=None, 
@@ -136,6 +146,7 @@ class IpaacaArgumentParser(argparse.ArgumentParser):
 			conflict_handler=conflict_handler, add_help=add_help)
 
 	def _add_ipaaca_lib_arguments(self):
+		# CMD-arguments for ipaaca
 		ipaacalib_group = self.add_argument_group('IPAACA library arguments')
 		ipaacalib_group.add_argument(
 			'--ipaaca-payload-type', 
@@ -157,6 +168,7 @@ class IpaacaArgumentParser(argparse.ArgumentParser):
 			choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'],
 			dest='_ipaaca_logging_level_',
 			help="enable IPAACA logging with threshold")
+		# CMD-arguments for rsb
 		rsblib_group = self.add_argument_group('RSB library arguments')
 		rsblib_group.add_argument(
 			'--rsb-enable-logging', 
@@ -164,6 +176,20 @@ class IpaacaArgumentParser(argparse.ArgumentParser):
 			choices=['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG'],
 			dest='_ipaaca_rsb_enable_logging_',
 			help="enable RSB logging with threshold")
+		rsblib_group.add_argument(
+			'--rsb-spread-host', 
+			action=self.IpaacaRSBSpreadHost,
+			default=None,
+			dest='_ipaaca_rsb_set_spread_host_',
+			metavar='HOST',
+			help="set RSB spread host")
+		rsblib_group.add_argument(
+			'--rsb-spread-port', 
+			action=self.IpaacaRSBSpreadPort,
+			default=None,
+			dest='_ipaaca_rsb_set_spread_port_',
+			metavar='PORT',
+			help="set RSB spread port")
 
 	def parse_args(self, args=None, namespace=None):
 		self._add_ipaaca_lib_arguments() # Add ipaaca-args just before parsing
diff --git a/ipaacalib/python/src/ipaaca/util/logger.py b/ipaacalib/python/src/ipaaca/util/logger.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd254ba0c46203ce60b4f5c6be702a7160e288af
--- /dev/null
+++ b/ipaacalib/python/src/ipaaca/util/logger.py
@@ -0,0 +1,313 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2015 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+import datetime
+import subprocess
+import sys
+import threading
+import time
+import traceback
+import uuid
+
+import ipaaca
+
+
+__all__ = [
+	'logger_send_ipaaca_logs',
+	'logger_set_log_filename',
+	'logger_set_module_name',
+	'LOG_DEBUG',
+	'LOG_INFO',
+	'LOG_WARN',
+	'LOG_WARNING',
+	'LOG_ERROR',
+]
+
+LOGGER_LOCK = threading.RLock()
+
+MODULE_NAME = sys.argv[0]
+
+SEND_IPAACA_LOGS = True
+
+OUTPUT_BUFFER = None
+
+STANDARD_LOG_FILE_EXTENSION = '.log'
+
+LOG_MODES = ['append', 'timestamp', 'overwrite']
+
+
+def logger_set_log_filename(filename, existing=None):
+	global OUTPUT_BUFFER
+	if existing is not None and not existing in LOG_MODES:
+		raise Exception('Invalid log mode {mode} given. '
+			'Valid options are {options}.'.format(
+				mode=existing,
+				options=', '.join(LOG_MODES)))
+	with LOGGER_LOCK:
+		if OUTPUT_BUFFER is None:
+			OUTPUT_BUFFER = ipaaca.OutputBuffer('LogSender')
+		msg = ipaaca.Message('logcontrol')
+		msg.payload = {
+			'cmd': 'open_log_file',
+			'filename': filename}
+		if existing is not None:
+			msg.payload['existing'] = existing
+		OUTPUT_BUFFER.add(msg)
+
+
+def logger_set_module_name(name):
+	global MODULE_NAME
+	with LOGGER_LOCK:
+		MODULE_NAME = name
+
+
+def logger_send_ipaaca_logs(flag=True):
+	global SEND_IPAACA_LOGS
+	with LOGGER_LOCK:
+		SEND_IPAACA_LOGS = flag
+
+
+def LOG_IPAACA(lvl, text, now=0.0, fn='???', thread='???'):
+	global OUTPUT_BUFFER
+	uid = str(uuid.uuid4())[0:8]
+	with LOGGER_LOCK:
+		if OUTPUT_BUFFER is None:
+			OUTPUT_BUFFER = ipaaca.OutputBuffer('LogSender')
+		msg = ipaaca.Message('log')
+		msg.payload = {
+				'module': MODULE_NAME,
+				'function': fn,
+				'level': lvl,
+				'time':' %.3f'%now,
+				'thread': thread,
+				'uuid': uid,
+				'text': text,}
+		try:
+			OUTPUT_BUFFER.add(msg)
+		except Exception, e:
+			LOG_ERROR('Caught an exception while logging via ipaaca. '
+				+ ' str(e); ' 
+				+ traceback.format_exc())
+
+
+def LOG_CONSOLE(lvlstr, msg, fn_markup='', msg_markup='', now=0.0, fn='???', thread='???'):
+	if isinstance(msg, basestring):
+		lines = msg.split('\n')
+	else:
+		lines = [msg]
+	for line in lines:
+		text = lvlstr+' '+thread+' '+fn_markup+fn+''+' '+msg_markup+unicode(line)+''
+		print(text)
+		fn = ' '*len(fn)
+
+
+def LOG_ERROR(msg, now=None):
+	now = time.time() if now is None else now
+	f = sys._getframe(1)
+	classprefix = (f.f_locals['self'].__class__.__name__+'.') if 'self' in f.f_locals else ''
+	fn = classprefix + f.f_code.co_name
+	thread = threading.current_thread().getName()
+	with LOGGER_LOCK:
+		if SEND_IPAACA_LOGS: LOG_IPAACA('ERROR', msg, now=now, fn=fn, thread=thread)
+		LOG_CONSOLE('[ERROR]', msg, fn_markup='', msg_markup='', now=now, fn=fn, thread=thread)
+
+
+def LOG_WARN(msg, now=None):
+	now = time.time() if now is None else now
+	f = sys._getframe(1)
+	classprefix = (f.f_locals['self'].__class__.__name__+'.') if 'self' in f.f_locals else ''
+	fn = classprefix + f.f_code.co_name
+	thread = threading.current_thread().getName()
+	with LOGGER_LOCK:
+		if SEND_IPAACA_LOGS: LOG_IPAACA('WARN', msg, now=now, fn=fn, thread=thread)
+		LOG_CONSOLE('[WARN] ', msg, fn_markup='', msg_markup='', now=now, fn=fn, thread=thread)
+
+
+LOG_WARNING = LOG_WARN
+
+
+def LOG_INFO(msg, now=None):
+	now = time.time() if now is None else now
+	f = sys._getframe(1)
+	classprefix = (f.f_locals['self'].__class__.__name__+'.') if 'self' in f.f_locals else ''
+	fn = classprefix + f.f_code.co_name
+	thread = threading.current_thread().getName()
+	with LOGGER_LOCK:
+		if SEND_IPAACA_LOGS: LOG_IPAACA('INFO', msg, now=now, fn=fn, thread=thread)
+		LOG_CONSOLE('[INFO] ', msg, now=now, fn=fn, thread=thread)
+
+
+def LOG_DEBUG(msg, now=None):
+	now = time.time() if now is None else now
+	f = sys._getframe(1)
+	classprefix = (f.f_locals['self'].__class__.__name__+'.') if 'self' in f.f_locals else ''
+	fn = classprefix + f.f_code.co_name
+	thread = threading.current_thread().getName()
+	with LOGGER_LOCK:
+		if SEND_IPAACA_LOGS: LOG_IPAACA('DEBUG', msg, now=now, fn=fn, thread=thread)
+		LOG_CONSOLE('[DEBUG]', msg, fn_markup='', msg_markup='', now=now, fn=fn, thread=thread)
+
+
+class LoggerComponent(object):
+
+	def __init__(self, filename, log_mode='append'):
+		self.ib = ipaaca.InputBuffer('Logger', ['log', 'logcontrol'])
+		self.ib.register_handler(self._logger_handle_iu_event)
+		self.logfile = None
+		self.log_mode = log_mode
+		self.open_logfile(filename)
+		if self.logfile is None:
+			print('Logging to console only ...')
+		print('Press Ctrl-C at any time to terminate the logger.')
+
+	def open_logfile(self, filename):
+		with LOGGER_LOCK:
+			if filename is None or filename.strip() == '':
+				print('No log file name specified, not opening one.')
+				self.close_logfile()
+			else:
+				new_logfile = None
+				try:
+					# create dir first
+					ret = subprocess.call(
+							'mkdir -p `dirname ' + filename + '`',
+							shell=True)
+					# proceed with dir+file
+					if self.log_mode == 'timestamp':
+						t = datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S')
+						if filename.endswith(STANDARD_LOG_FILE_EXTENSION):
+							# insert timestamp between filename and extension
+							# (only for standard extension)
+							filename = filename.replace(
+									STANDARD_LOG_FILE_EXTENSION,
+									'.' + t + STANDARD_LOG_FILE_EXTENSION)
+						else: # prepend timestamp
+							filename = t + '_' + filename
+					append_if_exist = not (self.log_mode == 'overwrite' or
+							self.log_mode == 'timestamp')
+					new_logfile = open(filename, 'a' if append_if_exist else 'w')
+					if self.logfile is not None:
+						text = u'Will now continue logging in log file ' + unicode(filename)
+						uid = str(uuid.uuid4())[0:8]
+						tim = time.time()
+						record = {
+							'uuid': uid, 
+							'time': tim,
+							'level': u'INFO',
+							'text': text,
+							'module': u'logger',
+							'function': u'LoggerComponent.open_logfile', 
+							'thread': '-', 
+							'logreceivedtime': tim}
+						self.logfile.write(unicode(record)+'\n')
+						self.logfile.close()
+					self.logfile = new_logfile
+					print('Logging to console and {filename} ...'.format(filename=filename))
+				except Exception as e:
+					print('Failed to open logfile {filename} for writing! Keeping previous configuration'.format(filename=filename))
+
+	def close_logfile(self):
+		if self.logfile is not None:
+			text = u'Closing of log file requested.'
+			uid = unicode(uuid.uuid4())[0:8]
+			tim = unicode(time.time())
+			record = {
+				'uuid': uid,
+				'time': tim,
+				'level': u'INFO',
+				'text': text,
+				'module': u'logger',
+				'function': u'LoggerComponent.close_logfile', 
+				'thread': u'-',
+				'logreceivedtime': tim}
+			self.logfile.write(unicode(record)+'\n')
+			self.logfile.close()
+			print('Closed current log file.')
+			self.logfile = None
+
+	def _logger_handle_iu_event(self, iu, event_type, own):
+		received_time = "%.3f" % time.time()
+		with LOGGER_LOCK:
+			try:
+				if iu.category == 'log':
+					pl = iu.payload
+					message = pl['text'] if 'text' in pl else '(No message.)'
+					uid = '????????' if 'uuid' not in pl else pl['uuid']
+					tim = '???' if 'time' not in pl else pl['time']
+					module = '???' if 'module' not in pl else pl['module']
+					function = '???' if 'function' not in pl else pl['function']
+					thread = '???' if 'thread' not in pl else pl['thread']
+					level = 'INFO' if 'level' not in pl else pl['level']
+					# dump to console
+					if level=='WARN':
+						level='WARNING'
+					if level not in ['DEBUG','INFO','WARNING','ERROR']:
+						level = 'INFO'
+					try:
+						print('%s %-8s {%s} {%s} {%s} %s'%(tim, ('['+level+']'), thread, module, function, message))
+					except:
+						print('Failed to format a string for printing!')
+					if self.logfile is not None:
+						try:
+							record = {
+								'uuid': uid, 
+								'time': tim, 
+								'level': level, 
+								'text': message,
+								'module': module,
+								'function': function, 
+								'thread': thread,
+								'logreceivedtime': received_time}
+							self.logfile.write(unicode(record) + '\n')
+						except:
+							print('Failed to write to logfile!')
+				elif iu.category == 'logcontrol':
+					cmd = iu.payload['cmd']
+					if cmd == 'open_log_file':
+						filename = iu.payload['filename'] if 'filename' in iu.payload else ''
+						if 'existing' in iu.payload:
+							log_mode_ = iu.payload['existing'].lower()
+							if log_mode_ not in LOG_MODES:
+								LOG_WARN(u'Value of "existing" should be "append", timestamp, or  "overwrite", continuing with mode {mode}'.format(mode=self.log_mode))
+							else:
+								self.log_mode = log_mode_
+						self.open_logfile(filename)
+					elif cmd == 'close_log_file':
+						self.close_logfile()
+					else:
+						LOG_WARN(u'Received unknown logcontrol command: '+unicode(cmd))
+			except Exception, e:
+				print('Exception while logging!')  # TODO write to file as well?
+				print(u'  '+unicode(traceback.format_exc()))
diff --git a/ipaacatools/scripts/ipaaca-iu-sniffer b/ipaacatools/scripts/ipaaca-iu-sniffer
index a4db5847098f8a1078cf50d4051719a84642f8f6..82e919432887c96b9d51320f174e71570b360d39 100755
--- a/ipaacatools/scripts/ipaaca-iu-sniffer
+++ b/ipaacatools/scripts/ipaaca-iu-sniffer
@@ -56,7 +56,7 @@ def event_type_color(typ):
 	return colors.get(typ, '1')
 
 def highlight_if_color(s, c='1'):
-	return s if not arguments.color else '[' + c + 'm' + s +''
+	return s if arguments.color else '[' + c + 'm' + s +''
 
 def pretty_printed_dict(d):
 	s='{\n'
@@ -87,7 +87,7 @@ def pretty_printed_iu_event(iu, event_type, local):
 	s += '\npayload=' + pretty_printed_dict(iu.payload)
 	return s
 
-def my_update_handler(iu, event_type, local):
+def iu_event_handler(iu, event_type, local):
 	if arguments.regex:
 		for cat in arguments.categories: # actually now regexs, not categories
 			if re.match(cat, iu.category):
@@ -96,19 +96,13 @@ def my_update_handler(iu, event_type, local):
 			return
 	print(pretty_printed_iu_event(iu, event_type, local), end='\n\n')
 
-
+def exit(code):
+	if platform.system() == 'Windows':
+		os._exit(code)
+	else:
+		sys.exit(code)
 
 parser = ipaaca.IpaacaArgumentParser(description='Ipaaca IU Sniffer -- Selectively listen to IPAACA traffic')
-parser.add_argument(
-	'-r', '--regex',
-	action='store_true',
-	dest='regex',
-	help='match categories by regular expressions')
-parser.add_argument(
-	'-c', '--color',
-	action='store_true',
-	dest='color',
-	help='colorize output')
 parser.add_argument(
 	'--channels',
 	dest='channels',
@@ -117,12 +111,29 @@ parser.add_argument(
 	nargs='+',
 	help="set the channels to listen on (otherwise 'default')")
 parser.add_argument(
-	'--categories',
+	'-c', '--categories',
 	default=[''],
 	dest='categories',
 	metavar='CATEGORY',
 	nargs='+',
 	help='set categories (or regex patterns) to be matched')
+parser.add_argument(
+	'-e', '--event-types',
+	default=None,
+	dest='event_types',
+	metavar='EVENT-TYPE',
+	nargs='+',
+	help='set event types ({})'.format(' '.join(ipaaca.iu.IUEventType._choices)))
+parser.add_argument(
+	'-r', '--regex',
+	action='store_true',
+	dest='regex',
+	help='match categories by regular expressions')
+parser.add_argument(
+	'--no-color',
+	action='store_true',
+	dest='color',
+	help='do not colorize output')
 parser.add_argument(
 	'--size-limit',
 	default=2048,
@@ -134,37 +145,45 @@ parser.add_argument(
 
 if __name__ == '__main__':
 	arguments = parser.parse_args()
-
 	buffers = {}
+
+	# Create one input buffer for each channel we are listening on
 	for channel in arguments.channels:
 		buffers[channel] = ipaaca.InputBuffer(
 			'IpaacaIUSniffer',
 			category_interests=arguments.categories if not arguments.regex else [''],
 			channel=channel,
 			resend_active=True)
-		buffers[channel].register_handler(my_update_handler)
-
-	channellist = 's ' if len(arguments.channels) > 1 else ' '
-	channellist += ', '.join(arguments.channels)
-	
-	print('Listening on channel' + channellist + ' for IU events of ', end='')
+		# Check whether the specified event_types are valid
+		if arguments.event_types is not None:
+			for et in arguments.event_types:
+				if et.upper() not in ipaaca.iu.IUEventType._choices:
+					print('ERROR: "{et}" is not a valid IPAACA event type.'.format(et=et.upper()))
+					exit(code=1)
+		buffers[channel].register_handler(
+			iu_event_handler,
+			for_event_types=[et.upper() for et in arguments.event_types] if arguments.event_types is not None else None)
+
+	# Tell user what we are doing
+	print('ipaaca-iu-sniffer listening')
+	print('  * on channel(s): ' + ', '.join(arguments.channels))
+	print('  * for event type(s): ', end='')
+	if arguments.event_types is None:
+		print('any')
+	else:
+		print(', '.join([highlight_if_color(et.upper(), event_type_color(et.upper())) for et in arguments.event_types]))
+	print('  * for category/ies', end='')
 	if arguments.categories == ['']:
-		print('any category ...')
+		print(': any')
 	else:
 		if arguments.regex:
-			print('whose category matches one of the regexes:')
-		else:
-			print('categories:')
-		print('\t' + ', '.join(arguments.categories))
-	print('')
+			print(' that match the regex', end='')
+		print(': ' + ', '.join(arguments.categories))
+
+	# Wait for the user to kill the sniffer
 	try:
 		while True:
 			time.sleep(1)
 	except KeyboardInterrupt:
 		pass
-	
-	if platform.system() == 'Windows':
-		os._exit(0)
-	else:
-		sys.exit(0)
-	
+	exit(code=0)
diff --git a/ipaacatools/scripts/ipaaca-logger b/ipaacatools/scripts/ipaaca-logger
new file mode 100755
index 0000000000000000000000000000000000000000..230143cfd2e193ad2507aa7c2671e8585be76aa6
--- /dev/null
+++ b/ipaacatools/scripts/ipaaca-logger
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# This file is part of IPAACA, the
+#  "Incremental Processing Architecture
+#   for Artificial Conversational Agents".
+#
+# Copyright (c) 2009-2015 Social Cognitive Systems Group
+#                         CITEC, Bielefeld University
+#
+# http://opensource.cit-ec.de/projects/ipaaca/
+# http://purl.org/net/ipaaca
+#
+# This file may be licensed under the terms of of the
+# GNU Lesser General Public License Version 3 (the ``LGPL''),
+# or (at your option) any later version.
+#
+# Software distributed under the License is distributed
+# on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
+# express or implied. See the LGPL for the specific language
+# governing rights and limitations.
+#
+# You should have received a copy of the LGPL along with this
+# program. If not, go to http://www.gnu.org/licenses/lgpl.html
+# or write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# The development of this software was supported by the
+# Excellence Cluster EXC 277 Cognitive Interaction Technology.
+# The Excellence Cluster EXC 277 is a grant of the Deutsche
+# Forschungsgemeinschaft (DFG) in the context of the German
+# Excellence Initiative.
+
+from __future__ import division, print_function
+
+import sys
+import time
+
+import ipaaca
+import ipaaca.util.logger as ipaacalog
+
+
+def main(log_mode, filename=None):
+	ipaacalog.logger_send_ipaaca_logs(False)
+	il = ipaacalog.LoggerComponent(filename, log_mode)
+	try:
+		while True:
+			time.sleep(1)
+	except KeyboardInterrupt:
+		il.close_logfile()
+		print('Logging-Component closed by keyboard interrupt.')
+		sys.exit(0)
+
+
+if __name__ == '__main__':
+	iap = ipaaca.IpaacaArgumentParser(
+        'ipaaca-logger')
+	iap.add_argument(
+		'-m', '--log-mode', dest='log_mode',
+		choices=ipaacalog.LOG_MODES,
+		default='append',
+		help="set what to do when logfile exists "
+				"(default: 'append'; 'timestamp' adds timestamp in any case)")
+	iap.add_argument(
+		'filename', nargs='?',
+		metavar='FILE',
+		help='set name of logfile')
+	arguments = iap.parse_args()
+	main(arguments.log_mode, arguments.filename)