Sling Post Request creating child nodes - aem

Since you can post with sling via form with content application/x-www-urlformencoded. This seems to able to create only one node. If my encoded form has child nodes, how should the encoding look?
&./firstnode=value&./secondNode=value
If I want the secondNode to be the child of the first node, what should I do?

think of all the parameter names as subpaths of the node you're posting to. by default, a single slash would denote a property:
./property=value
to specify a node, you need to set a value under the target node:
./subnode/property=value
i think nt:unstructured is used by default in these cases, but you can explicitly set the nodetype by
./subnode/jcr:primaryType=TYPE&./subnode/property=val&...

ALL nodes that have to be created must be treated independently (counting parent nodes), even if the node is only a parent and doesn't have properties of its own. I am not confident that you can build an entire tree with a single post, because you usually need to save the parent before adding children.
The Sling website has a section on multipart/form-data POSTs for more details.

Related

cq5 not returning child pages json data on '...infinity.json' request

Even though following path http://localhost:4502/content/geometrixx/en/products.infinity.json returning folllowing json.
But same page request in my upper environments (DEV, Stage, QA boxes) returning following json
Can anyone shed some light on this ? I am trying to read child pages data for one of the component and it is working great in local but not in upper environment boxes.
Thank you!
Given that these are stage / production instances, it's possible that additional security measures were taken. If you look at the security checklist, you will see it recommends limiting number of nodes exposed by the Sling Get Servlet [0]:
https://docs.adobe.com/docs/en/aem/6-1/administer/security/security-checklist.html
So if the json.maximumresults property of the Apache Sling Get Servlet was set to 5, the page.infinity.json request won't return all the nodes in the tree.
If you have access to the instance's configuration manager (/system/console/configMgr), you can check the value of the json.maximumresults property for this servlet.
[0] https://github.com/apache/sling-org-apache-sling-servlets-get/blob/dd8af0d1d4c9666ffb16d5324a47e41ba413d973/src/main/java/org/apache/sling/servlets/get/impl/DefaultGetServlet.java#L126
The second response looks like you are hitting the jcr:content sub node directly
/content/geometrixx/en/products/jcr:content.infinity.json
The reason I say this, is that the response in your second request is the same as the graph beneath your jcr:content node in the first response.
If the request is the same, you might want to look at your resource mappings to see if something is modifying your request.

Web API Best Practice for Deep Object Routes

When designing a RESTful API with ASP.NET Web API, I can create several routes to retrieve the same data. But should I? Is it considered helpful or confusing?
For example, if I have an object relationship of Parent > Child > Item, I could potentially have three routes return the same individual item:
api/parents/:parent/children/:child/items/:item
api/children/:child/items/:item
api/items/:item
Is it useful to provide all three routes, or should it be limited to the simplest route to avoid confusion? Is there a best practice in this regard?
Choosing which URIs/routes to use is a matter of the desired purpose, not content. Is it possible or propable that a user would look for a child without having a specific parent in mind? If yes, offer the data in a seperate root URI, if not, restrict access to the child data by requiring the user to provide a parentId.
The URI api/children would return all children regardless of their parents and therefore fulfills another purpose than api/parents/:parentId/children which would only return the children the :parentId instance actually has a reference to. The result will always contain data that can also be obtained using api/children, but it carries additional information because these children 'belong' to the specified parent.
In my opinion all of your options are valid because they all have different purposes. However I would avoid using different URIs for the same purpose.
If the user has access to the lowest-level unique identifier (:item in your case), then they should just call
api/items/:item
the information about the parent would be redundant / irrelevant.
i would go:
api/parents
api/parents/:parentid
api/parents/:parentid/children
api/children
api/children/:childid
api/children/:childid/items
api/items
api/items/:itemid

Replace node along with subnodes in a single request

I have a widget that creates a POST request that creates a node and a dynamic number of subnodes, like:
./sling:resourceType:app/component
_charset_:utf-8
:status:browser
./data:data
./a/a:one
./a/b:two
./b/a:one
./b/b:two
This works nice the first time. I get a node along with subnodes a and b.
The problem is in subsequent requests. I need all subnodes to be removed before creating the new ones. So if previously I created subnodes a,b,c and d, the previous request would result just in subnodes a and b to remain.
I know the suffix #Delete,but I would need to know in advance which subnodes need to be deleted, which I don't.
Can this be achieved OOTB with the Sling Post Servlet?
Greetings.
In case you are using CQ 5.6 or 5.6.1 you can use ':applyTo' request parameter to delete multiple items using a single request by passing a trailing star in its value.
For example, to delete all the children of '/content/foo', make a POST request with ':operation' = 'delete', and ':applyTo' = '/content/foo/*'.
$ curl -F":operation=delete" -F":applyTo=/content/foo/*" http://host/content/sample
This was introduced in Sling 2.1.2 and hence is not available in CQ 5.5 and below, as 5.5 runs on 2.1.1.
For 5.5, i suspect you might need to get the list of children and then pass the absolute URL's to the :applyTo as the value to delete them, before adding the new nodes.
The solution I'm using is use the #Delete suffix.
The problem with it is that you need to add one parameter with the #Delete suffix for every node you want to delete. What I'm doing is query the node in advance to check for all the subnodes of the node I'm updating and adding a #Delete parameter for every one of them.
So, If the JCR originally has
-node
\node1
\node2
\node3
I will first get http://example.com/content/node.json and traverse the json. Finally I will send a request with
./sling:resourceType:app/component
./value:value
./node1#Delete
./node2#Delete
./node3#Delete
./node1/value:value1
./node2/value:value2
that will update node1 and node2 while deleting node3 at the same time.

Strategy to generate auto increment unique number in CQ

I have a requirement to create CQ pages programmatically. But the challenge is that the page name/uri should be autogenerated combination of a string + unique number (eg. PT2000, PT2001).
Can someone tell me a way way to generate an autoincrement-id/constant in CQ in a way that the id's are unique even with multiple concurrent request?
Use a service that provides you with the ID and that manages the counter inside a volatile instance variable to make sure that state changes by one thread are immediately communicated to all other threads.
This should do the trick as long as your can guarantee that your implementation runs on a single author node. In a cluster scenario you additionally have to care about executing it only on one node.
i'd suggest creating a service that manages its counters somewhere in the repository, and also acts as a jcr EventListener. the service should listen for NODE_ADDED events on parent nodes of type cq:Page, and once onEvent is called, it can assigned the unique id at that point. you'd want to use synchronization obviously so that overlapping calls to onEvent() won't use up the same id.
You can use a GUID, Graphic User ID, the ID generated has a great probablity of uniqueness.
See wiki reference http://en.wikipedia.org/wiki/Globally_unique_identifier
and to create GUID:
Create a GUID in Java
This will ease you effort to verify the number is unique so just generate the ID and create the pages with that ID.
Doesn't AEM automatically append numbers to same name pages?
If it doesn't, then presumably this would fail, at which point you start over with the next number. Best guess should be enough in this case.

REST and RDF, what's the representation strategy?

Your triplestore contains a lot of nodes, and you have to make accessible this database via a REST interface.
Now, my solution would be that every named (not-anonymous) node is exported as a resource, whose representation is:
all the triples having the node as a subject
all the triples having the node as an object
all the connected anonymous nodes.
I am a little reluctant on point number 2: this would basically give both incoming and outgoing triples.
What is your take on a REST sytle representation of a purely RDF-oriented data store ?
Do you share my point of view or not, and if not, what is your take on it ?
Depends on what the the data is and what the interface users want to do with it. This question is similar to what the SPARQL DESCRIBE query form should return. (It's determined by the implementation.)
For the use cases I've had with RDF data, I'd go with 1 and 3, producing a blank node closure of the resource. Additionally, you could have a separate interface for case 2, returning the incoming arcs of the resource.
One easy way to make an RDF dataset REST traversible is to use URLs for all traversible elements.
When the URL is accessed, for example via HTTP GET, then result shows the connected nodes (connected as properties and/or inverse properties).
More formally the returned representation could be a Concise Bounded Description of the resource.
(disclaimer: this may not correspond exactly to the content of your question, but it corresponds to the title)
I think that about the topic of Rest representation of RDF data is a general problem of inverting the order of concepts. For me the normal would be to have a collection of Rest documents with RDF data and use a RDF database for indexing and making global querys.
In this situation you can organize your resources in the way you prefer.
Also (if you pretend to use the URI of the node as the exported resource) your approach will have subtle problems about what is the meaning of your resources: the Rest resources you propose here are "information resources" and then they cannot be abstract resources. There will be a conflict between information and meta-information.
I published an article here explaining this view in more detail.