You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by tb...@apache.org on 2013/04/09 16:57:06 UTC

svn commit: r1466063 - in /incubator/ambari/trunk: ./ ambari-server/src/main/java/org/apache/ambari/server/api/services/ ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/ ambari-server/src/test/java/org/apache/ambari/server/api...

Author: tbeerbower
Date: Tue Apr  9 14:57:05 2013
New Revision: 1466063

URL: http://svn.apache.org/r1466063
Log:
AMBARI-1844 - Need ability to update multiple hosts in 1 PUT call

Modified:
    incubator/ambari/trunk/CHANGES.txt
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
    incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/BaseServiceTest.java
    incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java

Modified: incubator/ambari/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/CHANGES.txt?rev=1466063&r1=1466062&r2=1466063&view=diff
==============================================================================
--- incubator/ambari/trunk/CHANGES.txt (original)
+++ incubator/ambari/trunk/CHANGES.txt Tue Apr  9 14:57:05 2013
@@ -12,7 +12,7 @@ Trunk (unreleased changes):
 
  NEW FEATURES
 
- AMBARI-1840. For global properties show restart for appropriate services 
+ AMBARI-1840. For global properties show restart for appropriate services
  only. (srimanth)
 
  AMBARI-1800. Add "Admin > Misc" section to Ambari Web to show service user
@@ -227,6 +227,9 @@ Trunk (unreleased changes):
 
  IMPROVEMENTS
 
