Showing posts with label JCR. Show all posts
Showing posts with label JCR. Show all posts

A solution for javax.jcr.lock.LockException

In one of my previous posts I showed how to connect to JCR using a simple
main() method , Java program
.
This is a simple program and should work fine in most of the cases.
But for some people it might throw a javax.jcr.lock.LockException.

Solution:

While connecting to the JCR we may use something like below.

 Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
This statement may sometimes lead to an error in applications like AEM.
To avoid this we need to mention the default environemnt we are logging into.

So we should USE THIS INSTEAD.

Session session = repository.login( new SimpleCredentials("admin", "admin".toCharArray()),"crx.default");



I would be happy to hear back from you. Please leave your suggestions in the comment section below. Cheers!!



JCR SQL 2 FULL Tutorial

JCR SQL2 Tutorial and Examples


Java content repository- Structured Query Language 2 better known as JCR-SQL2 is a new
specification which helps us to query data stored as properties under Nodes.It is a valuable tool for AEM developers to have a knowledge of this.

This article will explain various JCR queries in detail.
A basic understanding of SQL is a plus but now a mandate. Read on folks....


The 'SELECT' statement.

The first newbie command that we all try our hands on first. :)


i. Select Everything

SELECT * FROM [nt:base]
Selects every node from the content repository. This is because nt:base is the base type for all JCR nodes.




ii. Select Nodes of given type.

SELECT * FROM [my:type]
SELECT * FROM [nt:file]
SELECT * FROM [cq:Page]

The 1st query collects all nodes of jcr:PrimaryType = my:Type
The 2nd collects nodes where jcr:PrimaryType = nt:File, this is generally required to collect all nodes of nt:File type.
The 3rd collects all nodes of jcr:PrimaryType = cq:Page,is commonly used in Adobe Experience Manager to collect Pages.




iii. Find Nodes by Name

SELECT * FROM [nt:base] As nodes WHERE NAME(nodes) = 'jcr:content'
This will select all nodes of type nt:base having the name "jcr:content".




iv. Finding Nodes Under a path.

SELECT * FROM [nt:unstructured] As node WHERE ISDESCENDANTNODE ([/content/myProject])
This will return all nodes of type nt:unstructured under the given path /content/myProject




v. Finding Nodes Under MULTIPLE paths.

SELECT * FROM [nt:unstructured] AS s WHERE (ISDESCENDANTNODE('/content/myProject/Path1') 
or 
ISDESCENDANTNODE('/content/myProject/Path2'))
This will return all nodes of type nt:unstructured under 2 given paths /content/myProject/Path1 and /content/myProject/Path2




vii. Find Nodes based on property value.

SELECT * FROM [nt:base] AS nodes WHERE CONTAINS(nodes.title, 'news')
This will find all the nodes under the repository whose title contains the word "news". This can also be done using the LIKE clause but is not very efficient and hence slow.
SELECT * FROM [nt:base] AS nodes WHERE nodes.title LIKE 'news'




viii. Find Nodes based on MULTIPLE property values.

SELECT * FROM [nt:unstructured] WHERE title = 'fruit' AND color = 'red'
This will find all the nt:unstructured nodes under the repository whose title contains the word "fruit"
and has the color property as "red". You can also use the CONTAINS and LIKE clause here if you want to, just like the previous example.




The JCR 'LIKE' Clause

The LIKE clause is generally used for matching the attribute values.



i. Finding Nodes with exact match in title.

SELECT * from [cq:Page] where title LIKE 'News'
This will return all the nodes of type cq:Page where there is a title attribute EXACTLY Matching the word "News".




ii.Finding Nodes whose title contains a word/phrase.

SELECT * from [cq:Page] where title LIKE '%News%'
This will return all the nodes of type cq:Page where there is a title attribute WHICH CONTAINS the word "News".




iii. Finding files which matches the given file extension.

SELECT * FROM [nt:file] WHERE NAME() LIKE '%.txt'
This is used to find all the nodes of type nt:file whose name has a (.txt) file extension (text files).

SELECT [jcr:primaryType], [jcr:created], [jcr:createdBy], [jcr:path] FROM [nt:file]
WHERE LOCALNAME() LIKE '%.png'
Similarly the above query selects some attributes of the nt:file node for all files having the (.png) extension.




