A Redis distributed lock confusing result with Lua script - java

I use such code to achieve Redis distributed lock:
DefaultRedisScript<String> script = new DefaultRedisScript<>();
script.setScriptText("if not redis.call('get', KEYS[1]) then return redis.call('set', KEYS[1], ARGV[1],'ex',ARGV[2],'nx') else return false end");
String result = redisTemplate.execute(script,
Collections.singletonList("REDIS_KEY_INDEX_LOCK"), "exists", "60");
I expect the result will be among "OK", "Nil" and "false".I checked the document, the set directive with 'NX','EX' will return "OK" or "Nil".
My code's result is that the key REDIS_KEY_INDEX_LOCK is set with the value exists successfully in Redis, but the value of the Java variable result is null.
redisTemplatet variable is a instance of StringRedisTemplate ,I'm use Spring-Data-Redis.
Please help me, explaining why I got an unexpected result and how to correct it.

I know the reason now after reading Spring-Data-Redis source code, the script's return type needs to be specified explicitly.
DefaultRedisScript<String> script = new DefaultRedisScript<>();
script.setScriptText("if not redis.call('get', KEYS[1]) \n" +
"then if(redis.call('set', KEYS[1], ARGV[1],'EX',ARGV[2],'NX')) \n" +
" then return \"true\";\n" +
" else return \"false\";\n" +
"end\n" +
"else return \"false\";\n" +
"end");
script.setResultType(String.class);//need to specify return type explicitly
String result = redisTemplate.execute(script,
Collections.singletonList("REDIS_KEY_INDEX_LOCK"),"exists","60");
return result.equals("true");

Related

How to skip a scenario with Cucumber-JVM at run-time in JAVA

I need to skip a scenario from running based on a flag which I obtain from the application dynamically in run-time, which tells whether the feature to be tested is enabled. I don't want to throw any exception.
Sample code:
if (JIRA_Integration.equalsIgnoreCase("yes")) {
status = zapi.getTestExecutionStatusInJIRA(scenario.getName());
if(status.equalsIgnoreCase("pass")){
isScenarioAlreadyExecuted = true;
}else {
isScenarioAlreadyExecuted = false;
}
} else {
logger.info("Currently JIRA_Integration is disabled, enable it to update test scenario execution status in JIRA");
}
}
if(isScenarioAlreadyExecuted){
logger.info("Scenario: \"" + scenario.getName() + "\" is already passed in the previous test cycle");
throw new AssumptionViolatedException("Scenario: \"" + scenario.getName() + "\" is already passed in the previous test cycle");
}

Use of OMI_IGNORE_NOTFOUND flag in OpenMetadata interface

In SAS Open Metadata reference (page 126), it says:
The UpdateMetadata method enables you to update the properties of existing metadata objects. It returns an error if the metadata object to be updated does not exist, unless the OMI_IGNORE_NOTFOUND (134217728) flag is set.
Here is my problem, if I specify the flag or I don't specify the flag, I still get the same error: ("SASLibrary : A5X8AHW1.B40000SQ cannot be found in the wlibrary container in the Foundation repository.")
Here is a snippet that reproduces the error:
import com.sas.meta.SASOMI.IOMI;
import com.sas.metadata.MetadataUtil;
import org.omg.CORBA.StringHolder;
IOMI iOMI = ... // an instance of IOMI connection
StringHolder outputMeta = new StringHolder();
String request = ""
+ "<UpdateMetadata>"
+ " <Metadata>"
+ " <SASLibrary Id=\"A5X8AHW1.B40000SQ\"/>"
+ " </Metadata>"
+ " <NS>SAS</NS>"
+ " <Flags>" + (MetadataUtil.OMI_IGNORE_NOTFOUND | MetadataUtil.OMI_TRUSTED_CLIENT | MetadataUtil.OMI_RETURN_LIST) + "</Flags>"
+ " <Options/>"
+ "</UpdateMetadata>"
;
iOMI.DoRequest(request, outputMeta);
Any ideas what is going wrong?
Contrary to what that document states, I have only seen OMI_IGNORE_NOTFOUND flag work with the DeleteMetadata method.
The javadoc also seems to support this by stating
OMI_IGNORE_NOTFOUND (134217728) This flag is for DeleteMetadata to tell it to ignore objects not found so that it will not return on error.
com.sas.metadata.remote.MdOMIUtil Interface Field Summery

The browser console doesn't recognize js vars that were injected with selenium webdriver