+ AMBARI-1844. Need ability to update multiple hosts in 1 PUT call.
+ (tbeerbower)
+
  AMBARI-1825. Minor label change for the buttons to start/stop all services
  in the side nav. (yusaku)
 

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java?rev=1466063&r1=1466062&r2=1466063&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/BaseService.java Tue Apr  9 14:57:05 2013
@@ -31,7 +31,9 @@ import org.apache.ambari.server.controll
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Provides common functionality to all services.
@@ -64,13 +66,19 @@ public abstract class BaseService {
   protected Response handleRequest(HttpHeaders headers, String body, UriInfo uriInfo,
                                    Request.Type requestType, ResourceInstance resource) {
 
-    Result result;
+    Result result = new ResultImpl(new ResultStatus(ResultStatus.STATUS.OK));
     try {
-      RequestBody requestBody = getBodyParser().parse(body);
-      Request request = getRequestFactory().createRequest(
-          headers, requestBody, uriInfo, requestType, resource);
+      Set<RequestBody> requestBodySet = getBodyParser().parse(body);
 
-      result = request.process();
+      Iterator<RequestBody> iterator = requestBodySet.iterator();
+      while (iterator.hasNext() && result.getStatus().getStatus().equals(ResultStatus.STATUS.OK)) {
+        RequestBody requestBody = iterator.next();
+
+        Request request = getRequestFactory().createRequest(
+            headers, requestBody, uriInfo, requestType, resource);
+
+        result = request.process();
+      }
     } catch (BodyParseException e) {
       result =  new ResultImpl(new ResultStatus(ResultStatus.STATUS.BAD_REQUEST, e.getMessage()));
     }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java?rev=1466063&r1=1466062&r2=1466063&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java Tue Apr  9 14:57:05 2013
@@ -39,47 +39,75 @@ public class JsonRequestBodyParser imple
   private final static Logger LOG = LoggerFactory.getLogger(JsonRequestBodyParser.class);
 
   @Override
-  public RequestBody parse(String s) throws BodyParseException {
-    RequestBody body = new RequestBody();
-    body.setBody(s);
+  public Set<RequestBody> parse(String body) throws BodyParseException {
 
-    if (s != null && s.length() != 0) {
-      s = ensureArrayFormat(s);
+    Set<RequestBody> requestBodySet = new HashSet<RequestBody>();
+    RequestBody      rootBody       = new RequestBody();
+    rootBody.setBody(body);
+
+    if (body != null && body.length() != 0) {
       ObjectMapper mapper = new ObjectMapper();
       try {
-        JsonNode root = mapper.readTree(s);
+        JsonNode root = mapper.readTree(ensureArrayFormat(body));
 
-        Iterator<JsonNode> iter = root.getElements();
-        while (iter.hasNext()) {
-          Map<String, Object> mapProperties = new HashMap<String, Object>();
-          NamedPropertySet propertySet = new NamedPropertySet("", mapProperties);
-          JsonNode node = iter.next();
-          processNode(node, "", propertySet, body);
-
-          String query = body.getRequestInfoProperties().get(QUERY_FIELD_NAME);
-          if (query != null) {
-            body.setQueryString(query);
-          }
-          if (propertySet.getProperties().size() != 0) {
-            body.addPropertySet(propertySet);
+        Iterator<JsonNode> iterator = root.getElements();
+        while (iterator.hasNext()) {
+          JsonNode            node             = iterator.next();
+          Map<String, Object> mapProperties    = new HashMap<String, Object>();
+          Map<String, String> requestInfoProps = new HashMap<String, String>();
+          NamedPropertySet    propertySet      = new NamedPropertySet("", mapProperties);
+
+          processNode(node, "", propertySet, requestInfoProps);
+
+          if (!requestInfoProps.isEmpty()) {
+            // If this node has request info properties then add it as a
+            // separate request body
+            RequestBody requestBody = new RequestBody();
+            requestBody.setBody(body);
+
+            for (Map.Entry<String, String> entry : requestInfoProps.entrySet()) {
+              String key   = entry.getKey();
+              String value = entry.getValue();
+
+              requestBody.addRequestInfoProperty(key, value);
+
+              if (key.equals(QUERY_FIELD_NAME)) {
+                requestBody.setQueryString(value);
+              }
+            }
+            if (!propertySet.getProperties().isEmpty()) {
+              requestBody.addPropertySet(propertySet);
+            }
+            requestBodySet.add(requestBody);
+          } else {
+            // If this node does not have request info properties then add it
+            // as a new property set to the root request body
+            if (!propertySet.getProperties().isEmpty()) {
+              rootBody.addPropertySet(propertySet);
+            }
+            requestBodySet.add(rootBody);
           }
         }
       } catch (IOException e) {
         if (LOG.isDebugEnabled()) {
           LOG.debug("Caught exception parsing msg body.");
-          LOG.debug("Message Body: " + s, e);
+          LOG.debug("Message Body: " + body, e);
         }
         throw new BodyParseException(e);
       }
     }
-    return body;
+    if (requestBodySet.isEmpty()) {
+      requestBodySet.add(rootBody);
+    }
+    return requestBodySet;
   }
 
-  private void processNode(JsonNode node, String path, NamedPropertySet propertySet, RequestBody body) {
-    Iterator<String> iter = node.getFieldNames();
-    String name;
-    while (iter.hasNext()) {
-      name = iter.next();
+  private void processNode(JsonNode node, String path, NamedPropertySet propertySet,
+                           Map<String, String> requestInfoProps) {
+
+    Iterator<String> iterator = node.getFieldNames();
+    while (iterator.hasNext()) {
+      String   name  = iterator.next();
       JsonNode child = node.get(name);
       if (child.isArray()) {
         //array
@@ -88,7 +116,7 @@ public class JsonRequestBodyParser imple
 
         while (arrayIter.hasNext()) {
           NamedPropertySet arrayPropertySet = new NamedPropertySet(name, new HashMap<String, Object>());
-          processNode(arrayIter.next(), "", arrayPropertySet, body);
+          processNode(arrayIter.next(), "", arrayPropertySet, requestInfoProps);
           arraySet.add(arrayPropertySet.getProperties());
         }
         propertySet.getProperties().put(PropertyHelper.getPropertyId(path, name), arraySet);
@@ -97,18 +125,16 @@ public class JsonRequestBodyParser imple
         if (name.equals(BODY_TITLE)) {
           name = "";
         }
-        processNode(child, path.isEmpty() ? name : path + '/' + name, propertySet, body);
+        processNode(child, path.isEmpty() ? name : path + '/' + name, propertySet, requestInfoProps);
       } else {
         // field
         if (path.startsWith(REQUEST_INFO_PATH)) {
-          body.addRequestInfoProperty(PropertyHelper.getPropertyId(
+          requestInfoProps.put(PropertyHelper.getPropertyId(
               path.substring(REQUEST_INFO_PATH.length()), name), child.asText());
-
-        }  else {
+        } else {
           propertySet.getProperties().put(PropertyHelper.getPropertyId(
               path.equals(BODY_TITLE) ? "" : path, name), child.asText());
         }
-
       }
     }
   }

Modified: incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java?rev=1466063&r1=1466062&r2=1466063&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java (original)
+++ incubator/ambari/trunk/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/RequestBodyParser.java Tue Apr  9 14:57:05 2013
@@ -20,6 +20,8 @@ package org.apache.ambari.server.api.ser
 
 import org.apache.ambari.server.api.services.RequestBody;
 
+import java.util.Set;
+
 /**
  * Parse the provided String into a map of properties and associated values.
  */
@@ -40,12 +42,12 @@ public interface RequestBodyParser {
   public static final String BODY_TITLE = "Body";
 
   /**
-   * Parse the provided string into a request body which contains all properties in the string.
-   *
+   * Parse the provided string into request bodies based on the
+   * properties in the given body string.
    *
-   * @param s  the string body to be parsed
+   * @param body  the string body to be parsed
    *
-   * @return RequestBody instance containing all properties in the string
+   * @return a set of {@link RequestBody} instances
    */
-  public RequestBody parse(String s) throws BodyParseException;
+  public Set<RequestBody> parse(String body) throws BodyParseException;
 }

Modified: incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/BaseServiceTest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/BaseServiceTest.java?rev=1466063&r1=1466062&r2=1466063&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/BaseServiceTest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/BaseServiceTest.java Tue Apr  9 14:57:05 2013
@@ -31,6 +31,7 @@ import javax.ws.rs.core.UriInfo;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -99,7 +100,7 @@ public abstract class BaseServiceTest {
 
   private void testMethod(ServiceTestInvocation testMethod) throws InvocationTargetException, IllegalAccessException {
     try {
-      expect(bodyParser.parse(testMethod.getBody())).andReturn(requestBody);
+      expect(bodyParser.parse(testMethod.getBody())).andReturn(Collections.singleton(requestBody));
     } catch (BodyParseException e) {
       // needed for compiler
     }
@@ -137,7 +138,7 @@ public abstract class BaseServiceTest {
 
   private void testMethod_resultInErrorState(ServiceTestInvocation testMethod) throws Exception {
     try {
-      expect(bodyParser.parse(testMethod.getBody())).andReturn(requestBody);
+      expect(bodyParser.parse(testMethod.getBody())).andReturn(Collections.singleton(requestBody));
     } catch (BodyParseException e) {
       // needed for compiler
     }

Modified: incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java
URL: http://svn.apache.org/viewvc/incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java?rev=1466063&r1=1466062&r2=1466063&view=diff
==============================================================================
--- incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java (original)
+++ incubator/ambari/trunk/ambari-server/src/test/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParserTest.java Tue Apr  9 14:57:05 2013
@@ -28,6 +28,7 @@ import java.util.Map;
 import java.util.Set;
 
 import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Unit tests for JsonPropertyParser.
@@ -78,6 +79,39 @@ public class JsonRequestBodyParserTest {
       "    \"Category\" : { \"property2\" : \"prop2Value\"}" +
       "} }";
 
+  String multiBody = "[\n" +
+      "  {\n" +
+      "    \"RequestInfo\":{\n" +
+      "      \"query\":\"Hosts/host_name=h1\"\n" +
+      "    },\n" +
+      "    \"Body\":\n" +
+      "    {\n" +
+      "      \"Hosts\": {\n" +
+      "        \"desired_config\": {\n" +
+      "          \"type\": \"global\",\n" +
+      "          \"tag\": \"version20\",\n" +
+      "          \"properties\": { \"a\": \"b\", \"x\": \"y\" }\n" +
+      "        }\n" +
+      "      }\n" +
+      "    }\n" +
+      "  },\n" +
+      "  {\n" +
+      "    \"RequestInfo\":{\n" +
+      "      \"query\":\"Hosts/host_name=h2\"\n" +
+      "    },\n" +
+      "    \"Body\":\n" +
+      "    {\n" +
+      "      \"Hosts\": {\n" +
+      "        \"desired_config\": {\n" +
+      "          \"type\": \"global\",\n" +
+      "          \"tag\": \"version21\",\n" +
+      "          \"properties\": { \"a\": \"c\", \"x\": \"z\" }\n" +
+      "        }\n" +
+      "      }\n" +
+      "    }\n" +
+      "  }\n" +
+      "]\n";
+
   String queryPostJson = "{ \"services\" : [ {" +
       "\"ServiceInfo\" : {\n" +
       "    \"service_name\" : \"unitTestService1\"" +
@@ -117,7 +151,7 @@ public class JsonRequestBodyParserTest {
   @Test
   public void testParse() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse(serviceJson);
+    RequestBody body = parser.parse(serviceJson).iterator().next();
 
     Set<NamedPropertySet> setProps = body.getNamedPropertySets();
     assertEquals(1, setProps.size());
@@ -136,7 +170,7 @@ public class JsonRequestBodyParserTest {
 
     //assert body is correct by checking that properties match
     String b = body.getBody();
-    body = parser.parse(b);
+    body = parser.parse(b).iterator().next();
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(mapExpected, setProps2.iterator().next().getProperties());
   }
@@ -144,7 +178,7 @@ public class JsonRequestBodyParserTest {
   @Test
   public void testParse_NullBody() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse(null);
+    RequestBody body = parser.parse(null).iterator().next();
 
     assertNotNull(body.getNamedPropertySets());
     assertEquals(0, body.getNamedPropertySets().size());
@@ -156,7 +190,7 @@ public class JsonRequestBodyParserTest {
   @Test
   public void testParse_EmptyBody() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse("");
+    RequestBody body = parser.parse("").iterator().next();
 
     assertNotNull(body.getNamedPropertySets());
     assertEquals(0, body.getNamedPropertySets().size());
@@ -166,9 +200,28 @@ public class JsonRequestBodyParserTest {
   }
 
   @Test
+  public void testParse_MultiBody() throws BodyParseException {
+    RequestBodyParser parser = new JsonRequestBodyParser();
+    Set<RequestBody> bodySet = parser.parse(multiBody);
+
+    assertEquals(2, bodySet.size());
+
+    for (RequestBody body : bodySet) {
+      Set<NamedPropertySet> setProps = body.getNamedPropertySets();
+      assertEquals(1, setProps.size());
+
+      Map<String, Object> mapProps = setProps.iterator().next().getProperties();
+
+      assertEquals(4, mapProps.size());
+
+      assertEquals("global", mapProps.get("Hosts/desired_config/type"));
+    }
+  }
+
+  @Test
   public void testParse_Array() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse(arrayJson);
+    RequestBody body = parser.parse(arrayJson).iterator().next();
 
     Set<NamedPropertySet> setProps = body.getNamedPropertySets();
 
@@ -210,7 +263,7 @@ public class JsonRequestBodyParserTest {
     //assert body is correct by checking that properties match
     String b = body.getBody();
 
-    body = parser.parse(b);
+    body = parser.parse(b).iterator().next();
 
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(3, setProps2.size());
@@ -220,7 +273,7 @@ public class JsonRequestBodyParserTest {
   @Test
   public void testParse___Array_NoArrayBrackets() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse(arrayJson2);
+    RequestBody body = parser.parse(arrayJson2).iterator().next();
 
     Set<NamedPropertySet> setProps = body.getNamedPropertySets();
 
@@ -260,7 +313,7 @@ public class JsonRequestBodyParserTest {
 
     //assert body is correct by checking that properties match
     String b = body.getBody();
-    body = parser.parse(b);
+    body = parser.parse(b).iterator().next();
 
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(3, setProps2.size());
@@ -270,7 +323,7 @@ public class JsonRequestBodyParserTest {
   @Test
   public void testParse_QueryInBody() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse(serviceJsonWithQuery);
+    RequestBody body = parser.parse(serviceJsonWithQuery).iterator().next();
 
 
     Set<NamedPropertySet> setProps = body.getNamedPropertySets();
@@ -291,7 +344,7 @@ public class JsonRequestBodyParserTest {
 
     //assert body is correct by checking that properties match
     String b = body.getBody();
-    body = parser.parse(b);
+    body = parser.parse(b).iterator().next();
 
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(mapExpected, setProps2.iterator().next().getProperties());
@@ -300,7 +353,7 @@ public class JsonRequestBodyParserTest {
   @Test
   public void testParse_QueryPost() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse(queryPostJson);
+    RequestBody body = parser.parse(queryPostJson).iterator().next();
 
 
     Set<NamedPropertySet> setProperties = body.getNamedPropertySets();
@@ -339,7 +392,7 @@ public class JsonRequestBodyParserTest {
 
     //assert body is correct by checking that properties match
     String b = body.getBody();
-    body = parser.parse(b);
+    body = parser.parse(b).iterator().next();
 
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(1, setProps2.size());
@@ -349,7 +402,7 @@ public class JsonRequestBodyParserTest {
   @Test
   public void testParse___QueryPost_multipleSubResTypes() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse(queryPostMultipleSubResourcesJson);
+    RequestBody body = parser.parse(queryPostMultipleSubResourcesJson).iterator().next();
 
 
     Set<NamedPropertySet> setProperties = body.getNamedPropertySets();
@@ -389,7 +442,7 @@ public class JsonRequestBodyParserTest {
 
     //assert body is correct by checking that properties match
     String b = body.getBody();
-    body = parser.parse(b);
+    body = parser.parse(b).iterator().next();
 
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(1, setProps2.size());
@@ -400,7 +453,7 @@ public class JsonRequestBodyParserTest {
   public void testParse___QueryPost_QueryInBody() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
 
-    RequestBody body = parser.parse(queryPostJsonWithQuery);
+    RequestBody body = parser.parse(queryPostJsonWithQuery).iterator().next();
 
 
     Set<NamedPropertySet> setProperties = body.getNamedPropertySets();
@@ -446,7 +499,7 @@ public class JsonRequestBodyParserTest {
     String b = body.getBody();
     assertEquals(queryPostJsonWithQuery , b);
 
-    body = parser.parse(b);
+    body = parser.parse(b).iterator().next();
 
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(1, setProps2.size());
@@ -457,7 +510,7 @@ public class JsonRequestBodyParserTest {
   public void testParse_QueryOnlyInBody() throws BodyParseException {
     RequestBodyParser parser = new JsonRequestBodyParser();
 
-    RequestBody body = parser.parse(bodyQueryOnly);
+    RequestBody body = parser.parse(bodyQueryOnly).iterator().next();
 
     assertEquals("foo=bar", body.getQueryString());
     assertEquals(bodyQueryOnly, body.getBody());
@@ -478,7 +531,7 @@ public class JsonRequestBodyParserTest {
   @Test
   public void testRequestInfoProps() throws Exception {
     RequestBodyParser parser = new JsonRequestBodyParser();
-    RequestBody body = parser.parse(bodyWithRequestInfoProperties);
+    RequestBody body = parser.parse(bodyWithRequestInfoProperties).iterator().next();
 
     Set<NamedPropertySet> setProps = body.getNamedPropertySets();
     assertEquals(1, setProps.size());
@@ -504,7 +557,7 @@ public class JsonRequestBodyParserTest {
 
     //assert body is correct by checking that properties match
     String b = body.getBody();
-    body = parser.parse(b);
+    body = parser.parse(b).iterator().next();
 
     Set<NamedPropertySet> setProps2 = body.getNamedPropertySets();
     assertEquals(mapExpected, setProps2.iterator().next().getProperties());