Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.
SOLVED

question about value maps

Avatar

Level 9

As aem forums always deletes my post for no reason, Ill try putting the question into the response part. Please read the below reply for the question.

The problem is I cant find a way to combine two value maps. doing .putAll() fails (not supported), and so does constructing a new one.

1 Accepted Solution

Avatar

Correct answer by
Level 9

Seems that ValueMaps are immutable, even if you use .put() you will get run time errors.

Instead I change everywhere which used ValueMap to use HashMap<String,Object> instead, and copy each ValueMap into this. Then I can use the full power of maps.

 

	public void copyProps(ValueMap from, HashMap<String,Object> to) {
		// ignore jrc: and sling: object properties.
		from.forEach((key, value) ->  {
			if (!key.startsWith("jcr:") && !key.startsWith("sling:"))  {
				to.put(key, value);
			}
		});
	}

 

 

 

I use the above code to convert ValueMaps into HashMaps, and to also combine several page components VAlueMaps into a single HashMap so I can send the page back as json (using Gson on the resultant master hashmap).

This relies on not using the same field names on each components properties. 

View solution in original post

4 Replies

Avatar

Level 9

In regards to a page which shows thumbnails and summary of recent played games.  The content comes from individual game info pages which have to be looked up by ID.

We need to send a page to the client to show the played games as json so it can be rendered in react.

First i search for the required game info pages using QueryBuilder.

Then, for each page found, I use QueryBuilder again to search for the required components the page.

This returns a ValueMap for the components properties.

Now I need to combine each components ValueMap into one ValueMap for the page, add a few additional ones (like the URL of the info page), so I can pass it back, and eventually convert it to JSON to the client.

I cant see a way to instantiate a new value map, in order to manually copy each item into it.

i tried pulAll but this gives a null pointer exception.

In the next reply, ill try pasting the code so far (trying to not let AEM delete this post)

 

Avatar

Level 9

Here is the current (non working) code:

 

		predicate.put("path", path);
		predicate.put("type", "cq:unstructured");
		predicate.put("group.1_property", "sling:resourceType");
		predicate.put("group.1_property.value", "mysite/components/gamemain");
		predicate.put("group.2_property", "sling:resourceType");
		predicate.put("group.2_property.value", "mysite/components/gameterms");
		predicate.put("group.p.or", "true");
		
		Query query = _builder.createQuery(PredicateGroup.create(predicate), session);
		
		// should only be 2 components!
		query.setStart(0);
		query.setHitsPerPage(20);
		
		SearchResult searchResult = query.getResult();
		
		ValueMap allProps = null;
		
		for(Hit hit : searchResult.getHits()) {
			ValueMap props = hit.getProperties();
			if (allProps == null) {
				allProps  = props;
			}  else {
				allProps.putAll(props);  // Fails with null pointer exception
			}
		}
 

Avatar

Level 9

Below is the code so far. If I try to put it in a code block AEM deletes the post.

 

                predicate.put("path", path);
                predicate.put("type", "cq:unstructured");
                predicate.put("group.1_property", "sling:resourceType");
                predicate.put("group.1_property.value", "mysite/components/gamemain");
                predicate.put("group.2_property", "sling:resourceType");
                predicate.put("group.2_property.value", "mysite/components/gameterms");
                predicate.put("group.p.or", "true");
                
                Query query = _builder.createQuery(PredicateGroup.create(predicate), session);
                
                // should only be 2 components!
                query.setStart(0);
                query.setHitsPerPage(20);
                
                SearchResult searchResult = query.getResult();
                
                ValueMap allProps = null;
                
                for(Hit hit : searchResult.getHits()) {
                        ValueMap props = hit.getProperties();
                        if (allProps == null) {
                                allProps  = props;
                        }  else {
                                allProps.putAll(props);  // Fails with null pointer exception
                        }
                }

Avatar

Correct answer by
Level 9

Seems that ValueMaps are immutable, even if you use .put() you will get run time errors.

Instead I change everywhere which used ValueMap to use HashMap<String,Object> instead, and copy each ValueMap into this. Then I can use the full power of maps.

 

	public void copyProps(ValueMap from, HashMap<String,Object> to) {
		// ignore jrc: and sling: object properties.
		from.forEach((key, value) ->  {
			if (!key.startsWith("jcr:") && !key.startsWith("sling:"))  {
				to.put(key, value);
			}
		});
	}

 

 

 

I use the above code to convert ValueMaps into HashMaps, and to also combine several page components VAlueMaps into a single HashMap so I can send the page back as json (using Gson on the resultant master hashmap).

This relies on not using the same field names on each components properties.