Esper: Creating new Esper statements, and skipping those that already exist - java

The project I'm working on uses Esper to create monitoring rules. These rules are either active or inactive, based on a boolean in the SQL row. I would like to set up a check to see if there are any new active rules, create a statement from the, and add them to a hashmap. This will periodically run using Spring scheduler. The code so far looks like this:
private void refreshStatement(Rule rule) throws Expression {
List<String> allRules = dao.getAllRules();
for (String rule : allRules) {
EPStatement statement = epService.getEPAdministrator().createEPL(rule);
statement.addListener(new RuleListener(rule));
ruleMap.put(rule.getId(), statement);
}
}
On the initial run, this works fine. The statements are generated and added to the hashmap ruleMap. Upon the method running a second time due to the scheduler, though, it fails due to the first rule it sees already existing. For example:
ERROR [2018-08-14 12:00:00,000] org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler: Unexpected error occurred in scheduled task.
! com.espertech.esper.epl.expression.core.ExprValidationException: Context by name 'Test_Case' already exists
Is there any good way to check to see if an Esper statement already exists, and to skip the rule if it does? So far, I've tried catching the exception and simply returning a log stating that the EPL statement already exists, that way only new statements would be created:
private Exception e;
private void refreshStatement(Rule rule) throws Exception {
List<String> allRules = dao.getAllRules;
for (String rule : allRules) {
if (e instanceof ExprValidationException) {
log.info("The EPL statement already exists")
}
else {
EPStatement statement = epService.getEPAdministrator().createEPL(rule);
statement.addListener(new RuleListener(rule));
ruleMap.put(rule.getId(), statement);
}
}
}
However, I still got the same exception.
Edit: I just realized that I wrote the for loop wrong. The program will fail on when creating statement, and since that is in the else portion of the loop, it thus never checks for the exception.

You can get the currently-existing statements from EPAdministrator.getStatementNames() and EPAdministrator.getStatement(String name).
Comparing whether a statement already exists is up to your application but EPStatement.getText() returns you the EPL.

Related

How do I correctly handle errors like these in SQLite/Java/Android?

For example I have something like this:
public void saveFoodatas(List<Foodata> foodataList) {
DatabaseHelper.database.beginTransaction();
try {
for (Foodata foodata : foodataList) {
saveFoodata(foodata);
}
DatabaseHelper.database.setTransactionSuccessful();
}
finally {
DatabaseHelper.database.endTransaction();
}
}
Where DatabaseHelper is a class extending SQLiteOpenHelper and database is a SQLiteDatabase.
In this function I am trying to make it so you save/commit a lot of objects to the database, but if there is a failure, then don't commit any of the changes.
I believe that what it's currently set up to do correctly (if there is an error, it leaves the try block I think and goes straight to finally since there is no catch), but my question is how to properly trigger the failure condition. Do I need saveFoodata to "throw an exception"? If the function encounters some kind of failure without me doing any try/catch/throwing, does that count too? How exactly do I handle saveFooData()?
I think you are on the right track. You need to abort the transaction if an error occurs. You also need to alert the user of the problem. This means that saveFoodata() and saveFoodatas() should throw an exception so that the UI code can display a message to the user,

IllegalArgumentException: Invalid conditional statement inside expectation block

