Hi All,
In order to avoid the below error, I am creating resourceresolver and session at every place(all methods) and closing it at the end of method in finally block.. Sample piece of code for creating and closing resourceresolver and session in single method
I am doing lot of operations(remove node, add/modify/delete property under the node) in 30 different methods. Whether it will cause any performance issue if we creating and closing resourceresolver and session at 30 methods.
Error:
01.01.2016 09:21:56.916 *WARN* [0:0:0:0:0:0:0:1 [1424679716845] GET /content/geometrixx/en/services.html HTTP/1.0] org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate Attempt to perform hasProperty while another thread is concurrently reading from session-494. Blocking until the other thread is finished using this session. Please review your code to avoid concurrent use of a session.
java.lang.Exception: Stack trace of concurrent access to session-494
at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.perform(SessionDelegate.java:276)
at org.apache.jackrabbit.oak.jcr.session.ItemImpl.perform(ItemImpl.java:113)
at org.apache.jackrabbit.oak.jcr.session.NodeImpl.hasProperty(NodeImpl.java:812)
at org.apache.sling.jcr.resource.JcrPropertyMap.read(JcrPropertyMap.java:350)
Sample piece of code :
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session = resolver.adaptTo(Session.class);
Node test= session.getNode("/content/dam");
updateproperty(test);
session.save();
}
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
Solved! Go to Solution.
Please follow below post for best use of resource resolver
Views
Replies
Total Likes
Make sure that these session and resolver variables are also declared locally.
Personally I tend to avoid to 'create' sessions, but use the one attached from the request/user.
Also using ModifiableValueMap will make things easier.
Views
Replies
Total Likes
As @Jitendra mentioned, it really depends on how and what are you doing with session. Best practice is to create and close the session where ever necessary instead of creating it globally !
Views
Replies
Total Likes
Thanks for your reply..
Scenario :
Copying child nodes from particular node(/content/old/node1) and replacing child nodes under path /content/new/node1.Also doing add/modify/delete property under the node /content/new/node1 and its child nodes.
Similarly (/content/old/node2) to (/content/new/node2)
(/content/old/node3) to (/content/new/node3)
(/content/old/node4) to (/content/new/node4)
I am doing the above four operation at same time(creating job for each process /content/old/node1 to /content/new/node1). Four job is running parallel.
Initial call came to job class and it is directing to job service. In job service, I created resourceresolver
from resourceresolverfactory(org.apache.sling.api.resource) and made resourceresolver as global variable for creating session at various private lower level methods.
Example:
Private ResourceResolver resolver
Class Jobservice(){
public void mainmethod(){
resolver = resourceresolverfactory.getServiceResourceResolver(null);
String path = "/content/old/node1";
lowerMethod1(path)
}
private void lowerMethod1(String path){
Session session= resolver.adapt(Session.class);
Node destinationNode = session.getNode("/content/new/node1");
deleteAllCHildNodes(destinationNode);
updateProperty(destinationNode);
}
private void deleteAllCHildNodes(Node destNode){
Session session= resolver.adapt(Session.class);
---deleting all childnodes under destNode----
session.save();
}
Likewise I am doing different operation under /content/new/node1. I was getting concurrent access error and invaliditemstateexception(item doesi not exist anymore) at the different places in my code
because four jobs are running parallel and performing operation under the respective node. I came to know that sessions are
opening long time by google search(https://cqdump.wordpress.com/2015/03/02/aem-scaling-patterns-avoid-shared-sessions/) abt this issue.
Also changes done for node1 in session1(first job) will not be available in session2(opened in second job).
In order to avoid this error, I am creating resourceresolver and session at lower level methods and closing at the end of method itself(Session is opening for short duration) as below
Class Jobservice(){
public void mainmethod(){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session = resolver.adaptTo(Session.class);
String path = "/content/old/node1";
lowerMethod1(path);
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
private void lowerMethod1(String path){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session = resolver.adaptTo(Session.class);
Node destinationNode = session.getNode("/content/new/node1");
deleteAllCHildNodes(destinationNode);
updateProperty(destinationNode);
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
private void deleteAllCHildNodes(Node destNode){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session= resolver.adapt(Session.class);
---deleting all childnodes under destNode----
session.save();
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
Kindly share your thoughts on this one.. whether it is good practice to do create and close resourceresolver and session in single method and it will cause any performance issue because mostly maximum no of jobs(10) will run in parallel.
Please suggest any other ideas to handle the concurrent issue if my idea is not good.
Views
Replies
Total Likes
Thanks for your reply..
Scenario :
Copying child nodes from particular node(/content/old/node1) and replacing child nodes under path /content/new/node1.Also doing add/modify/delete property under the node /content/new/node1 and its child nodes.
Similarly (/content/old/node2) to (/content/new/node2)
(/content/old/node3) to (/content/new/node3)
(/content/old/node4) to (/content/new/node4)
I am doing the above four operation at same time(creating job for each process /content/old/node1 to /content/new/node1). Four job is running parallel.
Initial call came to job class and it is directing to job service. In job service, I created resourceresolver
from resourceresolverfactory(org.apache.sling.api.resource) and made resourceresolver as global variable for creating session at various private lower level methods.
Example:
Private ResourceResolver resolver
Class Jobservice(){
public void mainmethod(){
resolver = resourceresolverfactory.getServiceResourceResolver(null);
String path = "/content/old/node1";
lowerMethod1(path)
}
private void lowerMethod1(String path){
Session session= resolver.adapt(Session.class);
Node destinationNode = session.getNode("/content/new/node1");
deleteAllCHildNodes(destinationNode);
updateProperty(destinationNode);
}
private void deleteAllCHildNodes(Node destNode){
Session session= resolver.adapt(Session.class);
---deleting all childnodes under destNode----
session.save();
}
Likewise I am doing different operation under /content/new/node1. I was getting concurrent access error and invaliditemstateexception(item doesi not exist anymore) at the different places in my code
because four jobs are running parallel and performing operation under the respective node. I came to know that sessions are
opening long time by google search(https://cqdump.wordpress.com/2015/03/02/aem-scaling-patterns-avoid-shared-sessions/) abt this issue.
Also changes done for node1 in session1(first job) will not be available in session2(opened in second job).
In order to avoid this error, I am creating resourceresolver and session at lower level methods and closing at the end of method itself(Session is opening for short duration) as below
Class Jobservice(){
public void mainmethod(){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session = resolver.adaptTo(Session.class);
String path = "/content/old/node1";
lowerMethod1(path);
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
private void lowerMethod1(String path){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session = resolver.adaptTo(Session.class);
Node destinationNode = session.getNode("/content/new/node1");
deleteAllCHildNodes(destinationNode);
updateProperty(destinationNode);
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
private void deleteAllCHildNodes(Node destNode){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session= resolver.adapt(Session.class);
---deleting all childnodes under destNode----
session.save();
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
Kindly share your thoughts on this one.. whether it is good practice to do create and close resourceresolver and session in single method and it will cause any performance issue because mostly maximum no of jobs(10) will run in parallel.
Please suggest any other ideas to handle the concurrent issue if my idea is not good.
Views
Replies
Total Likes
Thanks for your reply..
Scenario :
Copying child nodes from particular node(/content/old/node1) and replacing child nodes under path /content/new/node1.Also doing add/modify/delete property under the node /content/new/node1 and its child nodes.
Similarly (/content/old/node2) to (/content/new/node2)
(/content/old/node3) to (/content/new/node3)
(/content/old/node4) to (/content/new/node4)
I am doing the above four operation at same time(creating job for each process /content/old/node1 to /content/new/node1). Four job is running parallel.
Initial call came to job class and it is directing to job service. In job service, I created resourceresolver
from resourceresolverfactory(org.apache.sling.api.resource) and made resourceresolver as global variable for creating session at various private lower level methods.
Example:
Private ResourceResolver resolver
Class Jobservice(){
public void mainmethod(){
resolver = resourceresolverfactory.getServiceResourceResolver(null);
String path = "/content/old/node1";
lowerMethod1(path)
}
private void lowerMethod1(String path){
Session session= resolver.adapt(Session.class);
Node destinationNode = session.getNode("/content/new/node1");
deleteAllCHildNodes(destinationNode);
updateProperty(destinationNode);
}
private void deleteAllCHildNodes(Node destNode){
Session session= resolver.adapt(Session.class);
---deleting all childnodes under destNode----
session.save();
}
Likewise I am doing different operation under /content/new/node1. I was getting concurrent access error and invaliditemstateexception(item doesi not exist anymore) at the different places in my code
because four jobs are running parallel and performing operation under the respective node. I came to know that sessions are
opening long time by google search(https://cqdump.wordpress.com/2015/03/02/aem-scaling-patterns-avoid-shared-sessions/) abt this issue.
Also changes done for node1 in session1(first job) will not be available in session2(opened in second job).
In order to avoid this error, I am creating resourceresolver and session at lower level methods and closing at the end of method itself(Session is opening for short duration) as below
Class Jobservice(){
public void mainmethod(){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session = resolver.adaptTo(Session.class);
String path = "/content/old/node1";
lowerMethod1(path);
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
private void lowerMethod1(String path){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session = resolver.adaptTo(Session.class);
Node destinationNode = session.getNode("/content/new/node1");
deleteAllCHildNodes(destinationNode);
updateProperty(destinationNode);
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
private void deleteAllCHildNodes(Node destNode){
ResourceResolver resolver = null;
Session session = null;
try {
resolver = resolverFactory.getServiceResourceResolver(null);
session= resolver.adapt(Session.class);
---deleting all childnodes under destNode----
session.save();
} catch (Exception e) {
Logging exception
} finally {
if (session != null && session.isLive()) {
session.logout();
}
if (resolver != null && resolver.isLive()) {
resolver.close();
}
}
}
Kindly share your thoughts on this one.. whether it is good practice to do create and close resourceresolver and session in single method and it will cause any performance issue because mostly maximum no of jobs(10) will run in parallel.
Please suggest any other ideas to handle the concurrent issue if my idea is not good.
Views
Replies
Total Likes
Always use local variables in this case.
Views
Replies
Total Likes
Hey sankarr26533925,
I don't know how are you creating jobs. But here is the solution of your problem using Java ExecuterFramework for multi-threaded application. Even if you are not using any framework and simply creating Threads then follow the same concept. Without a framework, you might have to take care of synchronization in
//Job Class
Job
this.resouceResolver = resourceResolver; this.jobService = jobService;
}
@Override
}
}
//This is the class where you initiate jobs.
// Get resouceResolver here and pass it to jobs. And when all your jobs are done, close resolver here in a finally block.
}
Jitendra
Views
Replies
Total Likes
I am using JobConsumer API (org.apache.sling.event.jobs.consumer). I should use CQ5 API only..Can we pass resourceresolver through Job properties ?
Views
Replies
Total Likes
So I can create session and resolver in each method. Will it cause any problem ?
Views
Replies
Total Likes
Can I create resourceresolver in local method and close it ?
Views
Replies
Total Likes
Technically you can do that but ideally, you should declare it globally for the service which can be used to complete a flow or a transaction and then make your master method to have the finally block to close the session or resourceresolver.
If you have multiple method which works independently, then you can still have the local variables
sankarr26533925 wrote...
Can I create resourceresolver in local method and close it ?
That's perfectly possible.
Views
Replies
Total Likes
I don't think that could solve your problem. But you can try it. I think, at the job level, Open
Jitendra
Views
Replies
Total Likes
Please follow below post for best use of resource resolver
Views
Replies
Total Likes