iv. Find Nodes under a given path.

SELECT * FROM [my:type] WHERE PATH([my:type]) LIKE '/content/myProject'
This will return all nodes of type "my:Type" under the path /content/myProject/.




v. Find Nodes under a given path and its subtree.

SELECT * FROM [my:type] WHERE PATH([my:type]) LIKE '/content/myProject/%'
This will return all nodes of type "my:Type" under the path /content/myProject/ and all its subtrees /content/myProject/*




The Jcr 'IS NOT NULL' Property

The 'IS NOT NULL' property is used to check for NON NULL values.

SELECT * FROM [my:type]WHERE [my:type].prop1 IS NOT NULL

SELECT * from [cq:Page] where image IS NOT NULL

In both the above queries the result is a set of node where the given properties is not null.
So if the values of the property is NULL in any case then the results will not be returned by the query. This means that the query will overlook any node having no value for the given property.





The JCR 'Order By' Clause

SELECT * FROM [nt:unstructured] WHERE ISDESCENDANTNODE ([/content/myProject]) 
ORDER BY [jcr:lastModified]
This will return all the nodes of type nt:unstructured in the given path /content/myProject ordered by the last modified time in increasing order.

Decreasing Order:
SELECT * FROM [nt:unstructured] WHERE ISDESCENDANTNODE ([/content/myProject]) 
ORDER BY [jcr:lastModified] DESC




JCR Query using Dates

SELECT * FROM cq:PageContent AS s
WHERE s.[jcr:created] >= CAST('2015-01-01T00:00:00.000Z' AS DATE)
AND s.[jcr:created] < CAST('2016-01-01T00:00:00.000Z' AS DATE)
This query will find all the nodes of type cq:PageContent which has been created between the given two dates.
This shows you how to query using dates in JCR SQL2.



JCR SQL2 'CAST' Property Values


BOOLEAN:


SELECT * FROM [my:type] WHERE prop1 = CAST('true' AS BOOLEAN)

SELECT * FROM [nt:unstructured] WHERE hideInNav = CAST('true' AS BOOLEAN)


LONG:

SELECT * FROM [my:type] WHERE PATH([my:type])> LIKE '/content/%' AND DEPTH([my:type]) = CAST(2 AS LONG)


DATE:

SELECT * FROM cq:PageContent AS s
WHERE s.[jcr:created] >= CAST('2015-01-01T00:00:00.000Z' AS DATE)
AND s.[jcr:created] < CAST('2016-01-01T00:00:00.000Z' AS DATE)
The examples above shows some JCR SQL2 queries using CAST property.
The CAST property can be used for the following datat types.
BINARYDOUBLEREFERENCE
BOOLEANLONGSTRING
DATENAMEURI
DECIMALPATHWEAKREFERENCE



How to Set a Node property in JCR

How to Add a Node property in JCR 
To set the property of a Node in JCR or AEM we can use the following code snippet in Java.
This uses the
javax.jcr.Node.setProperty(String propertyName, String propertyValue)
function to achive the desired task.

node.setProperty("propertyName","propertyValue");

Here's how to delete a Node property in JCR.



How to delete a Node property in JCR 

When you are working on AEM tool or with any JCR repository based environment, it is sometimes a requirement to add and delete properties of a node.

Heres how to add a property to a node in JCR.

To delete a property of a Node in JCR we can use either of the the following code in Java.

1. Get the property and remove it by calling the remove() method over the Node property.


node.getProperty("propertyName").remove();

2. Set the property to NULL in this manner. (Do not try to set it directly without typecasting)


node.setProperty("propertyName",(Value)null);

How to query JCR data in Adobe AEM

Different handy techniques to write JCR query in AEM/CQ:

For a Detailed Study on JCR Queries Please see this Article.
JCR SQL 2 FULL Tutorial: CHEAT SHEET

Java content repository, better known as JCR is a modern approach to our database solutions.
While working on JCR I found many rather simple techniques to write JCR queries from our JAVA application.
Some of them have been described below to help fellow developers.

For this example we will try to fetch all the "employee" nodes under the "codermagnet" parent node.


How to query JCR data in Adobe AEM



Download the Jack Rabbit Jar File form
http://www.apache.org/dyn/closer.cgi/jackrabbit/2.8.1/jackrabbit-standalone-2.8.1.jar
and place the Jack Rabbit jar in build path of your project.


OPTION 1: Quering JCR using QueryManager API

Create a new class file as shown below.

File: JCRQueryExample.java
package net.codermag.jcr.test;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.query.Query;
import javax.jcr.query.QueryManager;
import javax.jcr.query.QueryResult;

import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.core.TransientRepository;

public class JCRQueryExample {

 
 public static void main(String[] args) throws Exception {
  
  // Create a Session
  Repository repository = new TransientRepository();
  repository = JcrUtils.getRepository("http://localhost:4502/crx/server");
  Session session = repository.login(new SimpleCredentials("admin","admin".toCharArray()));
  
  
  
  //Building and Executing the Query
  QueryManager queryManager = session.getWorkspace().getQueryManager();
  String sqlStatement = "SELECT * FROM [nt:base] AS s WHERE ISDESCENDANTNODE([/content/codermagnet/employees])";
  Query query = queryManager.createQuery(sqlStatement, "JCR-SQL2");
  QueryResult result = query.execute();
  
  
  
  
  //Doing Something with the nodes returned.. Printing the paths
  NodeIterator iterator = result.getNodes();
  while (iterator.hasNext()) {
   System.out.println(((Node) iterator.next()).getPath());
  }

 }
}


Output:
/content/codermagnet/employees/kuper
/content/codermagnet/employees/john
/content/codermagnet/employees/harry
/content/codermagnet/employees/smith


OPTION 2: Quering JCR using ResourceResolver.findResources() method.

Another very handy and short way of doing this is illustrated below.This is my favorite as its a one liner query and is cute, clean and fast. One point that we need to remember while doing this is that for this second option we need the implicit "ResourceResolver" object. So this is more appropriate to be used as some sort of sling service inside our JCR application.

File: JCRQueryExample2.java

package net.codermag.jcr.test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.jcr.Node;
import javax.jcr.query.Query;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;

public class JCRQueryExample2 {

 public List<Node> getNodes(SlingHttpServletRequest request)
   throws Exception {

  List<Node> nodes = new ArrayList<Node>();
  ResourceResolver resolver = request.getResourceResolver();

  
  // Executing query in One Line....!!!!
  Iterator<Resource> nodeIter = resolver
    .findResources("SELECT * FROM [nt:base] AS s WHERE ISDESCENDANTNODE([/content/codermagnet/employees])",
      Query.JCR_SQL2);

   
  // Converting the Resource object to Node and then storing as arraylist
  while (nodeIter.hasNext()) {
   nodes.add(nodeIter.next().adaptTo(Node.class));
  }
  return nodes;
 }
}



Option 3: Quering JCR using QueryBuilder API

File:JCRQueryExample3.java

Note: For testing the below XPATH query before hand you can use the QueryBuilder debugger console at this URL
http://:/libs/cq/search/content/querydebug.html



package com.realogy.sir.core.servlets;

import java.util.HashMap;
import java.util.Map;
import javax.jcr.Session;
import org.apache.sling.api.SlingHttpServletRequest;
import com.day.cq.search.PredicateGroup;
import com.day.cq.search.Query;
import com.day.cq.search.QueryBuilder;
import com.day.cq.search.result.Hit;
import com.day.cq.search.result.SearchResult;


public class JCRQueryExample3 {

 public void getNodes(SlingHttpServletRequest request)throws Exception {

  
  //Form the map and fill all the required parameters in the map
  Map<String,String> map = new HashMap<String,String>();
  map.put("path", "/content/codermagnet/employees");
  map.put("type", "nt:base");
  map.put("orderby","@name");
  
  
  //Quering JCR using com.day.cq.search.QueryBuilder API
  PredicateGroup predicateGroup = PredicateGroup.create(map);
  QueryBuilder builder = request.getResourceResolver().adaptTo(QueryBuilder.class);
  Query query = builder.createQuery(predicateGroup, request.getResourceResolver().adaptTo(Session.class));
  SearchResult result = query.getResult();
  
  

  //Do something with the results
  for (Hit hit : result.getHits()) {
   String path = hit.getPath();
   System.out.println(path);
  } 
 }
}


Output:

/content/codermagnet/employees/harry
/content/codermagnet/employees/john
/content/codermagnet/employees/kuper
/content/codermagnet/employees/smith


You can use Option 2 and Option 3 when writing servlets or inside scriplet tags in AEM JSP pages where you have access or can derive the "resourceResolver" implicit object. In the above option I have derived the "resourceResolver" object from the org.apache.sling.api.SlingHttpServletRequest that is passed to the method.

For a Detailed Stydy on JCR Queries Please see this Article.

JCR SQL 2 FULL Tutorial: CHEAT SHEET

Store data in remote AEM JCR repository.

We can store data in the AEM's data repository i.e. the JCR repository very easily as shown below in the code sample. Only thing we have look out for is the username and the password we are using to access the repository.
Sometimes we do not have permission for writing to the JCR in those cases this will not work.
Here I am using the "Administrator" login for writing data into the AEM JCR.

Please make necessary changes to the port and the host URL as required.

This creates a node in AEM under the "content" folder as shown here.


The properties that will be set is shown below.


Step1:
Download the Jack Rabbit Jar File form 
and place the Jack Rabbit jar in build path of your project.


Step 2:
Create and execute a class as shown below.

File: StoreData.java

package net.codermag.jcr.test;

import javax.jcr.Node;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;

import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.core.TransientRepository;

public class StoreData {

 public static void main(String[] args) throws Exception {
  
  Repository repository = new TransientRepository();
  repository = JcrUtils.getRepository("http://localhost:4502/crx/server");

  // Create a Session
  Session session = repository.login(new SimpleCredentials("admin","admin".toCharArray()));

  // Create a node that represents the root node. For this you need root permission.
  Node root = session.getRootNode();

  
  // Getting the content node (This can be any node like etc/bin....)
  Node contentNode = root.getNode("content");
  
  

  if (contentNode.hasNode("codermagnet")) {

   Node coderMagnetNode = contentNode.getNode("codermagnet");
   
   //Setting the primary type. This can be any of the primary properties that AEM supports
   coderMagnetNode.setPrimaryType("nt:unstructured");

   coderMagnetNode.setProperty("name", "John Doe");
   coderMagnetNode.setProperty("email", "John@mail.com");
   coderMagnetNode.setProperty("isEmployed", true);
   coderMagnetNode.setProperty("roles", new String[] { "Manager","Admin", "Developer" });

   
   
   System.out.println("Data has been set..!");
   

  } else {
   System.out.println("Node Not Found..!");
  }

  session.save();

 }
}



Output:



Data has been set..!





Connect to JCR repository using a simple Java main method.

When using Adobe Experience Manager (CQ) as our content management tool we sometimes need to connect to a AEM JCR repository from our integrated development environment (IDE) like Eclipse or NetBeans.

The following code shows a simple executable Java program for connecting to any AEM JCR Repository using a main() method. This can be used to connect to any remote or local JCR repository.

The Steps to do so are as follows:-

Step1:
Download the Jack Rabbit Jar File form
http://www.apache.org/dyn/closer.cgi/jackrabbit/2.8.1/jackrabbit-standalone-2.8.1.jar
and place the Jack Rabbit jar in build path of your project.


Step 2:

File: ConnectJCR.java

package net.codermag.jcr.test;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;

import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.core.TransientRepository;

public class ConnectJCR {

 public static void main(String[] args) throws Exception {
  Repository repository = new TransientRepository();
  repository = JcrUtils.getRepository("http://localhost:4502/crx/server");

  // Create a Session
  Session session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
  //If you get javax.jcr.lock.LockException please use the line below
  //instead of the above one
  //Session session = repository.login( new SimpleCredentials("admin", "admin".toCharArray()),"crx.default");
  
  // Create a node that represents the root node
  Node root = session.getRootNode();
  Node content = root.getNode("content");
  Node subContent = content.getNode("dam");
  
  
  //Getting the iterator over the nodes
  NodeIterator childNodeIterator = subContent.getNodes();
  
  
  
  //Iterating over the nodes and printing their names
  while(childNodeIterator.hasNext()){
   Node childNode=(Node) childNodeIterator.next();
   System.out.println(childNode.getName());
   
  }
 }
}



javax.jcr.lock.LockException: Precondition Falied

If you are getting the javax.jcr.lock.LockException with the above program then please
follow this link
http://www.codermag.net/2016/10/how-to-fix-javax-jcr-lock-lockexception-precondition-failed.html