Hi All,
I am getting error in sing model class saying resource resolver is already closed
Below is my code for reference.
@Model(adaptables = Resource.class)
public class SchedulerComponent {
private static Logger LOG = LoggerFactory.getLogger(SchedulerComponent.class);
@Inject
private Date timer;
@Inject
private ResourceResolver resourceResolver;
@PostConstruct
public final void init() {
try {
Session session = resourceResolver.adaptTo(Session.class);
} catch(Exception ex) {
}
}
}
Below is error stack trace.
java.lang.IllegalStateException: Resource resolver is already closed.
at org.apache.sling.resourceresolver.impl.ResourceResolverImpl.checkClosed(ResourceResolverImpl.java:202)
at org.apache.sling.resourceresolver.impl.ResourceResolverImpl.adaptTo(ResourceResolverImpl.java:826)
at com.test.core.models.SchedulerComponent$MyTimeTask.run(SchedulerComponent.java:69)
at java.util.TimerThread.mainLoop(Unknown Source)
at java.util.TimerThread.run(Unknown Source)
Please advise to fix the problem.
Thanks,
Pradeep
Solved! Go to Solution.
I found the Solution to you. Everything i wrote is applicable. You need to break the code into a Interface, Service and Model.
Notice the Run method.
//Define RUN
public void run() {
try {
//Is SESSION valid
LOG.info("RUNNING IN THE RUN METHOD");
ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
session = resourceResolver.adaptTo(Session.class);
LOG.info("SESSION ID is " +session);
}
catch (Exception e)
{
e.printStackTrace();
}
}
This logged a message showing it was successfully invoked:
20.03.2018 22:56:48.589 *INFO* [Timer-23] com.adobe.community.time.core.TimeIml RUNNING IN THE RUN METHOD
20.03.2018 22:56:48.590 *INFO* [Timer-23] com.adobe.community.time.core.TimeIml SESSION ID is com.adobe.granite.repository.impl.CRX3SessionImpl@1e6230e
This was broken into a Service that implements a Java interface and extends TimerTask
We broke the code into this Interface:
package com.adobe.community.time.core;
public interface Time {
public String getTime() ;
}
This Implementation class
package com.adobe.community.time.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Reference;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.util.HashMap;
import java.util.Map;
//Sling Imports
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.TimerTask;
@Component
@Service
public class TimeIml extends TimerTask implements Time{
//Inject a Sling ResourceResolverFactory
@Reference
private ResourceResolverFactory resolverFactory;
private static Logger LOG = LoggerFactory.getLogger(TimeIml.class);
private Session session;
//Define RUN
public void run() {
try {
//Is SESSION valid
LOG.info("RUNNING IN THE RUN METHOD");
ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
session = resourceResolver.adaptTo(Session.class);
LOG.info("SESSION ID is " +session);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String getTime()
{
try{
//Invoke the adaptTo method to create a Session
ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
session = resourceResolver.adaptTo(Session.class);
LOG.info("Entering getCustData()");
return "LAM22";
}
catch (Exception e)
{
e.printStackTrace();
}
return "Error" ;
}
}
Model Class – we casted the 1st parameter for timer1.schedule – that was the KEY!!!!
timer1.schedule((TimerTask)time, timer);
Code for Model class – THis logges the message in the RUN METHOD – meaning it worked!
20.03.2018 22:56:48.589 *INFO* [Timer-23] com.adobe.community.time.core.TimeIml RUNNING IN THE RUN METHOD
package com.adobe.community.time.core.models;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import com.adobe.community.time.core.Time;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.settings.SlingSettingsService;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Model(adaptables=Resource.class)
public class HelloWorldModel {
@Inject
private SlingSettingsService settings;
@Inject
private Time time;
@Inject @Named("sling:resourceType") @Default(values="No resourceType")
protected String resourceType;
private String message;
private static Logger LOG = LoggerFactory.getLogger(HelloWorldModel.class);
@PostConstruct
protected void init() {
message = "\tHello World!\n";
message += "\tThis is instance: " + settings.getSlingId() + "\n";
message += "\tTime is: " + time.getTime() + "\n";
SetTimeInfo();
}
public String getMessage() {
return message;
}
public void SetTimeInfo() {
try {
Date timer = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timer timer1 = new Timer();
SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
SimpleDateFormat outFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
LOG.info("Right format is :::: "+outFormat.format(timer));
LOG.info("Current Time: " + df.format( new Date()));
//Date and time at which you want to execute
//Date date = df.parse("2018-03-18 17:08:00");
//MyTimeTask task = new MyTimeTask();
//schedulerTask.setTimer(timer1);
timer1.schedule((TimerTask)time, timer);
//String myVal33 = task.getCustData();
//this.subject = text;
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
ALSO - I tested with ADMIN CALL - to run this - white list the bundle - see - https://forums.adobe.com/thread/2355506
How are you invoking this model? The stacktrace indicates that you have an inner class "MyTimeTask" which is a runnable and invoked from a timer. Can you share the complete code?
Views
Replies
Total Likes
Hi Jorg,
Please find the full class code below
package com.test.core.models;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Model(adaptables = Resource.class)
public class SchedulerComponent {
private static Logger LOG = LoggerFactory.getLogger(SchedulerComponent.class);
@Inject
private Date timer;
@Inject
private ResourceResolver resourceResolver;
/*@Inject
private String classification;
*/
/*@Inject
private ResourceResolver resourceResolver;
*/
/*@Inject
private Session session;
*/
static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private boolean taskOver;
public boolean isTaskOver() {
return taskOver;
}
Timer timer1 = new Timer();
private class MyTimeTask extends TimerTask {
private ResourceResolver resourceResolver;
public MyTimeTask(ResourceResolver resourceResolver) {
this.resourceResolver = resourceResolver;
}
public void run() {
try {
/*Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "ReadService");
ResourceResolver resolver = null;
resolver = resolverFactory.getServiceResourceResolver(param);
*/Session session = resourceResolver.adaptTo(Session.class);
LOG.info("Entering to run method");
// write custom code here
LOG.info("0000000");
String classification = "english";
Node classificationNode = session.getNode("/content/myapp/api-data/"+classification);
LOG.info("111111");
//System.setProperty("https.proxyHost", "proxy.global.dish.com");
//System.setProperty("https.proxyPort", "8080");
URL url = new URL("https://teamtreehouse.com/matthew.json");
LOG.info("2222222");
URLConnection con = url.openConnection();
LOG.info("connection opened");
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), Charset.forName("UTF-8")));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
System.out.println(sb.toString());
Node fileNode = classificationNode.addNode("twelve-month-pre-pay", "nt:file");
fileNode.setProperty("jcr:date", sb.toString());
session.save();
LOG.info("Original data saved in repository");
/*
File jsonFile = new File("api-call-hindi.json");
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(jsonFile));
// Read json content from repository
String content = new String(Files.readAllBytes(Paths.get("api-call.json")));
LOG.info("Content is ::: "+content);
JSONObject apiJson = new JSONObject(content);
JSONArray base_linear_packages = apiJson.getJSONArray("base_linear_packages");
for(int i=0; i< base_linear_packages.length(); i++) {
JSONObject base_linear_package = base_linear_packages.getJSONObject(i);
// assuming all channels are present in classification_name:Hindi identifier:hindi-gold
if(base_linear_package.get("classification_name").equals("Hindi") && base_linear_package.get("identifier").equals("hindi-gold")) {
JSONArray channels = base_linear_package.getJSONArray("channels");
File channelsFile = new File("channels.json");
BufferedWriter channelsWriter = new BufferedWriter(new FileWriter(channelsFile));
ObjectMapper mapper1 = new ObjectMapper();
Object jsonObject1 = mapper.readValue(channels.toString(), Object.class);
String prettyString1 = mapper1.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject1);
channelsWriter.write(prettyString1);
System.out.println("Channles written!!!");
channelsWriter.close();
break;
}
}*/
LOG.info("Running Task");
LOG.info("Current Time: " + df.format( new Date()));
timer1.cancel();
taskOver = true;
} catch (RepositoryException e) {
LOG.info("RepositoryException is :::: ", e);
} catch (MalformedURLException e) {
LOG.info("MalformedURLException is :::: ", e);
} catch (IOException e) {
e.printStackTrace();
} catch(Exception e) {
LOG.info("Exception is :::: ", e);
}
}
}
@PostConstruct
public final void init() {
try {
LOG.info("Time is :::: "+timer);
SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
SimpleDateFormat outFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
LOG.info("Right format is :::: "+outFormat.format(timer));
LOG.info("Current Time: " + df.format( new Date()));
//Date and time at which you want to execute
//Date date = df.parse("2018-03-18 17:08:00");
MyTimeTask task = new MyTimeTask(resourceResolver);
timer1.schedule(task, timer);
} catch(Exception ex) {
LOG.error("Error in init :::: ", ex);
}
}
}
Views
Replies
Total Likes
Instead of using an inner class, why not create MyTimeTask as an AEM Servce (use @Component). Then you can get an instance of this Service by using @inject.
You can use @inject to get an instance of AEM services when using Sling Models.
I ahve not seen inner classes used with SLing Models and would think it would make more sense to break your code into a Model and a Service.
Views
Replies
Total Likes
Setup your project like this:
Also - to get a Session in your Service - use this code:
Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "ReadService");
ResourceResolver resolver = null;
resolver = resolverFactory.getServiceResourceResolver(param);
Session session = resourceResolver.adaptTo(Session.class);
This will work. IN your model - you will get an instance using @Inject, Once you enter the Service, you are getting a session using a system user and you will be able to perform JCR operations like reading and writing node props.
Views
Replies
Total Likes
Not solved the issue even after placed timertask logic in separate class
Nw below is my timertask class code
@Component
public class SchedulerTask extends TimerTask {
private static Logger LOG = LoggerFactory.getLogger(SchedulerTask.class);
@Reference
private ResourceResolver resourceResolver;
Timer timer = new Timer();
private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void run() {
try {
}
}
}
Below error i am getting
org.apache.sling.api.scripting.ScriptEvaluationException: org.apache.sling.scripting.sightly.SightlyException: Identifier com.test.core.models.SchedulerComponent cannot be correctly instantiated by the Use API
I am injecting timertask like below in main model class
@Inject
private SchedulerTask schedulerTask;
Views
Replies
Total Likes
This is an interesting use case. Something that i have not tried. Can you see if you can get that code to work in your service class.
Views
Replies
Total Likes
Hi,
the formating is a bit unfortunate, so I hope I did not get the code wrong.
For me it looks like that you have a sling model, and that you pass the resourceResolver (which is injected into it) to a TimerTask. And then this TimerTask throws the mentioned stacktrace.
That's what I would expect in this case. Because the request (which invokes the Sling Model) "owns" the resourceResolver, that means it is responsible for opening and closing it. If you start a new asynchronous thread and pass this resourceResolver to this new thread, the request does not know about it and closes the resourceResolver; and then you get the exception you posted.
The solution is to open a new ResourceResolver in the TimerThread.
Jörg
now i am getting nullpointer for resourceresolver
package com.test.core.models;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Model(adaptables = Resource.class)
public class SchedulerComponent {
private static Logger LOG = LoggerFactory.getLogger(SchedulerComponent.class);
@Inject
private Date timer;
/*@Inject
private String classification;
*/
/*@Inject
private ResourceResolver resourceResolver;
*/
/*@Inject
private Session session;
*/
/*@Inject
private SchedulerTask schedulerTask;
*/
static DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timer timer1 = new Timer();
private class MyTimeTask extends TimerTask {
@Inject
private ResourceResolver resourceResolver;
public void run() {
try {
/*Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "ReadService");
ResourceResolver resolver = null;
resolver = resolverFactory.getServiceResourceResolver(param);
*/Session session = resourceResolver.adaptTo(Session.class);
LOG.info("Entering to run method");
// write custom code here
LOG.info("0000000");
String classification = "hindi";
Node classificationNode = session.getNode("/content/myapp/api-data/"+classification);
LOG.info("111111");
//System.setProperty("https.proxyHost", "proxy.global.dish.com");
//System.setProperty("https.proxyPort", "8080");
URL url = new URL("https://teamtreehouse.com/matthew.json");
LOG.info("2222222");
URLConnection con = url.openConnection();
LOG.info("connection opened");
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), Charset.forName("UTF-8")));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line);
}
System.out.println(sb.toString());
Node fileNode = classificationNode.addNode("twelve-month-pre-pay", "nt:file");
fileNode.setProperty("jcr:date", sb.toString());
session.save();
LOG.info("Original data saved in repository");
/*
File jsonFile = new File("api-call-hindi.json");
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(jsonFile));
// Read json content from repository
String content = new String(Files.readAllBytes(Paths.get("api-call.json")));
LOG.info("Content is ::: "+content);
JSONObject apiJson = new JSONObject(content);
JSONArray base_linear_packages = apiJson.getJSONArray("base_linear_packages");
for(int i=0; i< base_linear_packages.length(); i++) {
JSONObject base_linear_package = base_linear_packages.getJSONObject(i);
// assuming all channels are present in classification_name:Hindi identifier:hindi-gold
if(base_linear_package.get("classification_name").equals("Hindi") && base_linear_package.get("identifier").equals("hindi-gold")) {
JSONArray channels = base_linear_package.getJSONArray("channels");
File channelsFile = new File("channels.json");
BufferedWriter channelsWriter = new BufferedWriter(new FileWriter(channelsFile));
ObjectMapper mapper1 = new ObjectMapper();
Object jsonObject1 = mapper.readValue(channels.toString(), Object.class);
String prettyString1 = mapper1.writerWithDefaultPrettyPrinter().writeValueAsString(jsonObject1);
channelsWriter.write(prettyString1);
System.out.println("Channles written!!!");
channelsWriter.close();
break;
}
}*/
LOG.info("Running Task");
LOG.info("Current Time: " + df.format( new Date()));
timer1.cancel();
} catch (RepositoryException e) {
LOG.info("RepositoryException is :::: ", e);
} catch (MalformedURLException e) {
LOG.info("MalformedURLException is :::: ", e);
} catch (IOException e) {
e.printStackTrace();
} catch(Exception e) {
LOG.info("Exception is :::: ", e);
}
}
}
@PostConstruct
public final void init() {
try {
LOG.info("Time is :::: "+timer);
SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
SimpleDateFormat outFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
LOG.info("Right format is :::: "+outFormat.format(timer));
LOG.info("Current Time: " + df.format( new Date()));
//Date and time at which you want to execute
//Date date = df.parse("2018-03-18 17:08:00");
MyTimeTask task = new MyTimeTask();
//schedulerTask.setTimer(timer1);
timer1.schedule(task, timer);
} catch(Exception ex) {
LOG.error("Error in init :::: ", ex);
}
}
}
Views
Replies
Total Likes
What exactly are you trying to accomplish. Looks like you are trying to implement Java logic that fires off jobs on a timer.
When most ppl want to implement a time based scheduler solution, they are writing a Sling Scheduler Service. Apache Sling :: Scheduler Service (commons scheduler)
Views
Replies
Total Likes
Hi Pradeep,
It's problem with injecting Date object which breaks and encounters exception. Here is working code for your sling models.
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.models.annotations.injectorspecific.SlingObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.jcr.Session;
import java.util.Date;
@Model(adaptables = Resource.class)
public class SchedulerComponent {
private static Logger LOG = LoggerFactory.getLogger(SchedulerComponent.class);
@Inject
@Optional
private Date timer;
@SlingObject
private ResourceResolver resourceResolver;
private String userName = "default user";
@PostConstruct
public final void init() {
try {
Session session = resourceResolver.adaptTo(Session.class);
userName = session.getUserID();
} catch (Exception ex) {
LOG.error(ex.getMessage());
}
}
public String getUserName() {
return userName;
}
}
Views
Replies
Total Likes
@Inject
private Date timer;
timer is the property in dialog of type Date. This is needed to pass to schedule the task.
My requirement is to run some piece of code on selected time. I am not using typical scheduler why because felix console access is not provided us, it is maintained and managed by Adobe, we can't ask them to run scheduler as and when needed. We have only author access. So in authoring dialog as soon as author is selecting particular date and time, my timer task code should execute. To accomplish this i am using java.util.TimerTask
Below code still throwing nullpointer for resourceresolver.
@SlingObject
private ResourceResolver resourceResolver;
Views
Replies
Total Likes
I sent you an email.
Views
Replies
Total Likes
I am going to figure this out - Many questions here - within a nest class - i do not think @Inject will work. But I will code this and see.
Views
Replies
Total Likes
IN AEM - to get a session - you use this typically in an OSGi bundle in a Service that is managed by AEM:
try {
Map<String, Object> param = new HashMap<String, Object>();
param.put(ResourceResolverFactory.SUBSERVICE, "datawrite");
ResourceResolver resolver = null;
resolver = resolverFactory.getServiceResourceResolver(param);
session = resolver.adaptTo(Session.class);
However to get this to work - you need this:
@Reference
private ResourceResolverFactory resolverFactory;
This code will only work from an AEM Service. You can easily get to work from a Model.
For example - assume you have an interface ;
package com.adobe.community.time.core;
public interface Time {
public String getTime() ;
}
Then you have the Service that implements TImer:
package com.adobe.community.time.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Reference;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.util.HashMap;
import java.util.Map;
//Sling Imports
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.TimerTask;
@Component
@Service
public class TimeIml extends TimerTask implements Time{
//Inject a Sling ResourceResolverFactory
@Reference
private ResourceResolverFactory resolverFactory;
private static Logger LOG = LoggerFactory.getLogger(TimeIml.class);
private Session session;
//Define RUN
public void run() {
try {
String A = "tt";
LOG.info(A);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String getTime()
{
try{
//Invoke the adaptTo method to create a Session
ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
session = resourceResolver.adaptTo(Session.class);
LOG.info("Entering getCustData()");
return "LAM22";
}
catch (Exception e)
{
e.printStackTrace();
}
return "Error" ;
}
}
In my model - I can get the getTime() method to be invoked by using @Inject.
@Inject
private Time time; // notice we are referencing the inteface - not the class
@Inject @Named("sling:resourceType") @Default(values="No resourceType")
protected String resourceType;
private String message;
private static Logger LOG = LoggerFactory.getLogger(HelloWorldModel.class);
@PostConstruct
protected void init() {
message = "\tHello World!\n";
message += "\tThis is instance: " + settings.getSlingId() + "\n";
message += "\tTime is: " + time.getTime() + "\n"; // call getTime
This works fine in AEM.
This code will work fine when used in a Service - like TImeImp
@Reference
private ResourceResolverFactory resolverFactory;
You are trying to use ResourceResolverFactory from a non-managed object -- this will not work
TimeIml tt = new TimeIml(); // ResourceResolverFactory will be NULL!!!
ResourceResolverFactory will be null in this case.
So you problem boils down to what to pass to the timer1.schedule(time, timer);
You cannot pass the @Inject instance as this is the interface - not the Object that extends TimerTask.
If you try and declare the object by using new:
TimeIml tt = new TimeIml()
ResourceResolverFactory is null.
Also - nested classes from a model will not let you use @Inject either. . You cannot inject ResourceResolverFactory.
Views
Replies
Total Likes
My HTL component is showing the value returned from getTime method:
Hi Pradeep,
I agree with Scott..
You cannot inject anything from the Inner class and It cannot be a model class. Also as Scott suggested better use Scheduler Service and not TimerTask
Thanks,
Ratna Kumar.
Views
Replies
Total Likes
I found the Solution to you. Everything i wrote is applicable. You need to break the code into a Interface, Service and Model.
Notice the Run method.
//Define RUN
public void run() {
try {
//Is SESSION valid
LOG.info("RUNNING IN THE RUN METHOD");
ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
session = resourceResolver.adaptTo(Session.class);
LOG.info("SESSION ID is " +session);
}
catch (Exception e)
{
e.printStackTrace();
}
}
This logged a message showing it was successfully invoked:
20.03.2018 22:56:48.589 *INFO* [Timer-23] com.adobe.community.time.core.TimeIml RUNNING IN THE RUN METHOD
20.03.2018 22:56:48.590 *INFO* [Timer-23] com.adobe.community.time.core.TimeIml SESSION ID is com.adobe.granite.repository.impl.CRX3SessionImpl@1e6230e
This was broken into a Service that implements a Java interface and extends TimerTask
We broke the code into this Interface:
package com.adobe.community.time.core;
public interface Time {
public String getTime() ;
}
This Implementation class
package com.adobe.community.time.core;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.apache.felix.scr.annotations.Reference;
import javax.inject.Inject;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import java.util.HashMap;
import java.util.Map;
//Sling Imports
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Model;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.TimerTask;
@Component
@Service
public class TimeIml extends TimerTask implements Time{
//Inject a Sling ResourceResolverFactory
@Reference
private ResourceResolverFactory resolverFactory;
private static Logger LOG = LoggerFactory.getLogger(TimeIml.class);
private Session session;
//Define RUN
public void run() {
try {
//Is SESSION valid
LOG.info("RUNNING IN THE RUN METHOD");
ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
session = resourceResolver.adaptTo(Session.class);
LOG.info("SESSION ID is " +session);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public String getTime()
{
try{
//Invoke the adaptTo method to create a Session
ResourceResolver resourceResolver = resolverFactory.getAdministrativeResourceResolver(null);
session = resourceResolver.adaptTo(Session.class);
LOG.info("Entering getCustData()");
return "LAM22";
}
catch (Exception e)
{
e.printStackTrace();
}
return "Error" ;
}
}
Model Class – we casted the 1st parameter for timer1.schedule – that was the KEY!!!!
timer1.schedule((TimerTask)time, timer);
Code for Model class – THis logges the message in the RUN METHOD – meaning it worked!
20.03.2018 22:56:48.589 *INFO* [Timer-23] com.adobe.community.time.core.TimeIml RUNNING IN THE RUN METHOD
package com.adobe.community.time.core.models;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import com.adobe.community.time.core.Time;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.settings.SlingSettingsService;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Model(adaptables=Resource.class)
public class HelloWorldModel {
@Inject
private SlingSettingsService settings;
@Inject
private Time time;
@Inject @Named("sling:resourceType") @Default(values="No resourceType")
protected String resourceType;
private String message;
private static Logger LOG = LoggerFactory.getLogger(HelloWorldModel.class);
@PostConstruct
protected void init() {
message = "\tHello World!\n";
message += "\tThis is instance: " + settings.getSlingId() + "\n";
message += "\tTime is: " + time.getTime() + "\n";
SetTimeInfo();
}
public String getMessage() {
return message;
}
public void SetTimeInfo() {
try {
Date timer = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timer timer1 = new Timer();
SimpleDateFormat inFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
SimpleDateFormat outFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
LOG.info("Right format is :::: "+outFormat.format(timer));
LOG.info("Current Time: " + df.format( new Date()));
//Date and time at which you want to execute
//Date date = df.parse("2018-03-18 17:08:00");
//MyTimeTask task = new MyTimeTask();
//schedulerTask.setTimer(timer1);
timer1.schedule((TimerTask)time, timer);
//String myVal33 = task.getCustData();
//this.subject = text;
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
ALSO - I tested with ADMIN CALL - to run this - white list the bundle - see - https://forums.adobe.com/thread/2355506
Woow thats simply Awesome Scott!!
I will test this code in Maven 10 too!!
~Ratna Kumar.
AN update - changed session id to :
LOG.info("SESSION ID is " +session.getUserID() );
Log message - 20.03.2018 23:21:02.626 *INFO* [Timer-25] com.adobe.community.time.core.TimeIml SESSION ID is admin
Views
Likes
Replies