I try to bowser to a page with selenium web-driver.
I then inject and execute some js via selenium web-driver.
I try to access these vars in this opened browser console,
but it seems they were not created. How come?
I have this code:
public void foo (){
String script =
"var aLocation = {};" +
"var aOffer = {};" +
"var aAdData = " +
"{ " +
"location: aLocation, " +
"offer: aOffer " +
" };" +
"var aClientEnv = " +
" { " +
" sessionid: \"\", " +
" cookie: \"\", " +
" lon: 34.847, " +
" lat: 32.123, " +
" venue: \"\", " +
" venue_context: \"\", " +
" source: \"\"," + // One of the following (string) values: ADS_PIN_INFO,
// ADS_0SPEED_INFO, ADS_LINE_SEARCH_INFO,
// ADS_ARROW_NEARBY_INFO, ADS_CATEGORY_AUTOCOMPLETE_INFO,
// ADS_HISTORY_LIST_INFO
// (this field is also called "channel")
" locale: \"\"" + // ISO639-1 language code (2-5 characters), supported formats:
" };" +
"W.setOffer(aAdData, aClientEnv);";
javascriptExecutor.executeScript(script);
}
which yields:
script =
var aLocation = {};
var aOffer = {};
var aAdData = {
location: aLocation,
offer: aOffer
};
var aClientEnv = {
sessionid: "",
cookie: "",
rtserver - id: 1,
lon: 34.847,
lat: 32.123,
venue: "",
venue_context: "",
source: "",
locale: ""
};
W.setOffer(aAdData, aClientEnv);
I evaluate aLocation in this browser console and get "variable not defined". How can this be?
It is important to know how Selenium executes the JavaScript that is executed in the browser.
Contrarily to what nilesh's answer implies slapping a var in front of a variable declaration does not take it out of the global space. For instance if var foo = 1 is executed outside of a function scope, it will declare a global variable named foo.
The key is how Selenium executes the script. It would be possible for Selenium to execute the script passed to executeScript in the global space. (There are ways.) However, it does not. What it does is wrap the script in a new function so any var that appears in the code passed to executeScript is going to declare a local variable.
Just dropping the var would work but I prefer to be explicit when I want to manipulate the global space. I explicitly access the window object (e.g. window.foo = 1). Dropping var looks like it could be a mistake, whereas using window. looks deliberate.
Because your variables are NOT global. As soon as you declare them with var they are scoped. If you want to test something out, just put nemo=100; in your script above and try printing out in console, it should work.
Edit #1
By the way, by no means I'm advocating global variables here. I'm just trying to explain what happened to your variables in JS executed by WebDriver. If you want to use global variables then more explicit declaration like window.foo makes more sense like others have suggested. However overall try to avoid using them. Moreover try to avoid executing JavaScript using WebDriver in the first place
unless you have no other choice. WebDriver is supposed to simulate a real user for you and your user is less likely to execute a JavaScript to interact with your web app.

reduce() not working with lightcouch

I have wirtten a program to manage tv series and I am stuck at an issue with lightcouch and a specific database query. This is what I have so far. To setup the database views I used the following lines:
MapReduce get_numberOfSeasonsMR = new MapReduce();
get_numberOfSeasonsMR.setMap(
"function(doc) { "
+ " emit(doc.seriesName, doc.season)"
+ "}");
get_numberOfSeasonsMR.setReduce(
"function (key, values, rereduce) {"
+ "return Math.max.apply({}, values)"
+ "}");
map.put("get_numberOfSeasons", get_numberOfSeasonsMR);
In Futon everything appears normal (see http://i.stack.imgur.com/1hgSJ.png).
However, when I try to execute the following line, I get an exception, instead of the results that appear in Futon.
int nr = client.view("design/get_numberOfSeasons").key("Arrow").queryForInt();
Exception:
org.lightcouch.NoDocumentException: Expecting exactly a single result of this view query, but was: 0
org.lightcouch.View.queryValue(View.java:246)
org.lightcouch.View.queryForInt(View.java:219)
....db.Server.getNumberOfSeasons(Server.java:237)
...
I tried to emit Strings in my map() function instead on ints, but it did not make any difference. What am I doing wrong? Or can someone post an example of a successful lightcouch map()+reduce() operation? The tutorials I found only used map() without reduce().
Thanks in advance ;)
Nothing seems wrong with your code, here is the full version:
CouchDbClient dbClient = new CouchDbClient();
DesignDocument designDocument = new DesignDocument();
designDocument.setId("_design/mydesign");
designDocument.setLanguage("javascript");
MapReduce get_numberOfSeasonsMR = new MapReduce();
get_numberOfSeasonsMR.setMap(
"function(doc) { "
+ " emit(doc.seriesName, doc.season)"
+ "}");
get_numberOfSeasonsMR.setReduce(
"function (key, values, rereduce) {"
+ "return Math.max.apply({}, values)"
+ "}");
Map<String, MapReduce> view = new HashMap<>();
view.put("get_numberOfSeasons", get_numberOfSeasonsMR);
designDocument.setViews(view);
dbClient.design().synchronizeWithDb(designDocument);
int count = dbClient.view("mydesign/get_numberOfSeasons").key("Arrow").queryForInt();

