How to create a cq5 page programatically from external environment? - content-management-system

We planned to create a CQ5 website from other cms, as per the requirements it has appx 1000 pages.It will take huge to time to create a page and author the content manually.So we decided to write utility for each template to create a page and author content.
It can be possible to write a utility inside CQ5 by using WCM API. But I want this to done from external environment i.e., outside CQ5. I have wrote the code but I couldn't get the ResourceResolver object in my java main its showing null pointer exception.
Please suggest me a way to achieve this It would be appreciated.

Well, you have to first get access to the JCR repository. Link here
By making an Authenticated Request you can then save the data to CQ. I would suggest using JCROM or sling models to create your DAO and models and then do a post request to save the data in JCR. You can use workflows as well in the process to save the data.

You could simply create new pages via a POST to the CQ instance, as long as the authenticated user has the required rights. Manipulating content illustrates what can be done.
Here is a small example.
curl -u admin:admin \
-F"jcr:primaryType=cq:Page" \
http://localhost:4502/content/geometrixx/en/index
curl -u admin:admin \
-F"jcr:primaryType=cq:PageContent" \
-F"sling:resourceType=geometrixx/components/homepage" \
-F"jcr:title=My new Homepage" \
http://localhost:4502/content/geometrixx/en/index/jcr:content
creates a new page and its jcr:content node. Creating components works that way as well.
A different approach would be, creating the required content structure in XML and import it.
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Page">
<jcr:content
cq:lastModified="{Date}2015-03-09T21:05:46.442Z"
cq:lastModifiedBy="admin"
jcr:primaryType="cq:PageContent"
jcr:title="My new Homepage"
sling:resourceType="geometrixx/components/homepage"/>
</jcr:root>
Using the simple-content-package-archetype you could create content programmatically and deploy it on the server easily.

Related

APIs Explorer's Firestore's projects.databases.documents.list has incorrect regex

