Repository: eclipse/leshan
Pull request #241 (2017-01-11 16:26:58)

raise InvalidRequestException when request parameters are not valid.
I add a new InvalidRequestException which is raised when we try to create a LWM2M request with invalid parameters.

This exception is catched in coapResource to return `bad request` instead of `internal server error`.

(I also clean a bit this part of the code)


Patch:
diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/CoapClientRequestBuilder.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/CoapClientRequestBuilder.java
index e3f3d275..f07fe247 100644
--- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/CoapClientRequestBuilder.java
+++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/CoapClientRequestBuilder.java
@@ -113,7 +113,7 @@ public class CoapClientRequestBuilder implements UplinkRequestVisitor {
     public void visit(final DeregisterRequest request) {
         coapRequest = Request.newDelete();
         buildRequestSettings();
-        coapRequest.getOptions().setUriPath(request.getRegistrationID());
+        coapRequest.getOptions().setUriPath(request.getRegistrationId());
     }
 
     public Request getRequest() {
diff --git a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/ObjectResource.java b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/ObjectResource.java
index 6dd106b8..0b149202 100644
--- a/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/ObjectResource.java
+++ b/leshan-client-cf/src/main/java/org/eclipse/leshan/client/californium/impl/ObjectResource.java
@@ -55,6 +55,7 @@ import org.eclipse.leshan.core.request.ReadRequest;
 import org.eclipse.leshan.core.request.WriteAttributesRequest;
 import org.eclipse.leshan.core.request.WriteRequest;
 import org.eclipse.leshan.core.request.WriteRequest.Mode;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.BootstrapWriteResponse;
 import org.eclipse.leshan.core.response.CreateResponse;
 import org.eclipse.leshan.core.response.DeleteResponse;
@@ -94,8 +95,17 @@ public class ObjectResource extends CoapResource implements NotifySender {
     public void handleRequest(Exchange exchange) {
         try {
             super.handleRequest(exchange);
+        } catch (InvalidRequestException e) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug(String.format("InvalidRequestException while handling request(%s) on the %s resource",
+                        exchange.getRequest(), getURI()), e);
+            }
+            Response response = new Response(ResponseCode.BAD_REQUEST);
+            response.setPayload(e.getMessage());
+            exchange.sendResponse(response);
         } catch (Exception e) {
-            LOG.error(String.format("Exception while handling a request on the %s resource", getURI()), e);
+            LOG.error(String.format("Exception while handling request(%s) on the %s resource", exchange.getRequest(),
+                    getURI()), e);
             exchange.sendResponse(new Response(ResponseCode.INTERNAL_SERVER_ERROR));
         }
     }
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/LinkObject.java b/leshan-core/src/main/java/org/eclipse/leshan/LinkObject.java
index 7d060195..2de6f723 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/LinkObject.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/LinkObject.java
@@ -100,6 +100,9 @@ public class LinkObject implements Serializable {
     }
 
     public static LinkObject[] parse(byte[] content) {
+        if (content == null) {
+            return new LinkObject[] {};
+        }
         String s = new String(content, Charsets.UTF_8);
         String[] links = s.split(",");
         LinkObject[] linksResult = new LinkObject[links.length];
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/AbstractDownlinkRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/AbstractDownlinkRequest.java
index ba658156..9114976d 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/AbstractDownlinkRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/AbstractDownlinkRequest.java
@@ -16,8 +16,8 @@
 package org.eclipse.leshan.core.request;
 
 import org.eclipse.leshan.core.node.LwM2mPath;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.LwM2mResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * A base class for concrete LWM2M Downlink request types.
@@ -28,15 +28,17 @@ public abstract class AbstractDownlinkRequest<T extends LwM2mResponse> implement
 
     private final LwM2mPath path;
 
-    protected AbstractDownlinkRequest(final LwM2mPath path) {
-        Validate.notNull(path);
-        if (path.isRoot()) {
-            throw new IllegalArgumentException("downlink request cannot target root path: " + path.toString());
-        }
-        if (path.isResourceInstance()) {
-            throw new IllegalArgumentException(
+    protected AbstractDownlinkRequest(LwM2mPath path) {
+        if (path == null)
+            throw new InvalidRequestException("path is mandatory");
+
+        if (path.isRoot())
+            throw new InvalidRequestException("downlink request cannot target root path: " + path.toString());
+
+        if (path.isResourceInstance())
+            throw new InvalidRequestException(
                     "downlink request cannot target resource instance path: " + path.toString());
-        }
+
         this.path = path;
     }
 
@@ -73,4 +75,12 @@ public abstract class AbstractDownlinkRequest<T extends LwM2mResponse> implement
         return true;
     }
 
+    protected static LwM2mPath newPath(String path) {
+        try {
+            return new LwM2mPath(path);
+        } catch (IllegalArgumentException e) {
+            throw new InvalidRequestException();
+        }
+    }
+
 }
\ No newline at end of file
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/BootstrapRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/BootstrapRequest.java
index 5e267ab4..1f70f5b7 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/BootstrapRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/BootstrapRequest.java
@@ -15,8 +15,8 @@
  *******************************************************************************/
 package org.eclipse.leshan.core.request;
 
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.BootstrapResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * The request to send to start a bootstrap session
@@ -25,8 +25,10 @@ public class BootstrapRequest implements UplinkRequest<BootstrapResponse> {
 
     private final String endpointName;
 
-    public BootstrapRequest(String endpointName) {
-        Validate.notEmpty(endpointName);
+    public BootstrapRequest(String endpointName) throws InvalidRequestException {
+        if (endpointName == null || endpointName.isEmpty())
+            throw new InvalidRequestException("endpoint is mandatory");
+
         this.endpointName = endpointName;
     }
 
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/BootstrapWriteRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/BootstrapWriteRequest.java
index 468991c3..a2475b37 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/BootstrapWriteRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/BootstrapWriteRequest.java
@@ -21,8 +21,8 @@ import org.eclipse.leshan.core.node.LwM2mObject;
 import org.eclipse.leshan.core.node.LwM2mObjectInstance;
 import org.eclipse.leshan.core.node.LwM2mPath;
 import org.eclipse.leshan.core.node.LwM2mResource;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.BootstrapWriteResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * A LWM2M request for writing object instances during the bootstrap phase.
@@ -32,24 +32,26 @@ public class BootstrapWriteRequest extends AbstractDownlinkRequest<BootstrapWrit
     private final LwM2mNode node;
     private final ContentFormat contentFormat;
 
-    public BootstrapWriteRequest(final LwM2mPath target, final LwM2mNode node, ContentFormat format) {
+    public BootstrapWriteRequest(LwM2mPath target, LwM2mNode node, ContentFormat format)
+            throws InvalidRequestException {
         super(target);
-        Validate.notNull(node);
+        if (node == null)
+            throw new InvalidRequestException("new node value is mandatory");
 
         // Validate node and path coherence
         if (getPath().isResource()) {
             if (!(node instanceof LwM2mResource)) {
-                throw new IllegalArgumentException(String.format("path '%s' and node type '%s' does not match",
+                throw new InvalidRequestException(String.format("path '%s' and node type '%s' does not match",
                         target.toString(), node.getClass().getSimpleName()));
             }
         } else if (getPath().isObjectInstance()) {
             if (!(node instanceof LwM2mObjectInstance)) {
-                throw new IllegalArgumentException(String.format("path '%s' and node type '%s' does not match",
+                throw new InvalidRequestException(String.format("path '%s' and node type '%s' does not match",
                         target.toString(), node.getClass().getSimpleName()));
             }
         } else if (getPath().isObject()) {
             if (!(node instanceof LwM2mObject)) {
-                throw new IllegalArgumentException(String.format("path '%s' and node type '%s' does not match",
+                throw new InvalidRequestException(String.format("path '%s' and node type '%s' does not match",
                         target.toString(), node.getClass().getSimpleName()));
             }
         }
@@ -57,19 +59,19 @@ public class BootstrapWriteRequest extends AbstractDownlinkRequest<BootstrapWrit
         // Validate content format
         if (ContentFormat.TEXT == format || ContentFormat.OPAQUE == format) {
             if (!getPath().isResource()) {
-                throw new IllegalArgumentException(
+                throw new InvalidRequestException(
                         String.format("%s format must be used only for single resources", format.toString()));
             } else {
                 LwM2mResource resource = (LwM2mResource) node;
                 if (resource.isMultiInstances()) {
-                    throw new IllegalArgumentException(
+                    throw new InvalidRequestException(
                             String.format("%s format must be used only for single resources", format.toString()));
                 } else {
                     if (resource.getType() == Type.OPAQUE && format == ContentFormat.TEXT) {
-                        throw new IllegalArgumentException(
+                        throw new InvalidRequestException(
                                 "TEXT format must not be used for byte array single resources");
                     } else if (resource.getType() != Type.OPAQUE && format == ContentFormat.OPAQUE) {
-                        throw new IllegalArgumentException(
+                        throw new InvalidRequestException(
                                 "OPAQUE format must be used only for byte array single resources");
                     }
                 }
@@ -93,7 +95,7 @@ public class BootstrapWriteRequest extends AbstractDownlinkRequest<BootstrapWrit
     }
 
     @Override
-    public void accept(final DownlinkRequestVisitor visitor) {
+    public void accept(DownlinkRequestVisitor visitor) {
         visitor.visit(this);
     }
 
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/CreateRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/CreateRequest.java
index fa889272..bbd69832 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/CreateRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/CreateRequest.java
@@ -23,8 +23,8 @@ import java.util.List;
 import org.eclipse.leshan.core.node.LwM2mObjectInstance;
 import org.eclipse.leshan.core.node.LwM2mPath;
 import org.eclipse.leshan.core.node.LwM2mResource;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.CreateResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * A Lightweight M2M request for creating Object Instance(s) within the LWM2M Client.
@@ -44,8 +44,10 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * @param contentFormat the payload format
      * @param objectId the object id
      * @param resources the resource values for the new instance
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public CreateRequest(ContentFormat contentFormat, int objectId, LwM2mResource... resources) {
+    public CreateRequest(ContentFormat contentFormat, int objectId, LwM2mResource... resources)
+            throws InvalidRequestException {
         this(contentFormat, new LwM2mPath(objectId), null, resources);
     }
 
@@ -67,8 +69,10 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * @param contentFormat the payload format
      * @param objectId the object id
      * @param resources the resource values for the new instance
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public CreateRequest(ContentFormat contentFormat, int objectId, Collection<LwM2mResource> resources) {
+    public CreateRequest(ContentFormat contentFormat, int objectId, Collection<LwM2mResource> resources)
+            throws InvalidRequestException {
         this(contentFormat, objectId, resources.toArray(new LwM2mResource[resources.size()]));
     }
 
@@ -91,8 +95,10 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * @param contentFormat the payload format
      * @param objectId the object id
      * @param instance the object instance
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public CreateRequest(ContentFormat contentFormat, int objectId, LwM2mObjectInstance instance) {
+    public CreateRequest(ContentFormat contentFormat, int objectId, LwM2mObjectInstance instance)
+            throws InvalidRequestException {
         this(contentFormat, new LwM2mPath(objectId), instance.getId(),
                 instance.getResources().values().toArray(new LwM2mResource[0]));
     }
@@ -115,8 +121,9 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * 
      * @param path the target path (object or object instance)
      * @param resources the resource values for the new instance
+     * @exception InvalidRequestException if the target path is not valid.
      */
-    public CreateRequest(String path, Collection<LwM2mResource> resources) {
+    public CreateRequest(String path, Collection<LwM2mResource> resources) throws InvalidRequestException {
         this(path, resources.toArray(new LwM2mResource[resources.size()]));
     }
 
@@ -128,8 +135,10 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * @param contentFormat the payload format (TLV or JSON)
      * @param path the target path (object or object instance)
      * @param resources the resource values for the new instance
+     * @exception InvalidRequestException if parameters are invalid.
      */
-    public CreateRequest(ContentFormat contentFormat, String path, Collection<LwM2mResource> resources) {
+    public CreateRequest(ContentFormat contentFormat, String path, Collection<LwM2mResource> resources)
+            throws InvalidRequestException {
         this(contentFormat, path, resources.toArray(new LwM2mResource[resources.size()]));
     }
 
@@ -140,9 +149,10 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * 
      * @param path the target path (object or object instance)
      * @param resources the resource values for the new instance
+     * @exception InvalidRequestException if the target path is not valid.
      */
-    public CreateRequest(String path, LwM2mResource... resources) {
-        this(null, new LwM2mPath(path), null, resources);
+    public CreateRequest(String path, LwM2mResource... resources) throws InvalidRequestException {
+        this(null, newPath(path), null, resources);
     }
 
     /**
@@ -153,9 +163,11 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * @param contentFormat the payload format (TLV or JSON)
      * @param path the target path (object or object instance)
      * @param resources the resource values for the new instance
+     * @exception InvalidRequestException if parameters are invalid.
      */
-    public CreateRequest(ContentFormat contentFormat, String path, LwM2mResource... resources) {
-        this(contentFormat, new LwM2mPath(path), null, resources);
+    public CreateRequest(ContentFormat contentFormat, String path, LwM2mResource... resources)
+            throws InvalidRequestException {
+        this(contentFormat, newPath(path), null, resources);
     }
 
     /**
@@ -165,9 +177,10 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * 
      * @param path the target path (object or object instance)
      * @param instance the object instance
+     * @exception InvalidRequestException if the target path is not valid.
      */
-    public CreateRequest(String path, LwM2mObjectInstance instance) {
-        this(null, new LwM2mPath(path), instance.getId(),
+    public CreateRequest(String path, LwM2mObjectInstance instance) throws InvalidRequestException {
+        this(null, newPath(path), instance.getId(),
                 instance.getResources().values().toArray((new LwM2mResource[instance.getResources().size()])));
     }
 
@@ -179,9 +192,11 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
      * @param contentFormat the payload format (TLV or JSON)
      * @param path the target path (object or object instance)
      * @param instance the object instance
+     * @exception InvalidRequestException if parameters are invalid.
      */
-    public CreateRequest(ContentFormat contentFormat, String path, LwM2mObjectInstance instance) {
-        this(contentFormat, new LwM2mPath(path), instance.getId(),
+    public CreateRequest(ContentFormat contentFormat, String path, LwM2mObjectInstance instance)
+            throws InvalidRequestException {
+        this(contentFormat, newPath(path), instance.getId(),
                 instance.getResources().values().toArray((new LwM2mResource[instance.getResources().size()])));
     }
 
@@ -190,9 +205,8 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
         super(target);
 
         // accept only object and object instance path
-        if (!target.isObject() && !target.isObjectInstance()) {
-            throw new IllegalArgumentException("Create request must target an object or object instance");
-        }
+        if (!target.isObject() && !target.isObjectInstance())
+            throw new InvalidRequestException("Create request must target an object or object instance");
 
         // validate instance id
         if (instanceId != null && instanceId == LwM2mObjectInstance.UNDEFINED) {
@@ -203,11 +217,12 @@ public class CreateRequest extends AbstractDownlinkRequest<CreateResponse> {
                 instanceId = target.getObjectInstanceId();
             } else {
                 if (instanceId != target.getObjectInstanceId()) {
-                    throw new IllegalArgumentException("Conflict between path instance id and node instance id");
+                    throw new InvalidRequestException("Conflict between path instance id and node instance id");
                 }
             }
         }
-        Validate.isTrue(instanceId == null || instanceId >= 0, "Invalid instance id: " + instanceId);
+        if (instanceId != null && instanceId < 0)
+            throw new InvalidRequestException("Invalid instance id: " + instanceId);
 
         // store attributes
         this.instanceId = instanceId;
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/DeleteRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/DeleteRequest.java
index d3346ba7..12de3c2f 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/DeleteRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/DeleteRequest.java
@@ -16,8 +16,8 @@
 package org.eclipse.leshan.core.request;
 
 import org.eclipse.leshan.core.node.LwM2mPath;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.DeleteResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * A Lightweight M2M request for deleting an Object Instance within the LWM2M Client.
@@ -30,7 +30,7 @@ public class DeleteRequest extends AbstractDownlinkRequest<DeleteResponse> {
      * @param objectId the object type
      * @param objectInstanceId the object instance
      */
-    public DeleteRequest(final int objectId, final int objectInstanceId) {
+    public DeleteRequest(int objectId, int objectInstanceId) {
         this(new LwM2mPath(objectId, objectInstanceId));
     }
 
@@ -38,19 +38,20 @@ public class DeleteRequest extends AbstractDownlinkRequest<DeleteResponse> {
      * Creates a request for deleting a particular object instance implemented by a client.
      *
      * @param path the path of the instance to delete
-     * @throw IllegalArgumentException if the path is not valid
+     * @exception InvalidRequestException if the path is not valid.
      */
-    public DeleteRequest(final String path) {
-        super(new LwM2mPath(path));
+    public DeleteRequest(String path) throws InvalidRequestException {
+        super(newPath(path));
     }
 
-    private DeleteRequest(final LwM2mPath target) {
+    private DeleteRequest(LwM2mPath target) {
         super(target);
-        Validate.isTrue(target.isObjectInstance(), "Only object instance can be delete.");
+        if (!target.isObjectInstance())
+            throw new InvalidRequestException("Only object instance can be delete.");
     }
 
     @Override
-    public void accept(final DownlinkRequestVisitor visitor) {
+    public void accept(DownlinkRequestVisitor visitor) {
         visitor.visit(this);
     }
 
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/DeregisterRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/DeregisterRequest.java
index 861766e0..7e884b96 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/DeregisterRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/DeregisterRequest.java
@@ -15,28 +15,31 @@
  *******************************************************************************/
 package org.eclipse.leshan.core.request;
 
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.DeregisterResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * A Lightweight M2M request for removing the registration information from the LWM2M Server.
  */
 public class DeregisterRequest implements UplinkRequest<DeregisterResponse> {
 
-    private String registrationID = null;
+    private String registrationId = null;
 
     /**
      * Creates a request for removing the registration information from the LWM2M Server.
-     *
-     * @param registrationID the registration ID to remove
+     * 
+     * @param registrationId the registration Id to remove
+     * @exception InvalidRequestException if registrationId is empty.
      */
-    public DeregisterRequest(String registrationID) {
-        Validate.notNull(registrationID);
-        this.registrationID = registrationID;
+    public DeregisterRequest(String registrationId) throws InvalidRequestException {
+        if (registrationId == null || registrationId.isEmpty())
+            throw new InvalidRequestException("registrationId is mandatory");
+
+        this.registrationId = registrationId;
     }
 
-    public String getRegistrationID() {
-        return registrationID;
+    public String getRegistrationId() {
+        return registrationId;
     }
 
     @Override
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/DiscoverRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/DiscoverRequest.java
index 31eb411b..49d5f07d 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/DiscoverRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/DiscoverRequest.java
@@ -16,6 +16,7 @@
 package org.eclipse.leshan.core.request;
 
 import org.eclipse.leshan.core.node.LwM2mPath;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.DiscoverResponse;
 
 /**
@@ -58,10 +59,10 @@ public class DiscoverRequest extends AbstractDownlinkRequest<DiscoverResponse> {
      * path.
      *
      * @param path the path of the LWM2M node to discover
-     * @throw IllegalArgumentException if the path is not valid
+     * @exception InvalidRequestException if the path is not valid.
      */
-    public DiscoverRequest(String path) {
-        super(new LwM2mPath(path));
+    public DiscoverRequest(String path) throws InvalidRequestException {
+        super(newPath(path));
     }
 
     private DiscoverRequest(LwM2mPath target) {
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/ExecuteRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/ExecuteRequest.java
index ae02348c..8c525b43 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/ExecuteRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/ExecuteRequest.java
@@ -16,8 +16,8 @@
 package org.eclipse.leshan.core.request;
 
 import org.eclipse.leshan.core.node.LwM2mPath;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.ExecuteResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * A Lightweight M2M request for initiate some action, it can only be performed on individual Resources.
@@ -30,10 +30,10 @@ public class ExecuteRequest extends AbstractDownlinkRequest<ExecuteResponse> {
      * Creates a new <em>execute</em> request for a resource that does not require any parameters.
      *
      * @param path the path of the resource to execute
-     * @throw IllegalArgumentException if the path is not valid
+     * @exception InvalidRequestException if the path is not valid.
      */
-    public ExecuteRequest(final String path) {
-        this(new LwM2mPath(path), null);
+    public ExecuteRequest(String path) throws InvalidRequestException {
+        this(newPath(path), null);
     }
 
     /**
@@ -41,10 +41,10 @@ public class ExecuteRequest extends AbstractDownlinkRequest<ExecuteResponse> {
      *
      * @param path the path of the resource to execute
      * @param parameters the parameters
-     * @throw IllegalArgumentException if the path is not valid
+     * @exception InvalidRequestException if the path is not valid.
      */
-    public ExecuteRequest(final String path, final String parameters) {
-        this(new LwM2mPath(path), parameters);
+    public ExecuteRequest(String path, String parameters) throws InvalidRequestException {
+        this(newPath(path), parameters);
     }
 
     /**
@@ -54,7 +54,7 @@ public class ExecuteRequest extends AbstractDownlinkRequest<ExecuteResponse> {
      * @param objectInstanceId the resource's object instance ID
      * @param resourceId the resource's ID
      */
-    public ExecuteRequest(final int objectId, final int objectInstanceId, final int resourceId) {
+    public ExecuteRequest(int objectId, int objectInstanceId, int resourceId) {
         this(new LwM2mPath(objectId, objectInstanceId, resourceId), null);
     }
 
@@ -66,14 +66,14 @@ public class ExecuteRequest extends AbstractDownlinkRequest<ExecuteResponse> {
      * @param resourceId the resource's ID
      * @param parameters the parameters
      */
-    public ExecuteRequest(final int objectId, final int objectInstanceId, final int resourceId,
-            final String parameters) {
+    public ExecuteRequest(int objectId, int objectInstanceId, int resourceId, String parameters) {
         this(new LwM2mPath(objectId, objectInstanceId, resourceId), parameters);
     }
 
-    private ExecuteRequest(final LwM2mPath path, final String parameters) {
+    private ExecuteRequest(LwM2mPath path, String parameters) {
         super(path);
-        Validate.isTrue(path.isResource(), "Only resource can be executed.");
+        if (!path.isResource())
+            throw new InvalidRequestException("Only resource can be executed.");
         this.parameters = parameters;
     }
 
@@ -83,7 +83,7 @@ public class ExecuteRequest extends AbstractDownlinkRequest<ExecuteResponse> {
     }
 
     @Override
-    public void accept(final DownlinkRequestVisitor visitor) {
+    public void accept(DownlinkRequestVisitor visitor) {
         visitor.visit(this);
     }
 
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/ObserveRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/ObserveRequest.java
index ea08e8e8..da584d71 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/ObserveRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/ObserveRequest.java
@@ -20,6 +20,7 @@ import java.util.Map;
 
 import org.eclipse.leshan.core.node.LwM2mPath;
 import org.eclipse.leshan.core.observation.Observation;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.ObserveResponse;
 
 /**
@@ -100,10 +101,10 @@ public class ObserveRequest extends AbstractDownlinkRequest<ObserveResponse> {
      * Creates a request for observing future changes of a particular LWM2M node (object, object instance or resource).
      * 
      * @param path the path to the LWM2M node to observe
-     * @throw IllegalArgumentException if the path is not valid
+     * @exception InvalidRequestException if the path is not valid.
      */
-    public ObserveRequest(String path) {
-        this(null, new LwM2mPath(path), null);
+    public ObserveRequest(String path) throws InvalidRequestException {
+        this(null, newPath(path), null);
     }
 
     /**
@@ -111,10 +112,10 @@ public class ObserveRequest extends AbstractDownlinkRequest<ObserveResponse> {
      * 
      * @param format the desired format for the response
      * @param path the path to the LWM2M node to observe
-     * @throw IllegalArgumentException if the path is not valid
+     * @exception InvalidRequestException if the path is not valid.
      */
-    public ObserveRequest(ContentFormat format, String path) {
-        this(format, new LwM2mPath(path), null);
+    public ObserveRequest(ContentFormat format, String path) throws InvalidRequestException {
+        this(format, newPath(path), null);
     }
 
     /**
@@ -124,10 +125,11 @@ public class ObserveRequest extends AbstractDownlinkRequest<ObserveResponse> {
      * @param path the path to the LWM2M node to observe
      * @param context additional information about the request. This context will be available via the
      *        {@link Observation} once established.
-     * @throw IllegalArgumentException if the path is not valid
+     * @exception InvalidRequestException if the path is not valid.
      */
-    public ObserveRequest(ContentFormat format, String path, Map<String, String> context) {
-        this(format, new LwM2mPath(path), context);
+    public ObserveRequest(ContentFormat format, String path, Map<String, String> context)
+            throws InvalidRequestException {
+        this(format, newPath(path), context);
     }
 
     private ObserveRequest(ContentFormat format, LwM2mPath target, Map<String, String> context) {
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/ReadRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/ReadRequest.java
index ceabe2ab..932f677d 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/ReadRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/ReadRequest.java
@@ -16,6 +16,7 @@
 package org.eclipse.leshan.core.request;
 
 import org.eclipse.leshan.core.node.LwM2mPath;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.ReadResponse;
 
 /**
@@ -95,10 +96,10 @@ public class ReadRequest extends AbstractDownlinkRequest<ReadResponse> {
      * Create a request for reading an object/instance/resource targeted by a specific path.
      * 
      * @param path the path to the LWM2M node to read
-     * @throws IllegalArgumentException if the target path is not valid
+     * @exception InvalidRequestException if the target path is not valid.
      */
-    public ReadRequest(String path) {
-        this(null, new LwM2mPath(path));
+    public ReadRequest(String path) throws InvalidRequestException {
+        this(null, newPath(path));
     }
 
     /**
@@ -106,10 +107,10 @@ public class ReadRequest extends AbstractDownlinkRequest<ReadResponse> {
      *
      * @param format the desired format for the response
      * @param path the path to the LWM2M node to read
-     * @throws IllegalArgumentException if the target path is not valid
+     * @exception InvalidRequestException if the target path is not valid.
      */
-    public ReadRequest(ContentFormat format, String path) {
-        this(format, new LwM2mPath(path));
+    public ReadRequest(ContentFormat format, String path) throws InvalidRequestException {
+        this(format, newPath(path));
     }
 
     private ReadRequest(ContentFormat format, LwM2mPath target) {
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/RegisterRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/RegisterRequest.java
index d859b988..b6e338b0 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/RegisterRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/RegisterRequest.java
@@ -20,8 +20,8 @@ import java.util.HashMap;
 import java.util.Map;
 
 import org.eclipse.leshan.LinkObject;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.RegisterResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * A Lightweight M2M request for sending the LWM2M Client properties required by the LWM2M Server to contact the LWM2M
@@ -37,11 +37,29 @@ public class RegisterRequest implements UplinkRequest<RegisterResponse> {
     private final LinkObject[] objectLinks;
     private final Map<String, String> additionalAttributes;
 
+    /**
+     * Creates a request for registering a LWM2M client to a LWM2M Server.
+     * 
+     * @param endpointName is the LWM2M client identifier.
+     * @param lifetime specifies the lifetime of the registration in seconds.
+     * @param lwVersion indicates the version of the LWM2M Enabler that the LWM2M Client supports.
+     * @param bindingMode indicates current {@link BindingMode} of the LWM2M Client.
+     * @param smsNumber is the MSISDN where the LWM2M Client can be reached for use with the SMS binding.
+     * @param objectLinks is the list of Objects supported and Object Instances available on the LWM2M Client.
+     * @param additionalAttributes are any attributes/parameters which is out of the LWM2M specification.
+     * @exception InvalidRequestException if endpoint name or objectlinks is empty.
+     */
     public RegisterRequest(String endpointName, Long lifetime, String lwVersion, BindingMode bindingMode,
-            String smsNumber, LinkObject[] objectLinks, Map<String, String> additionalAttributes) {
+            String smsNumber, LinkObject[] objectLinks, Map<String, String> additionalAttributes)
+            throws InvalidRequestException {
+
+        if (endpointName == null || endpointName.isEmpty())
+            throw new InvalidRequestException("endpoint is mandatory");
+
+        if (objectLinks == null || objectLinks.length == 0)
+            throw new InvalidRequestException(
+                    "supported object list is mandatory and mandatory objects should be present)");
 
-        Validate.notNull(endpointName);
-        Validate.noNullElements(objectLinks);
 
         this.endpointName = endpointName;
         this.lifetime = lifetime;
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/UpdateRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/UpdateRequest.java
index 8006ac98..7bff78e5 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/UpdateRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/UpdateRequest.java
@@ -16,8 +16,8 @@
 package org.eclipse.leshan.core.request;
 
 import org.eclipse.leshan.LinkObject;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.UpdateResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * A Lightweight M2M request for updating the LWM2M Client properties required by the LWM2M Server to contact the LWM2M
@@ -39,12 +39,14 @@ public class UpdateRequest implements UplinkRequest<UpdateResponse> {
      * @param smsNumber the SMS number the client can receive messages under
      * @param binding the binding mode(s) the client supports
      * @param objectLinks the objects and object instances the client hosts/supports
-     * @throws NullPointerException if the registration ID is <code>null</code>
+     * @exception InvalidRequestException if the registrationId is empty.
      */
     public UpdateRequest(String registrationId, Long lifetime, String smsNumber, BindingMode binding,
-            LinkObject[] objectLinks) {
+            LinkObject[] objectLinks) throws InvalidRequestException {
+
+        if (registrationId == null || registrationId.isEmpty())
+            throw new InvalidRequestException("registrationId is mandatory");
 
-        Validate.notNull(registrationId);
         this.registrationId = registrationId;
         this.objectLinks = objectLinks;
         this.lifeTimeInSec = lifetime;
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/WriteAttributesRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/WriteAttributesRequest.java
index 7052d88e..64889e0a 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/WriteAttributesRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/WriteAttributesRequest.java
@@ -17,38 +17,40 @@ package org.eclipse.leshan.core.request;
 
 import org.eclipse.leshan.ObserveSpec;
 import org.eclipse.leshan.core.node.LwM2mPath;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.WriteAttributesResponse;
-import org.eclipse.leshan.util.Validate;
 
 public class WriteAttributesRequest extends AbstractDownlinkRequest<WriteAttributesResponse> {
 
     private final ObserveSpec observeSpec;
 
-    public WriteAttributesRequest(final int objectId, final ObserveSpec observeSpec) {
+    public WriteAttributesRequest(int objectId, ObserveSpec observeSpec) throws InvalidRequestException {
         this(new LwM2mPath(objectId), observeSpec);
     }
 
-    public WriteAttributesRequest(final int objectId, final int objectInstanceId, final ObserveSpec observeSpec) {
+    public WriteAttributesRequest(int objectId, int objectInstanceId, ObserveSpec observeSpec)
+            throws InvalidRequestException {
         this(new LwM2mPath(objectId, objectInstanceId), observeSpec);
     }
 
-    public WriteAttributesRequest(final int objectId, final int objectInstanceId, final int resourceId,
-            final ObserveSpec observeSpec) {
+    public WriteAttributesRequest(int objectId, int objectInstanceId, int resourceId, ObserveSpec observeSpec)
+            throws InvalidRequestException {
         this(new LwM2mPath(objectId, objectInstanceId, resourceId), observeSpec);
     }
 
-    public WriteAttributesRequest(final String path, final ObserveSpec observeSpec) {
-        this(new LwM2mPath(path), observeSpec);
+    public WriteAttributesRequest(String path, ObserveSpec observeSpec) throws InvalidRequestException {
+        this(newPath(path), observeSpec);
     }
 
-    private WriteAttributesRequest(final LwM2mPath path, final ObserveSpec observeSpec) {
+    private WriteAttributesRequest(LwM2mPath path, ObserveSpec observeSpec) throws InvalidRequestException {
         super(path);
-        Validate.notNull(observeSpec);
+        if (observeSpec == null)
+            throw new InvalidRequestException("attributes are mandatory");
         this.observeSpec = observeSpec;
     }
 
     @Override
-    public void accept(final DownlinkRequestVisitor visitor) {
+    public void accept(DownlinkRequestVisitor visitor) {
         visitor.visit(this);
     }
 
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/WriteRequest.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/WriteRequest.java
index d79e747a..c84b3338 100644
--- a/leshan-core/src/main/java/org/eclipse/leshan/core/request/WriteRequest.java
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/WriteRequest.java
@@ -27,8 +27,8 @@ import org.eclipse.leshan.core.node.LwM2mPath;
 import org.eclipse.leshan.core.node.LwM2mResource;
 import org.eclipse.leshan.core.node.LwM2mSingleResource;
 import org.eclipse.leshan.core.node.ObjectLink;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.WriteResponse;
-import org.eclipse.leshan.util.Validate;
 
 /**
  * The request to change the value of a Resource, an array of Resources Instances or multiple Resources from an Object
@@ -66,9 +66,10 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
      * @param objectId the id of the object to write.
      * @param objectInstanceId the id of the object instance to write.
      * @param resources the list of resources to write.
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final Mode mode, final ContentFormat contentFormat, final int objectId,
-            final int objectInstanceId, final Collection<LwM2mResource> resources) {
+    public WriteRequest(Mode mode, ContentFormat contentFormat, int objectId, int objectInstanceId,
+            Collection<LwM2mResource> resources) throws InvalidRequestException {
         this(mode, contentFormat, new LwM2mPath(objectId, objectInstanceId),
                 new LwM2mObjectInstance(objectId, resources));
     }
@@ -81,8 +82,7 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
      * @param objectInstanceId the id of the object instance to write.
      * @param resources the list of resources to write.
      */
-    public WriteRequest(final Mode mode, final int objectId, final int objectInstanceId,
-            final Collection<LwM2mResource> resources) {
+    public WriteRequest(Mode mode, int objectId, int objectInstanceId, Collection<LwM2mResource> resources) {
         this(mode, ContentFormat.TLV, new LwM2mPath(objectId, objectInstanceId),
                 new LwM2mObjectInstance(objectId, resources));
     }
@@ -95,9 +95,10 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
      * @param objectId the id of the object to write.
      * @param objectInstanceId the id of the object instance to write.
      * @param resources the list of resources to write.
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final Mode mode, final ContentFormat contentFormat, final int objectId,
-            final int objectInstanceId, final LwM2mResource... resources) {
+    public WriteRequest(Mode mode, ContentFormat contentFormat, int objectId, int objectInstanceId,
+            LwM2mResource... resources) throws InvalidRequestException {
         this(mode, contentFormat, new LwM2mPath(objectId, objectInstanceId),
                 new LwM2mObjectInstance(objectId, resources));
     }
@@ -110,8 +111,7 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
      * @param objectInstanceId the id of the object instance to write.
      * @param resources the list of resources to write.
      */
-    public WriteRequest(final Mode mode, final int objectId, final int objectInstanceId,
-            final LwM2mResource... resources) {
+    public WriteRequest(Mode mode, int objectId, int objectInstanceId, LwM2mResource... resources) {
         this(mode, ContentFormat.TLV, new LwM2mPath(objectId, objectInstanceId),
                 new LwM2mObjectInstance(objectId, resources));
     }
@@ -120,15 +120,17 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
     /**
      * Request to write a <b>String Single-Instance Resource</b> using the TLV content format.
      */
-    public WriteRequest(final int objectId, final int objectInstanceId, final int resourceId, String value) {
+    public WriteRequest(int objectId, int objectInstanceId, int resourceId, String value) {
         this(ContentFormat.TLV, objectId, objectInstanceId, resourceId, value);
     }
 
     /**
      * Request to write a <b>String Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON).
+     * 
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final ContentFormat contentFormat, final int objectId, final int objectInstanceId,
-            final int resourceId, String value) {
+    public WriteRequest(ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId, String value)
+            throws InvalidRequestException {
         this(Mode.REPLACE, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mSingleResource.newStringResource(resourceId, value));
     }
@@ -136,15 +138,17 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
     /**
      * Request to write a <b>Boolean Single-Instance Resource</b> using the TLV content format.
      */
-    public WriteRequest(final int objectId, final int objectInstanceId, final int resourceId, boolean value) {
+    public WriteRequest(int objectId, int objectInstanceId, int resourceId, boolean value) {
         this(ContentFormat.TLV, objectId, objectInstanceId, resourceId, value);
     }
 
     /**
      * Request to write a <b>Boolean Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON).
+     * 
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final ContentFormat contentFormat, final int objectId, final int objectInstanceId,
-            final int resourceId, boolean value) {
+    public WriteRequest(ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId, boolean value)
+            throws InvalidRequestException {
         this(Mode.REPLACE, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mSingleResource.newBooleanResource(resourceId, value));
     }
@@ -152,15 +156,17 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
     /**
      * Request to write a <b>Integer Single-Instance Resource</b> using the TLV content format.
      */
-    public WriteRequest(final int objectId, final int objectInstanceId, final int resourceId, long value) {
+    public WriteRequest(int objectId, int objectInstanceId, int resourceId, long value) {
         this(ContentFormat.TLV, objectId, objectInstanceId, resourceId, value);
     }
 
     /**
      * Request to write a <b>Integer Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON).
+     * 
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final ContentFormat contentFormat, final int objectId, final int objectInstanceId,
-            final int resourceId, long value) {
+    public WriteRequest(ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId, long value)
+            throws InvalidRequestException {
         this(Mode.REPLACE, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mSingleResource.newIntegerResource(resourceId, value));
     }
@@ -168,15 +174,17 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
     /**
      * Request to write a <b> Float Single-Instance Resource</b> using the TLV content format.
      */
-    public WriteRequest(final int objectId, final int objectInstanceId, final int resourceId, double value) {
+    public WriteRequest(int objectId, int objectInstanceId, int resourceId, double value) {
         this(ContentFormat.TLV, objectId, objectInstanceId, resourceId, value);
     }
 
     /**
      * Request to write a <b> Float Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON).
+     * 
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final ContentFormat contentFormat, final int objectId, final int objectInstanceId,
-            final int resourceId, double value) {
+    public WriteRequest(ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId, double value)
+            throws InvalidRequestException {
         this(Mode.REPLACE, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mSingleResource.newFloatResource(resourceId, value));
     }
@@ -184,15 +192,17 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
     /**
      * Request to write a <b> Date Single-Instance Resource</b> using the TLV content format.
      */
-    public WriteRequest(final int objectId, final int objectInstanceId, final int resourceId, Date value) {
+    public WriteRequest(int objectId, int objectInstanceId, int resourceId, Date value) {
         this(ContentFormat.TLV, objectId, objectInstanceId, resourceId, value);
     }
 
     /**
      * Request to write a <b> Date Single-Instance Resource</b> using the given content format (TEXT, TLV, JSON).
+     * 
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final ContentFormat contentFormat, final int objectId, final int objectInstanceId,
-            final int resourceId, Date value) {
+    public WriteRequest(ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId, Date value)
+            throws InvalidRequestException {
         this(Mode.REPLACE, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mSingleResource.newDateResource(resourceId, value));
     }
@@ -200,15 +210,17 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
     /**
      * Request to write a <b> Binary Single-Instance Resource</b> using the TLV content format.
      */
-    public WriteRequest(final int objectId, final int objectInstanceId, final int resourceId, byte[] value) {
+    public WriteRequest(int objectId, int objectInstanceId, int resourceId, byte[] value) {
         this(ContentFormat.TLV, objectId, objectInstanceId, resourceId, value);
     }
 
     /**
      * Request to write a <b> Binary Single-Instance Resource</b> using the given content format (OPAQUE, TLV, JSON).
+     * 
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final ContentFormat contentFormat, final int objectId, final int objectInstanceId,
-            final int resourceId, byte[] value) {
+    public WriteRequest(ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId, byte[] value)
+            throws InvalidRequestException {
         this(Mode.REPLACE, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mSingleResource.newBinaryResource(resourceId, value));
     }
@@ -216,16 +228,17 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
     /**
      * Request to write a <b> Objlnk Single-Instance Resource</b> using the TLV content format.
      */
-    public WriteRequest(final int objectId, final int objectInstanceId, final int resourceId, ObjectLink value) {
+    public WriteRequest(int objectId, int objectInstanceId, int resourceId, ObjectLink value) {
         this(ContentFormat.TLV, objectId, objectInstanceId, resourceId, value);
     }
 
     /**
-     * Request to write a <b> Objlnk Single-Instance Resource</b> using the given content format (OPAQUE, TLV, JSON,
-     * TEXT).
+     * Request to write a <b> Objlnk Single-Instance Resource</b> using the given content format (TLV, JSON, TEXT).
+     * 
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
      */
-    public WriteRequest(final ContentFormat contentFormat, final int objectId, final int objectInstanceId,
-            final int resourceId, ObjectLink value) {
+    public WriteRequest(ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId,
+            ObjectLink value) throws InvalidRequestException {
         this(Mode.REPLACE, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mSingleResource.newObjectLinkResource(resourceId, value));
     }
@@ -240,9 +253,11 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
      * @param resourceId the id of the resource to write.
      * @param values the list of resource instance (id->value) to write.
      * @param type the data type of the resource.
+     * @exception InvalidRequestException if bad @{link ContentFormat} format was used.
+     * 
      */
-    public WriteRequest(final ContentFormat contentFormat, final int objectId, final int objectInstanceId,
-            final int resourceId, final Map<Integer, ?> values, Type type) {
+    public WriteRequest(ContentFormat contentFormat, int objectId, int objectInstanceId, int resourceId,
+            Map<Integer, ?> values, Type type) throws InvalidRequestException {
         this(Mode.REPLACE, contentFormat, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mMultipleResource.newResource(resourceId, values, type));
     }
@@ -255,9 +270,10 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
      * @param resourceId the id of the resource to write.
      * @param values the list of resource instance (id->value) to write.
      * @param type the data type of the resource.
+     * @exception InvalidRequestException if parameters are invalid.
      */
-    public WriteRequest(final int objectId, final int objectInstanceId, final int resourceId,
-            final Map<Integer, ?> values, Type type) {
+    public WriteRequest(int objectId, int objectInstanceId, int resourceId, Map<Integer, ?> values, Type type)
+            throws InvalidRequestException {
         this(Mode.REPLACE, ContentFormat.TLV, new LwM2mPath(objectId, objectInstanceId, resourceId),
                 LwM2mMultipleResource.newResource(resourceId, values, type));
     }
@@ -270,53 +286,55 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
      * @param contentFormat Format of the payload (TLV,JSON,TEXT,OPAQUE ..).
      * @param path the path of the LWM2M node to write (object instance or resource).
      * @param node the {@link LwM2mNode} to write.
+     * @exception InvalidRequestException if parameters are invalid.
      */
-    public WriteRequest(final Mode mode, final ContentFormat contentFormat, final String path, final LwM2mNode node) {
-        this(mode, contentFormat, new LwM2mPath(path), node);
+    public WriteRequest(Mode mode, ContentFormat contentFormat, String path, LwM2mNode node) throws InvalidRequestException {
+        this(mode, contentFormat, newPath(path), node);
     }
 
-    private WriteRequest(final Mode mode, ContentFormat format, final LwM2mPath target, final LwM2mNode node) {
+    private WriteRequest(Mode mode, ContentFormat format, LwM2mPath target, LwM2mNode node) {
         super(target);
-        Validate.notNull(mode);
-        Validate.notNull(node);
+        if (mode == null)
+            throw new InvalidRequestException("mode is mandatory");
+        if (node == null)
+            throw new InvalidRequestException("new node value is mandatory");
 
         // Validate Mode
-        if (getPath().isResource() && mode == Mode.UPDATE) {
-            throw new IllegalArgumentException(
+        if (getPath().isResource() && mode == Mode.UPDATE)
+            throw new InvalidRequestException(
                     String.format("Invalid mode for '%s': update is not allowed on resource", target.toString()));
-        }
 
         // Validate node and path coherence
         if (getPath().isResource()) {
             if (!(node instanceof LwM2mResource)) {
-                throw new IllegalArgumentException(String.format("path '%s' and node type '%s' does not match",
+                throw new InvalidRequestException(String.format("path '%s' and node type '%s' does not match",
                         target.toString(), node.getClass().getSimpleName()));
             }
         } else if (getPath().isObjectInstance()) {
             if (!(node instanceof LwM2mObjectInstance)) {
-                throw new IllegalArgumentException(String.format("path '%s' and node type '%s' does not match",
+                throw new InvalidRequestException(String.format("path '%s' and node type '%s' does not match",
                         target.toString(), node.getClass().getSimpleName()));
             }
         } else if (getPath().isObject()) {
-            throw new IllegalArgumentException("write request cannot target an object: " + target.toString());
+            throw new InvalidRequestException("write request cannot target an object: " + target.toString());
         }
 
         // Validate content format
         if (ContentFormat.TEXT == format || ContentFormat.OPAQUE == format) {
             if (!getPath().isResource()) {
-                throw new IllegalArgumentException(
+                throw new InvalidRequestException(
                         String.format("%s format must be used only for single resources", format.toString()));
             } else {
                 LwM2mResource resource = (LwM2mResource) node;
                 if (resource.isMultiInstances()) {
-                    throw new IllegalArgumentException(
+                    throw new InvalidRequestException(
                             String.format("%s format must be used only for single resources", format.toString()));
                 } else {
                     if (resource.getType() == Type.OPAQUE && format == ContentFormat.TEXT) {
-                        throw new IllegalArgumentException(
+                        throw new InvalidRequestException(
                                 "TEXT format must not be used for byte array single resources");
                     } else if (resource.getType() != Type.OPAQUE && format == ContentFormat.OPAQUE) {
-                        throw new IllegalArgumentException(
+                        throw new InvalidRequestException(
                                 "OPAQUE format must be used only for byte array single resources");
                     }
                 }
@@ -355,7 +373,7 @@ public class WriteRequest extends AbstractDownlinkRequest<WriteResponse> {
     }
 
     @Override
-    public void accept(final DownlinkRequestVisitor visitor) {
+    public void accept(DownlinkRequestVisitor visitor) {
         visitor.visit(this);
     }
 
diff --git a/leshan-core/src/main/java/org/eclipse/leshan/core/request/exception/InvalidRequestException.java b/leshan-core/src/main/java/org/eclipse/leshan/core/request/exception/InvalidRequestException.java
new file mode 100644
index 00000000..1dabecb3
--- /dev/null
+++ b/leshan-core/src/main/java/org/eclipse/leshan/core/request/exception/InvalidRequestException.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Sierra Wireless and others.
+ * 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Eclipse Distribution License v1.0 which accompany this distribution.
+ * 
+ * The Eclipse Public License is available at
+ *    http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ *    http://www.eclipse.org/org/documents/edl-v10.html.
+ * 
+ * Contributors:
+ *     Sierra Wireless - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.leshan.core.request.exception;
+
+/**
+ * Thrown to indicate that the application has attempted to create a request with invalid parameters.
+ */
+public class InvalidRequestException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public InvalidRequestException() {
+    }
+
+    public InvalidRequestException(String m) {
+        super(m);
+    }
+    
+    public InvalidRequestException(String m, Throwable e) {
+        super(m, e);
+    }
+
+    public InvalidRequestException(Throwable e) {
+        super(e);
+    }
+}
diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/RegisterResource.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/RegisterResource.java
index e446002c..cb229163 100644
--- a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/RegisterResource.java
+++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/RegisterResource.java
@@ -37,6 +37,7 @@ import org.eclipse.leshan.core.request.DeregisterRequest;
 import org.eclipse.leshan.core.request.Identity;
 import org.eclipse.leshan.core.request.RegisterRequest;
 import org.eclipse.leshan.core.request.UpdateRequest;
+import org.eclipse.leshan.core.request.exception.InvalidRequestException;
 import org.eclipse.leshan.core.response.DeregisterResponse;
 import org.eclipse.leshan.core.response.RegisterResponse;
 import org.eclipse.leshan.core.response.UpdateResponse;
@@ -81,8 +82,17 @@ public class RegisterResource extends CoapResource {
     public void handleRequest(Exchange exchange) {
         try {
             super.handleRequest(exchange);
+        } catch (InvalidRequestException e) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug(String.format("InvalidRequestException while handling request(%s) on the /rd resource",
+                        exchange.getRequest()), e);
+            }
+            Response response = new Response(ResponseCode.BAD_REQUEST);
+            response.setPayload(e.getMessage());
+            exchange.sendResponse(response);
         } catch (Exception e) {
-            LOG.error("Exception while handling a request on the /rd resource", e);
+            LOG.error(String.format("Exception while handling request(%s) on the /rd resource", exchange.getRequest()),
+                    e);
             exchange.sendResponse(new Response(ResponseCode.INTERNAL_SERVER_ERROR));
         }
     }
@@ -144,7 +154,9 @@ public class RegisterResource extends CoapResource {
         String smsNumber = null;
         String lwVersion = null;
         BindingMode binding = null;
-        LinkObject[] objectLinks = null;
+
+        // Get object Links
+        LinkObject[] objectLinks = LinkObject.parse(request.getPayload());
 
         Map<String, String> additionalParams = new HashMap<String, String>();
 
@@ -167,10 +179,6 @@ public class RegisterResource extends CoapResource {
                 }
             }
         }
-        // Get object Links
-        if (request.getPayload() != null) {
-            objectLinks = LinkObject.parse(request.getPayload());
-        }
 
         // Create request
         RegisterRequest registerRequest = new RegisterRequest(endpoint, lifetime, lwVersion, binding, smsNumber,
diff --git a/leshan-server-core/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java b/leshan-server-core/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java
index e17fd79e..df7adbba 100644
--- a/leshan-server-core/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java
+++ b/leshan-server-core/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java
@@ -52,10 +52,6 @@ public class RegistrationHandler {
 
     public RegisterResponse register(Identity sender, RegisterRequest registerRequest, InetSocketAddress serverEndpoint) {
 
-        if (registerRequest.getEndpointName() == null || registerRequest.getEndpointName().isEmpty() || sender == null) {
-            return RegisterResponse.badRequest(null);
-        }
-
         Registration.Builder builder = new Registration.Builder(RegistrationHandler.createRegistrationId(),
                 registerRequest.getEndpointName(), sender.getPeerAddress().getAddress(), sender.getPeerAddress()
                         .getPort(), serverEndpoint);
@@ -82,10 +78,6 @@ public class RegistrationHandler {
 
     public UpdateResponse update(Identity sender, UpdateRequest updateRequest) {
 
-        if (sender == null) {
-            return UpdateResponse.badRequest(null);
-        }
-
         // We must check if the client is using the right identity.
         Registration registration = registrationService.getById(updateRequest.getRegistrationId());
         if (registration == null) {
@@ -108,12 +100,9 @@ public class RegistrationHandler {
     }
 
     public DeregisterResponse deregister(Identity sender, DeregisterRequest deregisterRequest) {
-        if (sender == null) {
-            return DeregisterResponse.badRequest(null);
-        }
 
         // We must check if the client is using the right identity.
-        Registration registration = registrationService.getById(deregisterRequest.getRegistrationID());
+        Registration registration = registrationService.getById(deregisterRequest.getRegistrationId());
         if (registration == null) {
             return DeregisterResponse.notFound();
         }
@@ -123,7 +112,7 @@ public class RegistrationHandler {
             return DeregisterResponse.badRequest("forbidden");
         }
 
-        Registration unregistered = registrationService.deregisterClient(deregisterRequest.getRegistrationID());
+        Registration unregistered = registrationService.deregisterClient(deregisterRequest.getRegistrationId());
         if (unregistered != null) {
             return DeregisterResponse.success();
         } else {


Test patch:
diff --git a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/RegistrationTest.java b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/RegistrationTest.java
index d9c7f7d5..c08b5847 100644
--- a/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/RegistrationTest.java
+++ b/leshan-integration-tests/src/test/java/org/eclipse/leshan/integration/tests/RegistrationTest.java
@@ -21,6 +21,7 @@ import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsInstanceOf.instanceOf;
 import static org.junit.Assert.*;
 
+import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
@@ -29,7 +30,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.eclipse.californium.core.coap.CoAP.Code;
+import org.eclipse.californium.core.coap.Request;
 import org.eclipse.californium.core.coap.Response;
+import org.eclipse.californium.core.network.CoapEndpoint;
 import org.eclipse.californium.core.network.Endpoint;
 import org.eclipse.leshan.LinkObject;
 import org.eclipse.leshan.ResponseCode;
@@ -40,6 +44,7 @@ import org.eclipse.leshan.client.resource.LwM2mObjectEnabler;
 import org.eclipse.leshan.client.resource.ObjectEnabler;
 import org.eclipse.leshan.core.node.LwM2mPath;
 import org.eclipse.leshan.core.observation.Observation;
+import org.eclipse.leshan.core.request.ContentFormat;
 import org.eclipse.leshan.core.request.DeregisterRequest;
 import org.eclipse.leshan.core.request.ObserveRequest;
 import org.eclipse.leshan.core.request.ReadRequest;
@@ -287,4 +292,28 @@ public class RegistrationTest {
         sender.send(helper.server.getNonSecureAddress(), false, new DeregisterRequest(resp.getRegistrationID()), 5000l);
         lclient.getCoapServer().stop();
     }
+
+    @Test
+    public void register_with_invalid_request() throws InterruptedException, IOException {
+        // Check registration
+        helper.assertClientNotRegisterered();
+
+        // create a register request without the list of supported object
+        Request coapRequest = new Request(Code.POST);
+        coapRequest.setDestination(helper.server.getNonSecureAddress().getAddress());
+        coapRequest.setDestinationPort(helper.server.getNonSecureAddress().getPort());
+        coapRequest.getOptions().setContentFormat(ContentFormat.LINK.getCode());
+        coapRequest.getOptions().addUriPath("rd");
+        coapRequest.getOptions().addUriQuery("ep=" + helper.currentEndpointIdentifier);
+        
+        // send request
+        CoapEndpoint coapEndpoint = new CoapEndpoint(new InetSocketAddress(0));
+        coapEndpoint.start();
+        coapEndpoint.sendRequest(coapRequest);
+        
+        // check response
+        Response response = coapRequest.waitForResponse(1000);
+        assertEquals(response.getCode(), org.eclipse.californium.core.coap.CoAP.ResponseCode.BAD_REQUEST);
+        coapEndpoint.stop();
+    }
 }