Repository: eclipse/leshan
Pull request #616 (2018-11-13 15:52:27)

Add a way to make "atomic" operation (read/write) on LwM2mInstanceEnabler
Experimental work to try to support https://github.com/eclipse/leshan/issues/597#issuecomment-437888248

>At the client side I need to read all resources of a particular instance and pass it to another layer. Now since resources ids are called one by one in switch case (write/read), its not possible to send complete object at once. Thats the main reason I wanted to read complete instance at once and pass it to other layer.

The new API in LwM2mInstanceEnabler

```java
/**
* Gets values of all readable resources of this instance.
* 
* @param identity the identity of the requester. This could be an internal call in this case
*        <code> identity == ServerIdentity.SYSTEM</code>.
* 
* @return a success response with an {@link LwM2mObjectInstance} as content or a failure response with optional
*         explanation message.
*/
ReadResponse read(ServerIdentity identity);
```

sbernard31: I added the write and observe operation.

Patch:
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Device.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Device.java
index 743180e9..923e4a4a 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Device.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Device.java
@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.TimeZone;
 
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
 import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler;
 import org.eclipse.leshan.core.model.ObjectModel;
@@ -56,7 +57,7 @@ public class Device extends BaseInstanceEnabler {
     }
 
     @Override
-    public ReadResponse read(int resourceid) {
+    public ReadResponse read(ServerIdentity identity, int resourceid) {
 
         switch (resourceid) {
         case 0: // manufacturer
@@ -81,12 +82,12 @@ public class Device extends BaseInstanceEnabler {
             return ReadResponse.success(resourceid, supportedBinding);
 
         default:
-            return super.read(resourceid);
+            return super.read(identity, resourceid);
         }
     }
 
     @Override
-    public WriteResponse write(int resourceid, LwM2mResource value) {
+    public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
 
         switch (resourceid) {
 
@@ -101,17 +102,17 @@ public class Device extends BaseInstanceEnabler {
             return WriteResponse.success();
 
         default:
-            return super.write(resourceid, value);
+            return super.write(identity, resourceid, value);
         }
     }
 
     @Override
-    public ExecuteResponse execute(int resourceid, String params) {
+    public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
 
         if (resourceid == 4) { // reboot
             return ExecuteResponse.internalServerError("not implemented");
         } else {
-            return super.execute(resourceid, params);
+            return super.execute(identity, resourceid, params);
         }
     }
 
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Security.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Security.java
index a7b9e63d..82f1a5c1 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Security.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Security.java
@@ -21,6 +21,7 @@ import java.util.Arrays;
 import java.util.List;
 
 import org.eclipse.leshan.SecurityMode;
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
 import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler;
 import org.eclipse.leshan.core.model.ObjectModel;
@@ -135,7 +136,7 @@ public class Security extends BaseInstanceEnabler {
     }
 
     @Override
-    public WriteResponse write(int resourceId, LwM2mResource value) {
+    public WriteResponse write(ServerIdentity identity, int resourceId, LwM2mResource value) {
         LOG.debug("Write on resource {}: {}", resourceId, value);
 
         // restricted to BS server?
@@ -189,13 +190,13 @@ public class Security extends BaseInstanceEnabler {
             return WriteResponse.success();
 
         default:
-            return super.write(resourceId, value);
+            return super.write(identity, resourceId, value);
         }
 
     }
 
     @Override
-    public ReadResponse read(int resourceid) {
+    public ReadResponse read(ServerIdentity identity, int resourceid) {
         // only accessible for internal read?
 
         switch (resourceid) {
@@ -221,13 +222,13 @@ public class Security extends BaseInstanceEnabler {
             return ReadResponse.success(resourceid, shortServerId);
 
         default:
-            return super.read(resourceid);
+            return super.read(identity, resourceid);
         }
     }
 
     @Override
-    public ExecuteResponse execute(int resourceid, String params) {
-        return super.execute(resourceid, params);
+    public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
+        return super.execute(identity, resourceid, params);
     }
 
     @Override
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Server.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Server.java
index dfde43a6..141d001b 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Server.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/object/Server.java
@@ -20,6 +20,7 @@ package org.eclipse.leshan.client.object;
 import java.util.Arrays;
 import java.util.List;
 
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
 import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler;
 import org.eclipse.leshan.core.model.ObjectModel;
@@ -56,7 +57,7 @@ public class Server extends BaseInstanceEnabler {
     }
 
     @Override
-    public ReadResponse read(int resourceid) {
+    public ReadResponse read(ServerIdentity identity, int resourceid) {
 
         switch (resourceid) {
         case 0: // short server ID
@@ -82,12 +83,12 @@ public class Server extends BaseInstanceEnabler {
             return ReadResponse.success(resourceid, binding.toString());
 
         default:
-            return super.read(resourceid);
+            return super.read(identity, resourceid);
         }
     }
 
     @Override
-    public WriteResponse write(int resourceid, LwM2mResource value) {
+    public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
 
         switch (resourceid) {
 
@@ -138,18 +139,18 @@ public class Server extends BaseInstanceEnabler {
             }
 
         default:
-            return super.write(resourceid, value);
+            return super.write(identity, resourceid, value);
         }
     }
 
     @Override
-    public ExecuteResponse execute(int resourceid, String params) {
+    public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
 
         if (resourceid == 8) { // registration update trigger
             // TODO implement registration update trigger executable resource
             return ExecuteResponse.internalServerError("not implemented");
         } else {
-            return super.execute(resourceid, params);
+            return super.execute(identity, resourceid, params);
         }
     }
 
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseInstanceEnabler.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseInstanceEnabler.java
index 70c0280d..7c3126e5 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseInstanceEnabler.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseInstanceEnabler.java
@@ -19,9 +19,14 @@ package org.eclipse.leshan.client.resource;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.core.model.ObjectModel;
+import org.eclipse.leshan.core.model.ResourceModel;
+import org.eclipse.leshan.core.node.LwM2mObjectInstance;
 import org.eclipse.leshan.core.node.LwM2mResource;
 import org.eclipse.leshan.core.response.ExecuteResponse;
 import org.eclipse.leshan.core.response.ObserveResponse;
@@ -30,8 +35,9 @@ import org.eclipse.leshan.core.response.WriteResponse;
 
 public class BaseInstanceEnabler implements LwM2mInstanceEnabler {
 
-    private List<ResourceChangedListener> listeners = new ArrayList<>();
-    private Integer id = null;
+    protected List<ResourceChangedListener> listeners = new ArrayList<>();
+    protected Integer id = null;
+    protected ObjectModel model;
 
     public BaseInstanceEnabler() {
     }
@@ -50,6 +56,15 @@ public class BaseInstanceEnabler implements LwM2mInstanceEnabler {
         return id;
     }
 
+    @Override
+    public void setModel(ObjectModel model) {
+        this.model = model;
+    }
+
+    public ObjectModel getModel() {
+        return model;
+    }
+
     @Override
     public void addResourceChangedListener(ResourceChangedListener listener) {
         listeners.add(listener);
@@ -67,24 +82,70 @@ public class BaseInstanceEnabler implements LwM2mInstanceEnabler {
     }
 
     @Override
-    public ReadResponse read(int resourceid) {
+    public ReadResponse read(ServerIdentity identity) {
+        List<LwM2mResource> resources = new ArrayList<>();
+        for (ResourceModel resourceModel : model.resources.values()) {
+            // check, if internal request (SYSTEM) or readable
+            if (identity.isSystem() || resourceModel.operations.isReadable()) {
+                ReadResponse response = read(identity, resourceModel.id);
+                if (response.isSuccess() && response.getContent() instanceof LwM2mResource)
+                    resources.add((LwM2mResource) response.getContent());
+            }
+        }
+        return ReadResponse.success(new LwM2mObjectInstance(id, resources));
+    }
+
+    @Override
+    public ReadResponse read(ServerIdentity identity, int resourceid) {
         return ReadResponse.notFound();
     }
 
     @Override
-    public WriteResponse write(int resourceid, LwM2mResource value) {
+    public WriteResponse write(ServerIdentity identity, boolean replace, LwM2mObjectInstance value) {
+        Map<Integer, LwM2mResource> resourcesToWrite = new HashMap<>(value.getResources());
+
+        if (replace) {
+            // REPLACE
+            for (ResourceModel resourceModel : model.resources.values()) {
+                if (!identity.isLwm2mServer() || resourceModel.operations.isWritable()) {
+                    LwM2mResource writeResource = resourcesToWrite.remove(resourceModel.id);
+                    if (null != writeResource) {
+                        write(identity, resourceModel.id, writeResource);
+                    } else {
+                        reset(resourceModel.id);
+                    }
+                }
+            }
+        }
+        // UPDATE and resources currently not in the model
+        for (LwM2mResource resource : resourcesToWrite.values()) {
+            write(identity, resource.getId(), resource);
+        }
+        return WriteResponse.success();
+    }
+
+    @Override
+    public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
         return WriteResponse.notFound();
     }
 
     @Override
-    public ExecuteResponse execute(int resourceid, String params) {
+    public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
         return ExecuteResponse.notFound();
     }
 
     @Override
-    public ObserveResponse observe(int resourceid) {
+    public ObserveResponse observe(ServerIdentity identity) {
+        // Perform a read by default
+        ReadResponse readResponse = this.read(identity);
+        return new ObserveResponse(readResponse.getCode(), readResponse.getContent(), null, null,
+                readResponse.getErrorMessage());
+    }
+
+    @Override
+    public ObserveResponse observe(ServerIdentity identity, int resourceid) {
         // Perform a read by default
-        ReadResponse readResponse = this.read(resourceid);
+        ReadResponse readResponse = this.read(identity, resourceid);
         return new ObserveResponse(readResponse.getCode(), readResponse.getContent(), null, null,
                 readResponse.getErrorMessage());
     }
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseInstanceEnablerFactory.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseInstanceEnablerFactory.java
index 65f3a8ac..cf81d923 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseInstanceEnablerFactory.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseInstanceEnablerFactory.java
@@ -29,7 +29,7 @@ public abstract class BaseInstanceEnablerFactory implements LwM2mInstanceEnabler
         }
 
         // create new instance
-        LwM2mInstanceEnabler instance = create(model);
+        LwM2mInstanceEnabler instance = create();
 
         // set id if not already done
         if (instance.getId() == null) {
@@ -42,6 +42,9 @@ public abstract class BaseInstanceEnablerFactory implements LwM2mInstanceEnabler
             }
         }
 
+        // set model
+        instance.setModel(model);
+
         return instance;
     }
 
@@ -58,10 +61,9 @@ public abstract class BaseInstanceEnablerFactory implements LwM2mInstanceEnabler
     /**
      * Create a new instance enabler.
      * 
-     * @param model of this instance (CAN NOT be null).
      * @return the new instance enabler
      */
-    public abstract LwM2mInstanceEnabler create(ObjectModel model);
+    public abstract LwM2mInstanceEnabler create();
 
     public static int generateNewInstanceId(Collection<Integer> alreadyUsedIdentifier) {
         if (alreadyUsedIdentifier.isEmpty()) {
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseObjectEnabler.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseObjectEnabler.java
index 97e361f0..91648e17 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseObjectEnabler.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/BaseObjectEnabler.java
@@ -93,10 +93,10 @@ public abstract class BaseObjectEnabler implements LwM2mObjectEnabler {
                 return CreateResponse.notFound();
             }
         }
-        return doCreate(request);
+        return doCreate(identity, request);
     }
 
-    protected CreateResponse doCreate(CreateRequest request) {
+    protected CreateResponse doCreate(ServerIdentity identity, CreateRequest request) {
         // This should be a not implemented error, but this is not defined in the spec.
         return CreateResponse.internalServerError("not implemented");
     }
@@ -230,10 +230,10 @@ public abstract class BaseObjectEnabler implements LwM2mObjectEnabler {
             }
         }
 
-        return doDelete(request);
+        return doDelete(identity, request);
     }
 
-    protected DeleteResponse doDelete(DeleteRequest request) {
+    protected DeleteResponse doDelete(ServerIdentity identity, DeleteRequest request) {
         // This should be a not implemented error, but this is not defined in the spec.
         return DeleteResponse.internalServerError("not implemented");
     }
@@ -245,10 +245,10 @@ public abstract class BaseObjectEnabler implements LwM2mObjectEnabler {
                 return BootstrapDeleteResponse.badRequest("Device object instance is not deletable");
             }
         }
-        return doDelete(request);
+        return doDelete(identity, request);
     }
 
-    public BootstrapDeleteResponse doDelete(BootstrapDeleteRequest request) {
+    public BootstrapDeleteResponse doDelete(ServerIdentity identity, BootstrapDeleteRequest request) {
         // This should be a not implemented error, but this is not defined in the spec.
         return BootstrapDeleteResponse.internalServerError("not implemented");
     }
@@ -278,10 +278,10 @@ public abstract class BaseObjectEnabler implements LwM2mObjectEnabler {
             return ExecuteResponse.methodNotAllowed();
         }
 
-        return doExecute(request);
+        return doExecute(identity, request);
     }
 
-    protected ExecuteResponse doExecute(ExecuteRequest request) {
+    protected ExecuteResponse doExecute(ServerIdentity identity, ExecuteRequest request) {
         // This should be a not implemented error, but this is not defined in the spec.
         return ExecuteResponse.internalServerError("not implemented");
     }
@@ -305,11 +305,11 @@ public abstract class BaseObjectEnabler implements LwM2mObjectEnabler {
         if (id == LwM2mId.SECURITY) {
             return DiscoverResponse.notFound();
         }
-        return doDiscover(request);
+        return doDiscover(identity, request);
 
     }
 
-    protected DiscoverResponse doDiscover(DiscoverRequest request) {
+    protected DiscoverResponse doDiscover(ServerIdentity identity, DiscoverRequest request) {
 
         LwM2mPath path = request.getPath();
         if (path.isObject()) {
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/LwM2mInstanceEnabler.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/LwM2mInstanceEnabler.java
index 9bb847b7..1d46a8db 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/LwM2mInstanceEnabler.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/LwM2mInstanceEnabler.java
@@ -20,8 +20,11 @@ package org.eclipse.leshan.client.resource;
 
 import java.util.List;
 
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.core.model.ObjectModel;
+import org.eclipse.leshan.core.node.LwM2mObjectInstance;
 import org.eclipse.leshan.core.node.LwM2mResource;
+import org.eclipse.leshan.core.request.WriteRequest.Mode;
 import org.eclipse.leshan.core.response.ExecuteResponse;
 import org.eclipse.leshan.core.response.ObserveResponse;
 import org.eclipse.leshan.core.response.ReadResponse;
@@ -60,6 +63,14 @@ public interface LwM2mInstanceEnabler {
      */
     void setId(int id);
 
+    /**
+     * Set the model of this instance. It should be called only by
+     * {@link LwM2mInstanceEnablerFactory#create(ObjectModel, Integer, java.util.Collection)}.
+     * 
+     * @param model the model of this instance
+     */
+    void setModel(ObjectModel model);
+
     /**
      * Adds a callback handler that gets notified about changes to any of this LWM2M object instance's resources.
      * 
@@ -74,44 +85,86 @@ public interface LwM2mInstanceEnabler {
      */
     void removeResourceChangedListener(ResourceChangedListener listener);
 
+    /**
+     * Gets values of all readable resources of this instance.
+     * 
+     * @param identity the identity of the requester. This could be an internal call in this case
+     *        <code> identity == ServerIdentity.SYSTEM</code>.
+     * 
+     * @return a success response with an {@link LwM2mObjectInstance} as content or a failure response with optional
+     *         explanation message.
+     */
+    ReadResponse read(ServerIdentity identity);
+
     /**
      * Gets the current value of one of this LWM2M object instance's resources.
      * 
+     * @param identity the identity of the requester. This could be an internal call in this case
+     *        <code> identity == ServerIdentity.SYSTEM</code>.
      * @param resourceId the ID of the resource to get the value of
      * @return the response object representing the outcome of the operation. An implementation should set the result's
      *         {@link ReadResponse#getCode() response code} to either reflect the success or reason for failure to
      *         retrieve the value.
      */
-    ReadResponse read(int resourceId);
+    ReadResponse read(ServerIdentity identity, int resourceId);
+
+    /**
+     * Sets all resources of this LWM2M object instance.
+     * 
+     * @param identity the identity of the requester. This could be an internal call in this case
+     *        <code> identity == ServerIdentity.SYSTEM</code>.
+     * @param replace if replace is true a {@link Mode#REPLACE} should be done, else {@link Mode#UPDATE} should be done.
+     * @param value all the resources to be written.
+     * @return the response object representing the outcome of the operation. An implementation should set the result's
+     *         {@link WriteResponse#getCode() response code} to either reflect the success or reason for failure to set
+     *         the value.
+     */
+    WriteResponse write(ServerIdentity identity, boolean replace, LwM2mObjectInstance value);
 
     /**
      * Sets the value of one of this LWM2M object instance's resources.
      * 
+     * @param identity the identity of the requester. This could be an internal call in this case
+     *        <code> identity == ServerIdentity.SYSTEM</code>.
      * @param resourceid the ID of the resource to set the value for
      * @param value the value to set the resource to
      * @return the response object representing the outcome of the operation. An implementation should set the result's
      *         {@link WriteResponse#getCode() response code} to either reflect the success or reason for failure to set
      *         the value.
      */
-    WriteResponse write(int resourceid, LwM2mResource value);
+    WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value);
 
     /**
      * Executes the operation represented by one of this LWM2M object instance's resources.
      * 
+     * @param identity the identity of the requester. This could be an internal call in this case
+     *        <code> identity == ServerIdentity.SYSTEM</code>.
      * @param resourceid the ID of the resource to set the value for
      * @param params the input parameters of the operation
      * @return the response object representing the outcome of the operation. An implementation should set the result's
      *         {@link ExecuteResponse#getCode() response code} to either reflect the success or reason for failure to
      *         execute the operation.
      */
-    ExecuteResponse execute(int resourceid, String params);
+    ExecuteResponse execute(ServerIdentity identity, int resourceid, String params);
+
+    /**
+     * Performs an observe register the whole LWM2M object instance.
+     * 
+     * @param identity the identity of the requester. This could be an internal call in this case
+     *        <code> identity == ServerIdentity.SYSTEM</code>.
+     * @return a success response with an {@link LwM2mObjectInstance} as content or a failure response with optional
+     *         explanation message.
+     */
+    ObserveResponse observe(ServerIdentity identity);
 
     /**
      * Performs an observe register on one of this LWM2M object instance's resources.
-     *
+     * 
+     * @param identity the identity of the requester. This could be an internal call in this case
+     *        <code> identity == ServerIdentity.SYSTEM</code>.
      * @param resourceid the ID of the resource to set the value for
      */
-    ObserveResponse observe(int resourceid);
+    ObserveResponse observe(ServerIdentity identity, int resourceid);
 
     /**
      * @param objectModel the model of this instance
@@ -126,5 +179,4 @@ public interface LwM2mInstanceEnabler {
      * @param resourceId the ID of the resource to be reseted
      */
     void reset(int resourceId);
-
 }
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/ObjectEnabler.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/ObjectEnabler.java
index 5d7d9640..6bdce349 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/ObjectEnabler.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/ObjectEnabler.java
@@ -25,11 +25,9 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import org.eclipse.leshan.LwM2mId;
-import org.eclipse.leshan.ResponseCode;
 import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.servers.ServersInfoExtractor;
 import org.eclipse.leshan.core.model.ObjectModel;
-import org.eclipse.leshan.core.model.ResourceModel;
 import org.eclipse.leshan.core.node.LwM2mObject;
 import org.eclipse.leshan.core.node.LwM2mObjectInstance;
 import org.eclipse.leshan.core.node.LwM2mPath;
@@ -102,7 +100,7 @@ public class ObjectEnabler extends BaseObjectEnabler {
     }
 
     @Override
-    protected CreateResponse doCreate(CreateRequest request) {
+    protected CreateResponse doCreate(ServerIdentity identity, CreateRequest request) {
         Integer instanceId = request.getInstanceId(); // instanceId CAN be NULL
 
         // check instance id is valid
@@ -125,7 +123,7 @@ public class ObjectEnabler extends BaseObjectEnabler {
 
         // add/write resource
         for (LwM2mResource resource : request.getResources()) {
-            newInstance.write(resource.getId(), resource);
+            newInstance.write(identity, resource.getId(), resource);
         }
 
         // add new instance to this object
@@ -142,8 +140,11 @@ public class ObjectEnabler extends BaseObjectEnabler {
         // Manage Object case
         if (path.isObject()) {
             List<LwM2mObjectInstance> lwM2mObjectInstances = new ArrayList<>();
-            for (Entry<Integer, LwM2mInstanceEnabler> entry : instances.entrySet()) {
-                lwM2mObjectInstances.add(getLwM2mObjectInstance(entry.getKey(), entry.getValue(), identity, false));
+            for (LwM2mInstanceEnabler instance : instances.values()) {
+                ReadResponse response = instance.read(identity);
+                if (response.isSuccess()) {
+                    lwM2mObjectInstances.add((LwM2mObjectInstance) response.getContent());
+                }
             }
             return ReadResponse.success(new LwM2mObject(getId(), lwM2mObjectInstances));
         }
@@ -154,11 +155,11 @@ public class ObjectEnabler extends BaseObjectEnabler {
             return ReadResponse.notFound();
 
         if (path.getResourceId() == null) {
-            return ReadResponse.success(getLwM2mObjectInstance(path.getObjectInstanceId(), instance, identity, false));
+            return instance.read(identity);
         }
 
         // Manage Resource case
-        return instance.read(path.getResourceId());
+        return instance.read(identity, path.getResourceId());
     }
 
     @Override
@@ -168,8 +169,11 @@ public class ObjectEnabler extends BaseObjectEnabler {
         // Manage Object case
         if (path.isObject()) {
             List<LwM2mObjectInstance> lwM2mObjectInstances = new ArrayList<>();
-            for (Entry<Integer, LwM2mInstanceEnabler> entry : instances.entrySet()) {
-                lwM2mObjectInstances.add(getLwM2mObjectInstance(entry.getKey(), entry.getValue(), identity, true));
+            for (LwM2mInstanceEnabler instance : instances.values()) {
+                ReadResponse response = instance.observe(identity);
+                if (response.isSuccess()) {
+                    lwM2mObjectInstances.add((LwM2mObjectInstance) response.getContent());
+                }
             }
             return ObserveResponse.success(new LwM2mObject(getId(), lwM2mObjectInstances));
         }
@@ -180,32 +184,11 @@ public class ObjectEnabler extends BaseObjectEnabler {
             return ObserveResponse.notFound();
 
         if (path.getResourceId() == null) {
-            return ObserveResponse
-                    .success(getLwM2mObjectInstance(path.getObjectInstanceId(), instance, identity, true));
+            return instance.observe(identity);
         }
 
         // Manage Resource case
-        return instance.observe(path.getResourceId());
-    }
-
-    LwM2mObjectInstance getLwM2mObjectInstance(int instanceid, LwM2mInstanceEnabler instance, ServerIdentity identity,
-            boolean observe) {
-        List<LwM2mResource> resources = new ArrayList<>();
-        for (ResourceModel resourceModel : getObjectModel().resources.values()) {
-            // check, if internal request (SYSTEM) or readable
-            if (identity.isSystem() || resourceModel.operations.isReadable()) {
-                if (observe) {
-                    ObserveResponse response = instance.observe(resourceModel.id);
-                    if (response.getCode() == ResponseCode.CONTENT && response.getContent() instanceof LwM2mResource)
-                        resources.add((LwM2mResource) response.getContent());
-                } else {
-                    ReadResponse response = instance.read(resourceModel.id);
-                    if (response.getCode() == ResponseCode.CONTENT && response.getContent() instanceof LwM2mResource)
-                        resources.add((LwM2mResource) response.getContent());
-                }
-            }
-        }
-        return new LwM2mObjectInstance(instanceid, resources);
+        return instance.observe(identity, path.getResourceId());
     }
 
     @Override
@@ -218,31 +201,11 @@ public class ObjectEnabler extends BaseObjectEnabler {
             return WriteResponse.notFound();
 
         if (path.isObjectInstance()) {
-            // instance write
-            Map<Integer, LwM2mResource> writeResources = ((LwM2mObjectInstance) request.getNode()).getResources();
-            if (request.isReplaceRequest()) {
-                // REPLACE
-                writeResources = new HashMap<>(writeResources); // make them modifiable
-                for (ResourceModel resourceModel : getObjectModel().resources.values()) {
-                    if (!identity.isLwm2mServer() || resourceModel.operations.isWritable()) {
-                        LwM2mResource writeResource = writeResources.remove(resourceModel.id);
-                        if (null != writeResource) {
-                            instance.write(resourceModel.id, writeResource);
-                        } else {
-                            instance.reset(resourceModel.id);
-                        }
-                    }
-                }
-            }
-            // UPDATE and resources currently not in the model
-            for (LwM2mResource resource : writeResources.values()) {
-                instance.write(resource.getId(), resource);
-            }
-            return WriteResponse.success();
+            return instance.write(identity, request.isReplaceRequest(), (LwM2mObjectInstance) request.getNode());
         }
 
         // Manage Resource case
-        return instance.write(path.getResourceId(), (LwM2mResource) request.getNode());
+        return instance.write(identity, path.getResourceId(), (LwM2mResource) request.getNode());
     }
 
     @Override
@@ -254,7 +217,7 @@ public class ObjectEnabler extends BaseObjectEnabler {
             for (LwM2mObjectInstance instanceNode : ((LwM2mObject) request.getNode()).getInstances().values()) {
                 LwM2mInstanceEnabler instanceEnabler = instances.get(instanceNode.getId());
                 if (instanceEnabler == null) {
-                    doCreate(new CreateRequest(path.getObjectId(), instanceNode));
+                    doCreate(identity, new CreateRequest(path.getObjectId(), instanceNode));
                 } else {
                     doWrite(identity, new WriteRequest(Mode.REPLACE, path.getObjectId(), path.getObjectInstanceId(),
                             instanceNode.getResources().values()));
@@ -268,7 +231,7 @@ public class ObjectEnabler extends BaseObjectEnabler {
             LwM2mObjectInstance instanceNode = (LwM2mObjectInstance) request.getNode();
             LwM2mInstanceEnabler instanceEnabler = instances.get(path.getObjectInstanceId());
             if (instanceEnabler == null) {
-                doCreate(new CreateRequest(path.getObjectId(), instanceNode));
+                doCreate(identity, new CreateRequest(path.getObjectId(), instanceNode));
             } else {
                 doWrite(identity, new WriteRequest(Mode.REPLACE, request.getContentFormat(), path.getObjectId(),
                         path.getObjectInstanceId(), instanceNode.getResources().values()));
@@ -280,26 +243,26 @@ public class ObjectEnabler extends BaseObjectEnabler {
         LwM2mResource resource = (LwM2mResource) request.getNode();
         LwM2mInstanceEnabler instanceEnabler = instances.get(path.getObjectInstanceId());
         if (instanceEnabler == null) {
-            doCreate(new CreateRequest(path.getObjectId(),
+            doCreate(identity, new CreateRequest(path.getObjectId(),
                     new LwM2mObjectInstance(path.getObjectInstanceId(), resource)));
         } else {
-            instanceEnabler.write(path.getResourceId(), resource);
+            instanceEnabler.write(identity, path.getResourceId(), resource);
         }
         return BootstrapWriteResponse.success();
     }
 
     @Override
-    protected ExecuteResponse doExecute(ExecuteRequest request) {
+    protected ExecuteResponse doExecute(ServerIdentity identity, ExecuteRequest request) {
         LwM2mPath path = request.getPath();
         LwM2mInstanceEnabler instance = instances.get(path.getObjectInstanceId());
         if (instance == null) {
             return ExecuteResponse.notFound();
         }
-        return instance.execute(path.getResourceId(), request.getParameters());
+        return instance.execute(identity, path.getResourceId(), request.getParameters());
     }
 
     @Override
-    protected DeleteResponse doDelete(DeleteRequest request) {
+    protected DeleteResponse doDelete(ServerIdentity identity, DeleteRequest request) {
         if (null != instances.remove(request.getPath().getObjectInstanceId())) {
             return DeleteResponse.success();
         }
@@ -307,7 +270,7 @@ public class ObjectEnabler extends BaseObjectEnabler {
     }
 
     @Override
-    public BootstrapDeleteResponse doDelete(BootstrapDeleteRequest request) {
+    public BootstrapDeleteResponse doDelete(ServerIdentity identity, BootstrapDeleteRequest request) {
         if (request.getPath().isRoot() || request.getPath().isObject()) {
             if (id == LwM2mId.SECURITY) {
                 // For security object, we clean everything except bootstrap Server account.
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/ObjectsInitializer.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/ObjectsInitializer.java
index 87960deb..621059b0 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/ObjectsInitializer.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/ObjectsInitializer.java
@@ -31,10 +31,8 @@ public class ObjectsInitializer {
 
     protected LwM2mInstanceEnablerFactory defaultFactory = new BaseInstanceEnablerFactory() {
         @Override
-        public LwM2mInstanceEnabler create(ObjectModel model) {
-            SimpleInstanceEnabler simpleInstanceEnabler = new SimpleInstanceEnabler();
-            simpleInstanceEnabler.setObjectModel(model);
-            return simpleInstanceEnabler;
+        public LwM2mInstanceEnabler create() {
+            return new SimpleInstanceEnabler();
         }
     };
 
@@ -167,6 +165,7 @@ public class ObjectsInitializer {
                 int id = BaseInstanceEnablerFactory.generateNewInstanceId(instances.keySet());
                 instance.setId(id);
             }
+            instance.setModel(objectModel);
             instances.put(instance.getId(), instance);
         }
         return new ObjectEnabler(objectModel.id, objectModel, instances, getFactoryFor(objectModel),
@@ -198,7 +197,7 @@ public class ObjectsInitializer {
     protected LwM2mInstanceEnablerFactory getClassFactory(final Class<? extends LwM2mInstanceEnabler> clazz) {
         LwM2mInstanceEnablerFactory factory = new BaseInstanceEnablerFactory() {
             @Override
-            public LwM2mInstanceEnabler create(ObjectModel model) {
+            public LwM2mInstanceEnabler create() {
                 try {
                     return clazz.newInstance();
                 } catch (InstantiationException | IllegalAccessException e) {
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/SimpleInstanceEnabler.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/SimpleInstanceEnabler.java
index b84a5392..c2857bb8 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/SimpleInstanceEnabler.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/resource/SimpleInstanceEnabler.java
@@ -22,6 +22,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.core.model.ObjectModel;
 import org.eclipse.leshan.core.model.ResourceModel;
 import org.eclipse.leshan.core.node.LwM2mMultipleResource;
@@ -37,7 +38,6 @@ public class SimpleInstanceEnabler extends BaseInstanceEnabler {
 
     private static Logger LOG = LoggerFactory.getLogger(SimpleInstanceEnabler.class);
     protected Map<Integer, LwM2mResource> resources = new HashMap<>();
-    protected ObjectModel objectModel;
 
     public SimpleInstanceEnabler() {
     }
@@ -47,7 +47,7 @@ public class SimpleInstanceEnabler extends BaseInstanceEnabler {
     }
 
     @Override
-    public ReadResponse read(int resourceid) {
+    public ReadResponse read(ServerIdentity identity, int resourceid) {
         if (resources.containsKey(resourceid)) {
             return ReadResponse.success(resources.get(resourceid));
         }
@@ -55,7 +55,7 @@ public class SimpleInstanceEnabler extends BaseInstanceEnabler {
     }
 
     @Override
-    public WriteResponse write(int resourceid, LwM2mResource value) {
+    public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
         LwM2mResource previousValue = resources.put(resourceid, value);
         if (!value.equals(previousValue))
             fireResourcesChange(resourceid);
@@ -63,8 +63,8 @@ public class SimpleInstanceEnabler extends BaseInstanceEnabler {
     }
 
     @Override
-    public ExecuteResponse execute(int resourceid, String params) {
-        if (objectModel.resources.containsKey(resourceid)) {
+    public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
+        if (getModel().resources.containsKey(resourceid)) {
             LOG.info("Executing resource [{}] with params [{}]", resourceid, params);
             return ExecuteResponse.success();
         } else {
@@ -77,8 +77,9 @@ public class SimpleInstanceEnabler extends BaseInstanceEnabler {
         resources.remove(resourceid);
     }
 
-    public void setObjectModel(ObjectModel objectModel) {
-        this.objectModel = objectModel;
+    @Override
+    public void setModel(ObjectModel objectModel) {
+        super.setModel(objectModel);
 
         // initialize resources
         for (ResourceModel resourceModel : objectModel.resources.values()) {
diff --git a/leshan-client-core/src/main/java/org/eclipse/leshan/client/servers/ServersInfoExtractor.java b/leshan-client-core/src/main/java/org/eclipse/leshan/client/servers/ServersInfoExtractor.java
index 03c0492c..0f8cb470 100644
--- a/leshan-client-core/src/main/java/org/eclipse/leshan/client/servers/ServersInfoExtractor.java
+++ b/leshan-client-core/src/main/java/org/eclipse/leshan/client/servers/ServersInfoExtractor.java
@@ -37,6 +37,7 @@ import java.util.Map;
 
 import org.eclipse.leshan.LwM2mId;
 import org.eclipse.leshan.SecurityMode;
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler;
 import org.eclipse.leshan.client.resource.LwM2mObjectEnabler;
 import org.eclipse.leshan.core.node.LwM2mObject;
@@ -231,7 +232,7 @@ public class ServersInfoExtractor {
     }
 
     public static boolean isBootstrapServer(LwM2mInstanceEnabler instance) {
-        ReadResponse response = instance.read(LwM2mId.SEC_BOOTSTRAP);
+        ReadResponse response = instance.read(ServerIdentity.SYSTEM, LwM2mId.SEC_BOOTSTRAP);
         if (response == null || response.isFailure()) {
             return false;
         }
diff --git a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/MyDevice.java b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/MyDevice.java
index 33c03b37..afdccabe 100644
--- a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/MyDevice.java
+++ b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/MyDevice.java
@@ -12,6 +12,7 @@ import java.util.TimeZone;
 import java.util.Timer;
 import java.util.TimerTask;
 
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
 import org.eclipse.leshan.core.model.ObjectModel;
 import org.eclipse.leshan.core.model.ResourceModel.Type;
@@ -42,7 +43,7 @@ public class MyDevice extends BaseInstanceEnabler {
     }
 
     @Override
-    public ReadResponse read(int resourceid) {
+    public ReadResponse read(ServerIdentity identity, int resourceid) {
         LOG.info("Read on Device Resource " + resourceid);
         switch (resourceid) {
         case 0:
@@ -80,12 +81,12 @@ public class MyDevice extends BaseInstanceEnabler {
         case 21:
             return ReadResponse.success(resourceid, getMemoryTotal());
         default:
-            return super.read(resourceid);
+            return super.read(identity, resourceid);
         }
     }
 
     @Override
-    public ExecuteResponse execute(int resourceid, String params) {
+    public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
         LOG.info("Execute on Device resource " + resourceid);
         if (params != null && params.length() != 0)
             System.out.println("\t params " + params);
@@ -93,7 +94,7 @@ public class MyDevice extends BaseInstanceEnabler {
     }
 
     @Override
-    public WriteResponse write(int resourceid, LwM2mResource value) {
+    public WriteResponse write(ServerIdentity identity, int resourceid, LwM2mResource value) {
         LOG.info("Write on Device Resource " + resourceid + " value " + value);
         switch (resourceid) {
         case 13:
@@ -107,7 +108,7 @@ public class MyDevice extends BaseInstanceEnabler {
             fireResourcesChange(resourceid);
             return WriteResponse.success();
         default:
-            return super.write(resourceid, value);
+            return super.write(identity, resourceid, value);
         }
     }
 
diff --git a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/MyLocation.java b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/MyLocation.java
index 27f0669f..58ca5dcb 100644
--- a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/MyLocation.java
+++ b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/MyLocation.java
@@ -5,6 +5,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Random;
 
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
 import org.eclipse.leshan.core.model.ObjectModel;
 import org.eclipse.leshan.core.response.ReadResponse;
@@ -43,7 +44,7 @@ public class MyLocation extends BaseInstanceEnabler {
     }
 
     @Override
-    public ReadResponse read(int resourceid) {
+    public ReadResponse read(ServerIdentity identity, int resourceid) {
         LOG.info("Read on Location Resource " + resourceid);
         switch (resourceid) {
         case 0:
@@ -53,7 +54,7 @@ public class MyLocation extends BaseInstanceEnabler {
         case 5:
             return ReadResponse.success(resourceid, getTimestamp());
         default:
-            return super.read(resourceid);
+            return super.read(identity, resourceid);
         }
     }
 
diff --git a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/RandomTemperatureSensor.java b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/RandomTemperatureSensor.java
index 1f847d96..308d6951 100644
--- a/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/RandomTemperatureSensor.java
+++ b/leshan-client-demo/src/main/java/org/eclipse/leshan/client/demo/RandomTemperatureSensor.java
@@ -9,6 +9,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.BaseInstanceEnabler;
 import org.eclipse.leshan.core.model.ObjectModel;
 import org.eclipse.leshan.core.response.ExecuteResponse;
@@ -43,7 +44,7 @@ public class RandomTemperatureSensor extends BaseInstanceEnabler {
     }
 
     @Override
-    public synchronized ReadResponse read(int resourceId) {
+    public synchronized ReadResponse read(ServerIdentity identity, int resourceId) {
         switch (resourceId) {
         case MIN_MEASURED_VALUE:
             return ReadResponse.success(resourceId, getTwoDigitValue(minMeasuredValue));
@@ -54,18 +55,18 @@ public class RandomTemperatureSensor extends BaseInstanceEnabler {
         case UNITS:
             return ReadResponse.success(resourceId, UNIT_CELSIUS);
         default:
-            return super.read(resourceId);
+            return super.read(identity, resourceId);
         }
     }
 
     @Override
-    public synchronized ExecuteResponse execute(int resourceId, String params) {
+    public synchronized ExecuteResponse execute(ServerIdentity identity, int resourceId, String params) {
         switch (resourceId) {
         case RESET_MIN_MAX_MEASURED_VALUES:
             resetMinMaxMeasuredValues();
             return ExecuteResponse.success();
         default:
-            return super.execute(resourceId, params);
+            return super.execute(identity, resourceId, params);
         }
     }
 


Test patch:
diff --git a/leshan-client-core/src/test/java/org/eclipse/leshan/client/util/BaseInstanceEnablerFactoryTest.java b/leshan-client-core/src/test/java/org/eclipse/leshan/client/util/BaseInstanceEnablerFactoryTest.java
index dbffdb64..44d1c79e 100644
--- a/leshan-client-core/src/test/java/org/eclipse/leshan/client/util/BaseInstanceEnablerFactoryTest.java
+++ b/leshan-client-core/src/test/java/org/eclipse/leshan/client/util/BaseInstanceEnablerFactoryTest.java
@@ -27,7 +27,6 @@ import org.eclipse.leshan.client.resource.LwM2mInstanceEnabler;
 import org.eclipse.leshan.client.resource.SimpleInstanceEnabler;
 import org.eclipse.leshan.core.model.LwM2mModel;
 import org.eclipse.leshan.core.model.ObjectLoader;
-import org.eclipse.leshan.core.model.ObjectModel;
 import org.junit.Test;
 
 public class BaseInstanceEnablerFactoryTest {
@@ -42,7 +41,7 @@ public class BaseInstanceEnablerFactoryTest {
         BaseInstanceEnablerFactory badInstanceEnablerFactory = new BaseInstanceEnablerFactory() {
 
             @Override
-            public LwM2mInstanceEnabler create(ObjectModel model) {
+            public LwM2mInstanceEnabler create() {
                 // do no respect the contract and set a bad id;
                 return new SimpleInstanceEnabler(id + 1);
             }
@@ -56,7 +55,7 @@ public class BaseInstanceEnablerFactoryTest {
         BaseInstanceEnablerFactory instanceEnablerFactory = new BaseInstanceEnablerFactory() {
 
             @Override
-            public LwM2mInstanceEnabler create(ObjectModel model) {
+            public LwM2mInstanceEnabler create() {
                 return new SimpleInstanceEnabler();
             }
         };
diff --git a/leshan-client-core/src/test/java/org/eclipse/leshan/client/util/LinkFormatHelperTest.java b/leshan-client-core/src/test/java/org/eclipse/leshan/client/util/LinkFormatHelperTest.java
index c0128c48..1b85bf56 100644
--- a/leshan-client-core/src/test/java/org/eclipse/leshan/client/util/LinkFormatHelperTest.java
+++ b/leshan-client-core/src/test/java/org/eclipse/leshan/client/util/LinkFormatHelperTest.java
@@ -174,17 +174,16 @@ public class LinkFormatHelperTest {
         // create factory
         BaseInstanceEnablerFactory factory = new BaseInstanceEnablerFactory() {
             @Override
-            public LwM2mInstanceEnabler create(ObjectModel model) {
-                SimpleInstanceEnabler simpleInstanceEnabler = new SimpleInstanceEnabler();
-                simpleInstanceEnabler.setObjectModel(model);
-                return simpleInstanceEnabler;
+            public LwM2mInstanceEnabler create() {
+                return new SimpleInstanceEnabler();
             }
         };
 
         // create first instance
         Map<Integer, LwM2mInstanceEnabler> instances = new HashMap<>();
-        LwM2mInstanceEnabler instance = factory.create(objectModel);
+        LwM2mInstanceEnabler instance = factory.create();
         instance.setId(0);
+        instance.setModel(objectModel);
         instances.put(0, instance);
 
         // create objectEnabler
diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/IntegrationTestHelper.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/IntegrationTestHelper.java
index badd0a14..200a2b80 100644
--- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/IntegrationTestHelper.java
+++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/IntegrationTestHelper.java
@@ -33,6 +33,7 @@ import org.eclipse.leshan.client.californium.LeshanClientBuilder;
 import org.eclipse.leshan.client.object.Device;
 import org.eclipse.leshan.client.object.Security;
 import org.eclipse.leshan.client.object.Server;
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.LwM2mObjectEnabler;
 import org.eclipse.leshan.client.resource.ObjectsInitializer;
 import org.eclipse.leshan.core.model.LwM2mModel;
@@ -130,11 +131,11 @@ public class IntegrationTestHelper {
         initializer.setInstancesForObject(LwM2mId.SERVER, new Server(12345, LIFETIME, BindingMode.U, false));
         initializer.setInstancesForObject(LwM2mId.DEVICE, new Device("Eclipse Leshan", MODEL_NUMBER, "12345", "U") {
             @Override
-            public ExecuteResponse execute(int resourceid, String params) {
+            public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
                 if (resourceid == 4) {
                     return ExecuteResponse.success();
                 } else {
-                    return super.execute(resourceid, params);
+                    return super.execute(identity, resourceid, params);
                 }
             }
         });
diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/QueueModeIntegrationTestHelper.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/QueueModeIntegrationTestHelper.java
index 5172df4e..d05ba0a9 100644
--- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/QueueModeIntegrationTestHelper.java
+++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/QueueModeIntegrationTestHelper.java
@@ -27,6 +27,7 @@ import org.eclipse.leshan.client.californium.LeshanClientBuilder;
 import org.eclipse.leshan.client.object.Device;
 import org.eclipse.leshan.client.object.Security;
 import org.eclipse.leshan.client.object.Server;
+import org.eclipse.leshan.client.request.ServerIdentity;
 import org.eclipse.leshan.client.resource.LwM2mObjectEnabler;
 import org.eclipse.leshan.client.resource.ObjectsInitializer;
 import org.eclipse.leshan.core.model.LwM2mModel;
@@ -69,11 +70,11 @@ public class QueueModeIntegrationTestHelper extends IntegrationTestHelper {
         initializer.setInstancesForObject(LwM2mId.SERVER, new Server(12345, LIFETIME, BindingMode.UQ, false));
         initializer.setInstancesForObject(LwM2mId.DEVICE, new Device("Eclipse Leshan", MODEL_NUMBER, "12345", "UQ") {
             @Override
-            public ExecuteResponse execute(int resourceid, String params) {
+            public ExecuteResponse execute(ServerIdentity identity, int resourceid, String params) {
                 if (resourceid == 4) {
                     return ExecuteResponse.success();
                 } else {
-                    return super.execute(resourceid, params);
+                    return super.execute(identity, resourceid, params);
                 }
             }
         });