Summary: APIs Explorer "Try this API" for projects.databases.documents.list appears (!?) to have an overly restrictive/incorrect regex on parent and requirement on collectionId.
Neither gcloud firestore nor firebase firestore: provides functionality to list collections, I'm planning to write a simple app to do so.
As always, I explored the APIs methods using the excellent APIs Explorer but the projects.databases.documents.list "Try this API" appears (!?) to have an overly restrictive|incorrect regex on parent.
The documentation correctly states that:
https://firestore.googleapis.com/v1/{parent=projects/*/databases/*/documents/*/**}/{collectionId}
And:
Required. The parent resource name. In the format:
projects/{project_id}/databases/{database_id}/documents or
projects/{project_id}/databases/{database_id}/documents/{document_path}.
For example: projects/my-project/databases/my-database/documents or projects/my-project/databases/my-database/documents/chatrooms/my-chatroom
Using Google's first format example: projects/my-project/databases/my-database/documents does not work:
APIs Explorer only accepts the second format example for parent but then requires a value for collectionId which may not be desired:
APIs Explorer appends collectionId to the parent to from the URL. In the case of parent ending /documents (which isn't permitted), this would make sense to access the chatrooms collection or in the case that parent ends /documents/chatrooms/my-chatroom to then get the messages collection (with my-chatroom) but the requirement prohibits using APIs Explorer (!) to query projects/my-project/databases/my-database/documents/chatrooms; collectionId is required and would need to be chatrooms but a parent of projects/my-project/databases/my-database/documents is not permitted.
Using one of my projects (${PROJECT}) and (default) for {database_id}, I can use the documentation's examples correctly in curl:
TOKEN=$(gcloud auth print-access-token)
PROJECT=...
PARENT=projects/${PROJECT}/databases/(default)/documents
COLLECTION=...
curl \
--header "Authorization: Bearer ${TOKEN}" \
--header 'Accept: application/json' \
--write-out '%{response_code}' \
--output /dev/null \
--silent \
https://firestore.googleapis.com/v1/${PARENT}/${COLLECTION}
200
The APIs works correctly navigating down through subcollections too.
Posting this here in the hopes that, if APIs Explorer is indeed incorrect, fixing it can help other developers not encounter this issue and be discouraged.
Note: Since I'm posting feedback, the tool doesn't correctly adjust cURL, HTTP or JavaScript generated examples to reflect the checkbox value on "API Key"; when the "API Key" is deselected, the parameter should not be included in the calls.
It seems to be a problem with the regular expression in the API explorer. I need to enter the parent as projects/fire-template-24/databases/(default)/documents/users/ (including the forward slash) and also enter the collectionId as it's required (users in my case). This seems to be making a query at:
https://[GOOGLE+APIS_URL]/projects/[ID]/databases/(default)/documents/users//users?key=[API_KEY]
This returns an error about the extra trailing slash which the API explorer forced me to add and collectionId field is also appended to it with another /.
The following regular expression seems to be working:
^projects\/[^/]+\/databases\/[^/]+\/documents(\/[^/]+(\/[^/]+\/[^/]+)*)$
The above RegEx doesn't required a forward slash in parent and matches a collection path only. If the collectionId is removed then it should work. Working example of the RegEx can be found here.
I could also observe the same in the API explorer page. I observed that there is an existing issue in the Public Issue Tracker for the same. As mentioned in the #2 comment of the issue, this issue report has been forwarded to the Firestore Engineering team to investigate, but there is no ETA for a resolution. I would suggest you star the issue so that you will get notified whenever there is any update on the issue.

How to create a child page in Confluence by copying an existing page and using the REST API

I use the following code to create a child page under an existing parent:
curl -v -u admin:password -X POST -H 'Content-Type: application/json' -d'{"type":"page","title":"Created by API", "ancestors":[{"id":97585021}], "space":{"key":"Some_Key"},"body":{"storage":{"value":"<p>This is a test page created by API. Pls ignore</p>","representation":"storage"}}}' https://confluence.ges.symantec.com/rest/api/content/ | python -mjson.tool.
Using this I'm successfully able to create a child page under the parent content id 97585021.
What I would like to do next is: create a page under the parent id 97585021 using another page that acts as a template. The template page is in Confluence under the same content id 97585021. So I would like all pages to be created as a copy of this page.
How can I achieve this?
First step, simply get the page body content of your template in Confluence:
https://confluence.ges.symantec.com/rest/api/content/1234?expand=body.storage
Ref.: https://docs.atlassian.com/confluence/REST/latest/#content-getContentById
With the extracted body content, make some modifications if necessary, and finally create your child page by doing the exact same request you did.

updated json file not showing in public link

I got some problem when updating my json file which located in a bucket, and will be called by a html page. I will update my json file every 5 minutes from the command line, and this can be done. However, even though the json file itself is updated and set to be public, the public link is still showing the old content not the new content.
If I click the json file, I can see that the content has been changed, but if I click the public link, the content still remains not updated.
Does anybody know how much time it takes for Google Cloud Storage to load the buffer so that the new content will be shown in the public link?
Or is there any method to update the json file and get the public link updating instantly?
Thank you!
By default, publicly visible objects accessed anonymously have a cache-control header set to 1 hour. You can override this when you upload a new object by explicitly setting the cacheControl metadata to something else.
If you're using gsutil to upload the object, you could do it like this:
gsutil -h "Cache-Control:no-cache, max-age=0" \
cp -a public-read myfile.json gs://mybucket

dotCMS REST API fetch template by its id

I consider using dotCMS and integrate it with other system by its rest API but in spite of ability to fetch content by its api I cannot fetch tempates defined in dotCMS.
With url api/content/type/xml/id/c12fe7e6-d338-49d5-973b-2d974d57015b I obtain as response following xml:
<contentlets>
<content>
<template>1763fa6e-91c0-464e-8b16-9a25d7ae6ce5</template>
<modDate>2015-12-10 10:58:56.098</modDate>
<cachettl>15</cachettl>
<title>About Us</title>
<httpsreq/>
<showOnMenu>true</showOnMenu>
<inode>84e2879a-7749-40f4-bded-9d59dbb2b1da</inode>
<____DOTNAME____>About Us</____DOTNAME____>
<disabledWYSIWYG>[]</disabledWYSIWYG>
<seokeywords>dotCMS Content Management System</seokeywords>
<host>48190c8c-42c4-46af-8d1a-0cd5db894797</host>
<lastReview>2015-12-10 10:58:56.093</lastReview>
<stInode>c541abb1-69b3-4bc5-8430-5e09e5239cc8</stInode>
<owner>dotcms.org.1</owner>
<friendlyname>About Us</friendlyname>
<identifier>c12fe7e6-d338-49d5-973b-2d974d57015b</identifier>
<redirecturl/>
<canonicalUrl/>
<pagemetadata>dotCMS</pagemetadata>
<languageId>1</languageId>
<seodescription>
dotCMS Content Management System demo site - About Quest
</seodescription>
<folder>1049e7fe-1553-4731-bdf9-ba069f1dc08b</folder>
<sortOrder>0</sortOrder>
<modUser>dotcms.org.1</modUser>
</content>
</contentlets>
Is there any possibility to fetch template by its id (here 1763fa6e-91c0-464e-8b16-9a25d7ae6ce5) and obtain html file as response or some xml with html content?
Ok so after some hours of source code analysis I think I can assume that there is no rest api implemented by dotCMS. Instead of this we can use java api and fetch such components like templates, containers etc. by calling methods which are responsible for fetching these components from database. Then we can implement our own rest services.
Templates in dotCMS govern the display of "pages" which can be made up of multiple content objects. If you want to return a content object that has formatting applied to it, take a look at the widget API here:
http://dotcms.com/docs/latest/remote-widgets
and how it can be used here:
http://dotcms.com/docs/latest/remote-widgets

AEM:: Error Handling using the acs-aem-commons package

As defined here http://adobe-consulting-services.github.io/acs-aem-commons/features/errorpagehandler.html I am trying to confgure error pages for my application. Here is what I have done:
1) Created 404.jsp and default.jsp at /apps/sling/servlet/errorhandler as defined on the page.
2) Added below widget to the advanced tab:
<errorpages
jcr:primaryType="cq:Widget"
path="/apps/acs-commons/components/utilities/errorpagehandler/dialog/errorpages.infinity.json"
xtype="cqinclude"/>
3) Created /apps//config/com.adobe.acs.commons.errorpagehandler.impl.ErrorPageHandlerImpl.xml
with the following properties:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="sling:OsgiConfig"
prop.enabled="{Boolean}true"
prop.error-page.fallback-name="500"
prop.error-page.system-path="/content/error"
prop.error-page.extension="html"
ttl="{Long}300"/>
4) Created /content/myapp/en/errors using a fresh template. The template has only a parsys. Inside the /content/myapp/en/errors, I have created page 404 and 500 using the same template. In the video it is shown that when the speaker opens the pages 404.html and 500.html created under geometrixx from siteadmin he is able to see appropriate error messages. What I am not able to understand is that if my template consists of only a parsys how will the 404 and 500 pages show the error messge. From where are those messages being generated ? Am I missing something here ? Do I have to create any component ?
5) In the Page Properties of the page /content/myapp/en , I have configured /content/myapp/en/errors as the Error Page. To generate a 404 error when I try to access the URL /content/myapp/ent.html instead of /content/myapp/en.html it throws a
No resource found
Cannot serve request to /content/myapp/ent.html in /apps/sling/servlet/errorhandler/404.jsp
Not sure how do I get he nice looking pages as shown in the video.
5) How can I make the error messages authorable ?
Thanks in advance
No need to follow so many steps. The ACS commons package with the error handler is available as a package. Down load this package from This ACS commons git hub site
The name of the file is --> acs-aem-commons-content-1.9.6.zip(2.3 MB).
Then just create sling:OsgiConfig node in your /apps/myapp/config with
name --> com.adobe.acs.commons.wcm.impl.ComponentErrorHandlerImpl. Then put the below configuration into the node.
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="sling:OsgiConfig"
prop.edit.enabled="{Boolean}true"
prop.edit.html="/apps/acs-commons/components/utilities/component-error-handler/edit.html"
prop.preview.enabled="{Boolean}false"
prop.preview.html="/apps/acs-commons/components/utilities/component-error-handler/preview.html"
prop.publish.enabled="{Boolean}false"
prop.publish.html="/dev/null"
/>
Below is the configure component in crxde lite
Thats all. You need not do anything else.You will get proper error pages or messages for all 500 or 404 errors
As you said in 5th step In the Page Properties of the page /content/myapp/en , you have configured /content/myapp/en/errors as the Error Page. This error pages are work for for child pages under this path /content/myapp/en . In your case it will be work for all the childs under /content/myapp/en/*.html
Ex. It will work for /content/myapp/en/{invalidurl}.html
The question was about the page error handler, the answer is provided about in: component error handler. These two different things altogether.
the CEH handles the exception in component scope where as EPH handles it in request scope
when component fails and the exception is not handled by CEH and response is written as 500, it will be handled by EPH
For point 4) The template has only a parsys.
Yes you have to configure the components and place them in the parsys as you would do for your content pages that will display in case of error pages. The error handler gives you the flexibility to modify what shows up in error pages by keeping them authorable. You can change the look and feel of error pages for each of the valid HTTP errors.
For example, whatever I create in my content/error/404.html page will show up when the actual 404 is returned by the errorhandler.
In case of an invalid URL:
For point 5) In the Page Properties of the page /content/myapp/en , I have configured /content/myapp/en/errors as the Error Page. To generate a 404 error when I try to access the URL /content/myapp/ent.html instead of /content/myapp/en.html it throws an error.
The mistake that you did here was that you are trying to access a parent page url.
One solution would be to place the custom error pages at a level higher than the content pages for your website.
You can do this more than once. As in keep separate error page for global errors, some other for myapp, some others for myapp/en and so on.
So if you have seen there is a tab in page properties where you can author the error pages root url. This can be leveraged to give different URLs as per requirement.
For example,
If you want an error page for /content/myapp/ent.html then place a separate set of error handler pages at content/myapp in addition to those at content/myapp/en.
Then goto myapp.html and in Page Properties override the error page url to content/myapp/error.
For each parent whenever you need a separate error page url author those in page properties.
So now I have two renditions of my error page: One for content/myapp and other for content/myapp/en
As shown below:
path - /content/test.html (Global)
path - /content/myapp/ent.html (Myapp):
Config node:
Sample template to show the difference: