I am trying to create a cronjob in cq using a time interval
I see on the link https://sling.apache.org/documentation/bundles/scheduler-service-commons-scheduler.html I could make job1 run and it will work. But I have a questions on the code.
In the below code
Why is job1.run() invoked in a catch block? Can we not add it to the try block?
Can I replace the catch block instead of job1.run() using thread using start and can I add in try block or must it be in the catch block?
Thread newThread = new Thread(job1);
newThread.start();
I see the cronjob code in the above link
protected void activate(ComponentContext componentContext) throws Exception {
//case 1: with addJob() method: executes the job every minute
String schedulingExpression = "0 * * * * ?";
String jobName1 = "case1";
Map<String, Serializable> config1 = new HashMap<String, Serializable>();
boolean canRunConcurrently = true;
final Runnable job1 = new Runnable() {
public void run() {
log.info("Executing job1");
}
};
try {
this.scheduler.addJob(jobName1, job1, config1, schedulingExpression, canRunConcurrently);
} catch (Exception e) {
job1.run();
}
}
According to the Javadoc, addJob, addPeriodicJob and fireJobAt will throw an Exception if the job cannot be added. The docs do not suggest anything regarding the cause of such failures.
The snippet on the Apache Sling Scheduler documentation page that you quoted in your question catches and ignores these exceptions.
Looking at the implementation provided, job1 is just a regular runnable so executing the run method manually in the catch block does not affect the Scheduler at all.
What it seems to be doing is attempt to add the job and in case of failure, silently ignore it and run it manually so that it prints "Executing job1"
There are at least two serious problems with this approach:
The code ignores the fact that something went wrong while adding the job and pretends this never happens (no logging, nothing)
It runs the job manually giving you the impression that it has been scheduled and just ran for the first time.
As to why it's happening? I have no idea. It's just silly and It's certainly not something I'd like to see in actual, non-tutorial code.
The API using such a generic exception to signal failure is also quite unfortunate.
Coincidentally, Sling 7 deprecates addJob, addPeriodicJob and fireJobAt and replaces them all with schedule. The schedule method returns a boolean so it doesn't give any more information about what exactly happened but it doesn't require you to use ugly try catch blocks.
If you're unable to use the latest version of Sling, make sure to use a logger and log the exceptions. Running your jobs manually, whatever they are, probably won't make much sense but that's something you need to decide.
Related
For diagnostic purposes I sometimes need to store the call stack that lead to a given state transition (such as granting a lock, committing a transaction, etc.) so that when something goes wrong later I can find out who originally triggered the state transition.
Currently, the only way I am aware of to retrieve the call stack looks like the following code snippet, which I consider terribly ugly:
StackTraceElement[] cause;
try {
throw new Exception();
} catch (Exception e) {
cause = e.getStackTrace();
}
Does somebody know of a better way to accomplish this?
I think you can get the same thing with:
StackTraceElement[] cause = Thread.currentThread().getStackTrace();
Well, you can improve it slightly by not actually throwing the exception.
Exception ex = new Exception();
ex.fillInStackTrace();
StackTraceElement[] cause = ex.getStackTrace();
Actually, I just checked: the constructor calls fillInStackTrace() already. So you can simplify it to:
StackTraceElement[] cause = new Exception().getStackTrace();
This is actually what Thread.getStackTrace() does if it's called on the current thread, so you might prefer using it instead.
If you want it as a String and use Apache Commons:
org.apache.commons.lang.exception.ExceptionUtils.getFullStackTrace(new Throwable())
There's a new option since JDK 9: StackWalker
It isn't as expensive as Thread.currentThread().getStackTrace().
see also How Expensive is Thread.getStackTrace()?
Is there any way to continue executing Cucumber Steps even when one of the steps fails. In my current setup when a step fails , cucumber skips remaining steps....I wonder if there is some way to twick cucumber runner setup..
I could comment out failing steps but its not practical when you dont know which step will fail...If i could continue with remaining step i would know complete set of failing Tests in one shot....rather than going in cycle over cycle...
Environment: Cucumber JVM , R , Java , Ibatis , Spring Framework, Maven
It is not a good idea to continue executing steps after a step failure because a step failure can leave the World with an invariant violation. A better strategy is to increase the granularity of your scenarios. Instead of writing a single scenario with several "Then" statements, use a list of examples to separately test each postconditions. Sometimes a scenario outline and list of examples can consolidate similar stories. https://docs.cucumber.io/gherkin/reference/#scenario-outline
There is some discussion about adding a feature to tag certain steps to continue after failure. https://github.com/cucumber/cucumber/issues/79
One way would be to catch all the assertion errors and decide in the last step whether to fail or pass the test case. In this case, you can tailor it, say, check at any step to see if there is more than n errors and fail the test, if so.
Here's what I have done:
initialize a StringBuffer for Errors in your #Before for the test cases
catch the Assertion Errors and add to the StringBuffer, so that, they do not get thrown and terminate the test case.
Check the StringBuffer to determine whether to fail the test case.
StringBuffer verificationErrors;
// Initialize your error SringBuffer here
#Before
public void initialize() {
verificationErrors = new StringBuffer();
}
// The following is one of the steps in the test case where I need to assert something
#When("^the value is (\\d+)$")
public void the_result_should_be(int arg1) {
try {
assertEquals(arg1, 0);
}
catch(AssertionError ae) {
verificationErrors.append("Value is incorrect- "+ae.getMessage());
}
Check the StringBuffer in #After or in the last step of test case to determine if you can pass it or fail it, as follows:
if (!(verificationErrors.size()==0)) {
fail(verificationErrors.toString());
}
The only issue would be that, in the report, all the steps would look green but the test case looks failed. Then you might have to look through the Errors String to know which step(s) failed. You could add extra information to the String whenever there is an Assertion Error to help you locate the step easily.
Use SoftAssert to accumulate all assertion failures. Then tag your step definitions class as #ScenarioScoped and in step definitions class add a method tagged #After where you do mySoftAssert.assertAll();
i.e.
import io.cucumber.guice.ScenarioScoped;
import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.en.Then;
#ScenarioScoped
public class MyStepDefinitions {
SoftAssert mySoftAssert=new SoftAssert();
#Then("check something")
public void checkSomething() {
mySoftAssert.assertTrue(actualValue>expectedMinValue);
}
#After
public void afterScenario(Scenario scenario) throws Exception {
mySoftAssert.assertAll();
}
}
I want to pause /resume my webdriver test case execution on press of a button.
The way i come up is to use Thread class suspend and resume methods. But i want to make sure that it should not pause while webdriver is typing text or something. As if it will do the browser may loose the focus from that point. So i want to ensure atomic execution of element.sendKeys or element.click.
Please suggest any ideas???
Just run the test in debug mode. Then you can just suspend the entire JVM. This will have the effect of pausing WebDriver.
I think your best option here is to implement your own synchronization and start/stop around Selenium. One way to achieve this is to protect every call to a WebDriver API method with a monitor and a boolean flag to indicate that some other instance would like to suspend test execution:
private boolean suspend = false;
private Object monitor = new Object();
Your code before each API call could look as follows:
synchronized (monitor) {
if (suspend) {
try {
monitor.wait();
} catch (InterruptedException ex) {
// thrown if someonelse calls notify
}
}
}
If you want to suspend test execution, you need to have someone (i.e. another Thread) execute the following code:
synchronized (monitor) {
suspend = true;
}
To continue again, you would need to execute the following code:
synchronized (monitor) {
monitor.notifyAll();
}
Thats just a very simple solution. There are more sophisticated synchronization styles, but this one should be sufficient.
How can I stop a Gradle build after detecting a problem? I can use an assert, throw an exception, do a System.exit (bad idea), or use a dedicated function in Gradle (but I could not find one). What is the best way for Gradle (and why?).
I usually throw the relevant exception from the org.gradle.api package, for example InvalidUserDataException for when someone has entered something invalid, or GradleScriptException for more general errors.
If you want to stop the current task or action, and move on to the next, you can also throw a StopActionException
If you want to stop the build, throw:
throw new GradleException('error occurred')
or throw the subclasses for the above exception. Some of the subclass exceptions actually only fail the current task but continue with the build.
There is currently no dedicated method, although there have been discussions to add one.
The recommended way to stop a Gradle build is to throw an exception. Since Groovy doesn't have checked exceptions, and Gradle by default does not print the exception type, it's not that critical which exception is thrown. In build scripts, GradleException is often used, but a Groovy assertion also seems reasonable (depending on the circumstances and audience). What's important is to provide a clear message. Adding a cause (if available) helps for debugging (--stacktrace).
Gradle provides dedicated exception types StopExecutionException/StopActionException for stopping the current task/task action but continuing the build.
Another option if you don't have any desire to be able to catch the exception later on is to call the ant fail task. It's slightly easier to read in my opinion and you can give a nice message to the user without use of --stacktrace.
task (tarball, dependsOn: warAdmin) << {
ant.fail('The sky is falling!!')
}
Gives you a message like:
* What went wrong:
Execution failed for task ':tarball'.
> The sky is falling!!
Probably you can catch this (perhaps it throws ant's BuildException?) but if that's a goal then I wouldn't use ant.fail. I'd just make it easy to see what exception to catch by throwing standard gradle exception as tim_yates suggested.
Throwing a simple GradleException works in stopping the build script. This works great for
checking required environment setup.
GradleException('your message, why the script is stopped.')
Example:
if(null == System.getenv()['GRADLE_USER_HOME']) {
throw new GradleException('Required GRADLE_USER_HOME environment variable not set.')
}
Here is a code fragment that tries to emulate how the Gradle javac task throws errors:
task myCommand(type:Exec) {
... normal task setup ....
ignoreExitValue true
standardOutput = new ByteArrayOutputStream()
ext.output = { standardOutput.toString() }
doLast {
if (execResult.exitValue) {
logger.error(output())
throw new TaskExecutionException( it,
new Exception( "Command '${commandLine.join(' ')}' failed; "
+ "see task output for details." )
)
}
}
}
When the command returns 0 there is no output. Any other value will print the standardOutput and halt the build.
NOTE: If your command writes to errorOutput as well, you may need to include that in the error log.
So I'm trying to use the TPL features in .NET 4.0 and have some code like this (don't laugh):
/// <summary>Fetches a thread along with its posts. Increments the thread viewed counter.</summary>
public Thread ViewThread(int threadId)
{
// Get the thread along with the posts
Thread thread = this.Context.Threads.Include(t => t.Posts)
.FirstOrDefault(t => t.ThreadID == threadId);
// Increment viewed counter
thread.NumViews++;
Task.Factory.StartNew(() =>
{
try {
this.Context.SaveChanges();
}
catch (Exception ex) {
this.Logger.Error("Error viewing thread " + thread.Title, ex);
}
this.Logger.DebugFormat(#"Thread ""{0}"" viewed and incremented.", thread.Title);
});
return thread;
}
So my immediate concerns with the lambda are this.Context (my entity framework datacontext member), this.Logger (logger member) and thread (used in the logger call). Normally in the QueueUserWorkItem() days, I would think these would need to be passed into the delegate as part of a state object. Are closures going to be bail me out of needing to do that?
Another issue is that the type that this routine is in implements IDisposable and thus is in a using statement. So if I do something like...
using (var bl = new ThreadBL()) {
t = bl.ViewThread(threadId);
}
... am I going to create a race between a dispose() call and the TPL getting around to invoking my lambda?
Currently I'm seeing the context save the data back to my database but no logging - no exceptions either. This could be a configuration thing on my part but something about this code feels odd. I don't want to have unhandled exceptions in other threads. Any input is welcome!
As for your question on closures, yes this is exactly what closures are about. You don't worry about passing state, instead it is captured for you from any outer context and copied onto a compiler supplied class which is also where the closure method will be defined. The compiler does a lot of magic here to make you're life simple. If you want to understand more I highly recommend picking up Jon Skeet's C# in Depth. The chapter on closures is actually available here.
As for your specific implementation, it will not work mainly for the exact problem you mentioned: the Task will be scheduled at the end of ViewThread, but potentially not execute before your ThreadBL instance is disposed of.