diff --git a/src/main/java/it/inaf/oats/vospace/SetNodeController.java b/src/main/java/it/inaf/oats/vospace/SetNodeController.java
index d80bd72bcd83f2981360c854adc0cf5a050ef7d2..06ad3bfa9c6298f9da9a870d480058f11832d743 100644
--- a/src/main/java/it/inaf/oats/vospace/SetNodeController.java
+++ b/src/main/java/it/inaf/oats/vospace/SetNodeController.java
@@ -2,7 +2,6 @@ package it.inaf.oats.vospace;
 
 import it.inaf.ia2.aa.data.User;
 import it.inaf.oats.vospace.datamodel.NodeUtils;
-import it.inaf.oats.vospace.exception.LinkFoundException;
 import it.inaf.oats.vospace.exception.NodeNotFoundException;
 import it.inaf.oats.vospace.exception.PermissionDeniedException;
 import it.inaf.oats.vospace.persistence.NodeDAO;
@@ -18,6 +17,7 @@ import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 @RestController
@@ -31,7 +31,8 @@ public class SetNodeController extends BaseNodeController {
     @PostMapping(value = {"/nodes", "/nodes/**"},
             consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE},
             produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
-    public ResponseEntity<Node> setNode(@RequestBody Node node, User principal, HttpServletRequest request) {
+    public ResponseEntity<Node> setNode(@RequestBody Node node, User principal, HttpServletRequest request,
+            @RequestParam(value = "recursive", required = false, defaultValue = "false") boolean recursive) {
 
         String path = getPath();
         LOG.debug("setNode called for path {}", path);
@@ -70,7 +71,7 @@ public class SetNodeController extends BaseNodeController {
         // A HTTP 200 status code and a Node representation in the entity-body The full 
         // expanded record for the node SHALL be returned, including any xsi:type 
         // specific extensions.
-        return ResponseEntity.ok(nodeDao.setNode(node));
+        return ResponseEntity.ok(nodeDao.setNode(node, recursive));
     }
 
     private void checkViews(DataNode requestedDataNode, DataNode savedDataNode) {
diff --git a/src/test/java/it/inaf/oats/vospace/SetNodeControllerTest.java b/src/test/java/it/inaf/oats/vospace/SetNodeControllerTest.java
index f010df8497f8cb21d747b9c76d45ec4ae068e8f9..196e4bd84a091f695720595502471aa3a90ec761 100644
--- a/src/test/java/it/inaf/oats/vospace/SetNodeControllerTest.java
+++ b/src/test/java/it/inaf/oats/vospace/SetNodeControllerTest.java
@@ -101,7 +101,7 @@ public class SetNodeControllerTest {
         view.setUri(uri);
         return view;
     }
-    
+
     /* Test case:
        try to modify node type.
        Forbidden.
@@ -123,7 +123,6 @@ public class SetNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().isForbidden());
-
     }
 
     /* Test case:
@@ -147,7 +146,6 @@ public class SetNodeControllerTest {
                 .accept(MediaType.APPLICATION_XML))
                 .andDo(print())
                 .andExpect(status().isForbidden());
-
     }
 
     /* Test case:
@@ -205,12 +203,12 @@ public class SetNodeControllerTest {
         String requestBody = getResourceFileContent("modify-data-node-description-leaving-views.xml");
 
         Node node = getWritableDataNodeWithAcceptsAndProvides("/mydata1");
-        
+
         // Create node
         when(nodeDao.listNode(eq("/")))
                 .thenReturn(Optional.of(getContainerParentNode("/")));
         when(nodeDao.listNode(eq("/mydata1"))).thenReturn(Optional.of(node));
-        when(nodeDao.setNode(any())).thenReturn(node);
+        when(nodeDao.setNode(any(), eq(false))).thenReturn(node);
 
         mockMvc.perform(post("/nodes/mydata1")
                 .header("Authorization", "Bearer user2_token")
@@ -221,4 +219,29 @@ public class SetNodeControllerTest {
                 .andExpect(status().isOk());
     }
 
+    @Test
+    public void testSetNodeRecursive() throws Exception {
+        String requestBody = getResourceFileContent("modify-container-node.xml");
+
+        ContainerNode node = new ContainerNode();
+        node.setUri(URI_PREFIX + "/myfolder1");
+
+        Property groupWriteProp = new Property();
+        groupWriteProp.setUri(NodeProperties.GROUP_WRITE_URI);
+        groupWriteProp.setValue("group1");
+        node.getProperties().add(groupWriteProp);
+
+        when(nodeDao.listNode(eq("/"))).thenReturn(Optional.of(getContainerParentNode("/")));
+        when(nodeDao.listNode(eq("/myfolder1"))).thenReturn(Optional.of(node));
+        when(nodeDao.setNode(any(), eq(true))).thenReturn(node);
+
+        mockMvc.perform(post("/nodes/myfolder1")
+                .param("recursive", "true")
+                .header("Authorization", "Bearer user2_token")
+                .content(requestBody)
+                .contentType(MediaType.APPLICATION_XML)
+                .accept(MediaType.APPLICATION_XML))
+                .andDo(print())
+                .andExpect(status().isOk());
+    }
 }
diff --git a/src/test/resources/modify-container-node.xml b/src/test/resources/modify-container-node.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c1ed32a8974dcffbad644d785a88cedc96ecac62
--- /dev/null
+++ b/src/test/resources/modify-container-node.xml
@@ -0,0 +1,4 @@
+<vos:node xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns:vos="http://www.ivoa.net/xml/VOSpace/v2.0" xsi:type="vos:ContainerNode" uri="vos://example.com!vospace/myfolder1">
+</vos:node>