I have a problem with an Expectations block I have written in my test case:
new Expectations() {
{
mFindHandlerMock.findAll((Model) any, (Set<Id>) any, false);
if (!pWithRealData) {
result = Collections.emptySet();
} else {
result = pAllData;
}
times = 1;
Deencapsulation.invoke(mDb, "readSqlQuery", withAny(String.class));
result = "select * from realdata";
times = 1;
}
};
the test case crashes with:
java.lang.IllegalArgumentException: Invalid conditional statement inside expectation block
exactly here:
if (!pWithRealData) {
it's just a simple boolean that is false in this case.
I have absolutly no clue why the exception happens.
I already searched with google but found nothing helpful.
Could you help me?
From the JMockit release notes for version 1.14:
Enhancement: Conditionals and loops will now trigger an exception when found inside an expectation recording block, to prevent API misuse and to encourage simpler tests. See issue #97.
The GitHub issues related to this:
https://github.com/jmockit/jmockit1/issues/97
https://github.com/jmockit/jmockit1/issues/123
In the one issue they state that:
Yes, and this is as intended, to avoid tests getting too complicated when recording expectations. A full test was not shown, but it looks to me that recording the specific expectations directly would be better in this case.
In the JMockit source you can see which other types of conditionals and loops will throw that exception.
In short, from JMockit 1.14 onwards you are not allowed to have conditionals (such as if statements) and loops in the Expectation block.

Why is my Java app getting killed?

I could be wrong about which line is causing the problem, but the error changes everytime I change this if() statement:
try {
while(true) {
String LRU = hashOperation();
System.out.println("In worker thread, this should be valid JSON: " + LRU);
if (jsonValidator.isStringValidJSON(LRU) && !LRU.isEmpty()) {
HashMap<String,String> messageMap = jsonGenerator.readJSON(LRU);
So I assume the problem is with this if() statement. If I write it like this:
if (jsonValidator.isStringValidJSON(LRU)) {
Then the app starts up and I get this exception:
In worker thread, this should be valid JSON:
Exception in worker thread in Main::main: No content to map to Object due to end of input
but if I write it like this:
if (jsonValidator.isStringValidJSON(LRU) && !LRU.isEmpty()) {
Then the app starts up, but then almost instantly dies:
/usr/bin/java -cp /home/jenkins/run-nlp/SSAM.jar com.sofar.SSAM.Main
Starting NLP app 2015/08/30 21:42:28
Loading classifier from dependencies/english.all.7class.distsim.crf.ser.gz ... Killed
The basic idea here is that the app starts up and then spins up some background threads that poll endlessly on Redis, looking for input (the input comes from another app, that publishes data to a channel on Redis).
When I see "Killed" I assume that an Exception went uncaught, but I have this whole Thread::run() wrapped in a try/catch that ends with:
} catch (Exception e) {
System.out.println("Exception in worker thread in Main::main: " + e.getMessage());
}
You can see that this is the Exception message that I get if I do this:
if (jsonValidator.isStringValidJSON(LRU)) {
Although it is possible the error is elsewhere, and I think it is odd that an empty string would be valid JSON, I thought I would screen out that possibility with:
if (jsonValidator.isStringValidJSON(LRU) && !LRU.isEmpty()) {
Why would this one change cause my app to be Killed?
UPDATE:
I refactored the app to this:
static void processMessage(ssamBrain ssamBrain, Jedis jedis, HashMap<String, String> responseMap, JsonGenerator jsonGenerator, JSONValidator jsonValidator, String LRU) {
try {
if (!LRU.isEmpty()) {
HashMap<String,String> messageMap = jsonGenerator.readJSON(LRU);
Transformer transformer = new Transformer();
Again, the line that causes the problem seems to be:
if (!LRU.isEmpty()) {
If I don't have that if() statement, then the code gets:
java.io.EOFException: No content to map to Object due to end of input
on the next line, since an empty string is not valid JSON.
But when I add this:
if (!LRU.isEmpty()) {
Then my app dies on startup.
Maybe autoboxing is the problem? Or the absence of it? Assume for now:
LRU = "";
I assume I can call methods on it, but maybe not? And why wouldn't I get an Exception?
It's possible the problem is elsewhere, but that if() statement seems to be the main thing that causes the problem to surface.
UPDATE
UPDATE
The app sometimes survives for a few minutes, but other times it dies after a few seconds. So I guess I need to ask:
1.) when a Java app says "Killed" in the terminal, does that always mean that an Exception went uncaught?
2.) what might cause such variable behavior?
How to works if operator:
if (CONDITION_1 && CONDITION_2){
doSomething();
}
checks CONDITION_1 - if it is true:
checks CONDITION_2 - if it is true:
runs doSometring().
If CONDITION_1 is false or throws an exception, CONDITION_2 never checks.
Please, show the exception stackTrace.
Change:
if (jsonValidator.isStringValidJSON(LRU) && !LRU.isEmpty())
to:
if (!LRU.isEmpty() && jsonValidator.isStringValidJSON(LRU))
So, you first check if LRU is empty and if it is not - you run validation.

Exception Catching in the LHS of Drools

I have a problem where the when clause of a drools rule throws a MethodNotFoundException. I'm looking for a way to figure out which rule it is during runtime to be able to remove it from the list of rules to use.
Rule Example
Rule "FooBar"
when
$V1 : Foo ( ) AND
$V2 : FooBar( ) from $V1.getGoodMethod() AND
$V3 : FooBarBar( status == "FooBar" ) from $V2.getBadMethod()
reply : FooFooBar()
then
reply.getList().add("FooBar");
end
So, the getBadMethod on FooBar doesn't exist. I would like a way of telling what rule it is, and removing it from the list of rules to use.
Tried and Failed Solutions:
I've tried extending the DefaultAgendaEventListener and overriding the beforeActivationFired method to add the rule being fired to a list. I was hoping the last one in the list would be the one that threw the error, but sadly it didn't work out that way.
I've now tried adding "always true" rules before all my rules. They log the name of the rule that comes after it. The problem being when there is an exception in the "WHEN" clause nothing gets logged. It's as if no rules get fired when an Exception such as the one above occurs.
The problem all lies with the dynamic drools generation code. I would like to take a two pronged approach of fixing the generation code, and catching exceptions like the one listed in this post.
Side note: I do check for errors in the builder. I receive no errors from the below code.
KnowledgeBuilderErrors errors = builder.getErrors();
if (!errors.isEmpty()) {
for (KnowledgeBuilderError error : errors) {
...
}
}
As per my understanding, before doing fireAllRules() method below steps should be followed:
Add rules to the Package / Knowledge Builder
Validate that there are no errors in the Rules
Inject Rules in the working memory
Of Course, it is possible to fireRules without Step 2, but this practice can result in problems as mentioned in this question.
If I were you, I would follow the below logic to fix your this issue:
Step 1:
private RuleBase initialiseDrools() throws IOException, DroolsParserException {
PackageBuilder packageBuilder = readRules();
return addRulesToWorkingMemory(packageBuilder);
}
Step 2:
private PackageBuilder readRules() throws DroolsParserException, IOException {
PackageBuilder packageBuilder = new PackageBuilder();
PackageBuilder intermPackageBuilder = null;
listOfReader = dynamicRuleReader(); // Here goes your application code
for(Reader reader : listOfReader){
try{
intermPackageBuilder = new PackageBuilder();
intermPackageBuilder.addPackage(reader);
assertNoRuleErrors(intermPackageBuilder); // This is the core step.
// Above line throws an exception, every time a rules fails. You can persist this exception for production debugging
packageBuilder.addPackage(reader);
}catch(DroolsParserException | IOException e){
logger.error("Rules contain error, so skip adding them to the Package Builder");
}
}
return packageBuilder;
}
Step 3:
public void shouldFireAllRules() throws IOException, DroolsParserException {
RuleBase ruleBase = initialiseDrools();
WorkingMemory workingMemory = ruleBase.newStatefulSession();
int expectedNumberOfRulesFired = 2; // Idealy this number should be equal to the number of total rules injected in the Working memory
int actualNumberOfRulesFired = workingMemory.fireAllRules();
assertThat(actualNumberOfRulesFired, is(expectedNumberOfRulesFired));
}
Using above method, you will not executing a rule that has errors, and the situation described above will not arise.
However, I still believe you should focus more on the piece of code that generate erroneous Rules, and the method described above only to track and persist such occurrences.

Verify if a link is present or not

I'm trying to verify if a link is present or not -- but -- if it's not present, I want my script to continue executing (close the browser, etc).
The purpose of my script is to determine if a 'Delete Address' link is present or not. If it is, I click on the link and delete the address. This works fine. If the link is not present however, I just want to continue execution without triggering an exception. My code below triggers an exception if the link is not there.
Thanks for any help...
try {
String txt = driver.findElement(By.linkText("Delete Address")).getText().trim();
Assert.assertTrue(txt.equals("Delete Address"));
Alert javascriptprompt = driver.switchTo().alert();
javascriptprompt.accept();
} catch (NoSuchElementException e) {
}
I can see several options here
Do not use asserts in the test at all. In this case the test is marked as successful (if you caught exceptions)
If you want the lines after the findElement() call be executed you can
move all lines expect for findElement() out of the try {} clause
use the try {} catch {} finally {} construction and put to the finally {} clause all the code you want to be executed, no matter what happens in the try {}
If you want to avoid catching exception, you can create a listener class by implementing the interface ITestListener and in onTestFailure() obtain the exception using getThrowable()
String stackTraceString = Throwables.getStackTraceAsString(getCurrentTestResult().getThrowable());
Then, if the exception is NoSuchElementException then set test result to success
result.setStatus(ITestResult.SUCCESS);
setCurrentTestResult(result);
Another solution would be to use .findElements. It will return an empty collection, as opposed to throwing an exception, if there are no elements found with the given selector.

Categories