String concatenation in java is not working on one system

I believe that most of you would be thinking that this is the same question you have heard multiple times (and answered ) about string concatenation in Java. But trust me, it is different. In fact, so different that I am even hesitant in posting it here. But anyways, here it is. I have some piece of code which goes like:
public void handleSuccess(String result)
{
result = result.trim();
MessageBox.alert("Information","Result after trimming: '" + result + "'");
result = result.substring(result.indexOf('\n') + 1);
MessageBox.alert("Information","Result after substring: '" + result + "'");
String returns = getReturns();
MessageBox.alert("Information","Returns: '" + returns + "'");
String action = getAction();
MessageBox.alert("Information","Action: '" + action + "'");
String finalResult = result + returns + action;
MessageBox.alert("Information","Final result: '" + finalResult + "'");
}
Now the situation here is that, all of these : getReturns(), result and getAction() return non blank values, and in fact the string finalResult contains the concatenated value after the last line is executed.
So, at Line 1, "result" contains "12/03/2013|04-AERTY|". The value of result remains same at end of line 1,2. getReturns() returns value 12.4724. So at end of line 3, finalResult contains "12/03/2013|04-AERTY|12.4724". getAction() returns "expt". So, at end of line 5, finalResult contains "12/03/2013|04-AERTY|12.4724|expt"
This is , when I debug or run the application in eclipse. As soon as build the same application on a UNIX system to generate a "war" file, and deploy the war on a tomcat server, the problem rears it's ugly head. When I run the application on the deployed war, the last line does not contain the concatenated value. So at the end of line 5, finalResult contains just "12/03/2013|04-AERTY|12.4724". I expected it to contain "12/03/2013|04-AERTY|12.4724|expt" as it does while running in eclipse.
I have tried stringbuffer, stringbuilder and the "+" operator as well, but nothing seems to work. I am not even getting an exception.
Can somebody help me in fixing this or at least enlightening me in what I might be doing wrong here?
Just to stress again, the code on eclipse(which is on a windows machine) and UNIX machine are exactly same. I have done a diff on them.
Here is what I get after putting the message-boxes:
Message-box 1: "Result after trimming: '12/03/2013|04-AERTY|'"
Message-box 2: "Result after substring: '12/03/2013|04-AERTY|'"
Message-box 3:"Returns: '12.4724'"
Message-box 4:"Action: '|expt'"
Message-box 5:"Final result: '12/03/2013|04-AERTY|12.4724|expt'"
Message-box 5 output is the one I receive when I execute code using eclipse
When running on deployed war, Message-box 1-4 have the same output as above, but Message-box 5 says: "Final result: '12/03/2013|04-AERTY|12.4724"
It's not clear where the extra "|" is meant to come from - if getAction() just returns expt, the result would be 12/03/2013|04-AERTY|12.4724|expt.
Anyway, I think it's safe to say that string concatenation will be working fine, and something else is wrong. You should add more diagnostics, logging everything:
public void handleSuccess(String result) {
result = result.trim();
log.info("Result after trimming: '" + result + "'");
result = result.substring(result.indexOf('\n') + 1);
log.info("Result after substring: '" + result + "'");
String returns = getReturns();
log.info("Returns: '" + returns + "'");
String action = getAction();
log.info("Action: '" + action + "'");
// It's not clear what this is meant to do. I suggest you remove it and
// use logging instead.
MessageBox.alert("Information", "The selected action is " + action, null);
String finalResult = result + returns + action;
log.info("Final result: '" + finalResult + "'");
I suspect you'll find that action is an empty string in the broken case.
Note that I've added quotes round each of the logged values, very deliberately. That means that if there's some unprintable character at the end of a string which causes problems, you should be able to detect that in the logging.
EDIT: As per the comment thread, when these were turned into message boxes (as it turns out this is running in GWT) it looks like there's something wrong with the early strings, as the closing ' isn't seen in diagnostics, in the broken case. The OP is going to investigate further.

Categories