AllRowsReader class with token range - java

This is an example of using AllRowsReader class from Astyanax recipes:
reader = new AllRowsReader.Builder<>(keyspace, columnFamily)
.withPageSize(1000)
.withConcurrencyLevel(10)
.withPartitioner(null)
.withConsistencyLevel(ConsistencyLevel.CL_ONE)
.withIncludeEmptyRows(false)
.withTokenRange(startToken, endToken)
.forEachRow(new Function<Row<String, String>, Boolean>() {
#Override
public Boolean apply(#Nullable Row<String, String> row) {
startToken = keyspace.getPartitioner().getTokenForKey(row.getRawKey());
// some other statements
return true;
}
})
.build();
reader.call();
where
startToken = keyspace.getPartitioner().getMinToken();
lastToken = keyspace.getPartitioner().getMaxToken();
If to run AllRowsReader without "withTokenRange(startToken, endToken)" then all works fine. But with "withTokenRange(startToken, endToken)" not all rows are fetched during column family reading.
AllRowsReader's source has this code:
if (this.concurrencyLevel != null || startToken != null|| endToken != null) {
List<TokenRange> tokens = partitioner.splitTokenRange(
startToken == null ? partitioner.getMinToken() : startToken,
endToken == null ? partitioner.getMinToken() : endToken,
this.concurrencyLevel == null ? 1 : this.concurrencyLevel);
for (TokenRange range : tokens) {
subtasks.add(makeTokenRangeTask(range.getStartToken(), range.getEndToken()));
}
}
Later partitioner.getMinToken() reverts to maxToken. So I don't understand what is the difference from my approach? Why AllRowsReader with minToken/maxToken works differnt from AllRowsReader without them?
If operation is teminated, I execute it again with the last startToken (so it must be a shift). But in this case I see some rows were fetched before. And this is confusing me too...
P.S. Astyanax automatically determines Murmur3Partitioner.
Thanks for any help.
Links:
AllRowsReader source,
Murmur3Partitioner source

Dmitry,
Treat the token range as a ring,as the circle completes start will be equal to end.Thats why in astyanax code there are setting the same token as min and max.
startToken == null ? partitioner.getMinToken() : startToken,
endToken == null ? partitioner.getMinToken() : endToken
I hope this clarifies your answer.Let me know if you have doubts

Related

Dynamic expression evaluator at runtime

I have an app that I wanted to customize using some sort of expression evaluator.
I wanted to change certain parts of the app without recompiling my code.
I am thinking of using groovy expression.
Say for example, I have a feature that can be enabled/disabled by supplying expression:
In this case, this feature will be enabled
Example 1:
EXPRESSION : status = part-time || status = hourly
INPUT: status = part-time
In this case, this feature will be disabled
Example 2:
EXPRESSION : status = part-time || status = hourly
INPUT: status = permanent
Users are required to enter an expression and an Input. Expression should evaluate to a boolean expression
They can also change the expression and the program will pick up this by some evaluation.
These expressions by the way are documented and is exposed by me to the user of my application
Example 3:
EXPRESSION : salary > 10000
INPUT: salary = 7000
I have seen a program before that does this and they say that they uses groovy under the hood.
But I cannot get my head wrap around the concept.
Can somebody please give me an idea?
Alternative approach using evaluate. Your variables are defined in binding, evaluate contains the expression:
// setup binding
def emp = [status:'permanent', name:'Hugo']
def binding = new Binding()
binding.status = 'permanent'
binding.status2 = 'part-time'
binding.salary = 7000
binding.employee = emp
println binding.variables
// evaluate the script
def ret = new GroovyShell(binding).evaluate("status == 'part-time' || status == 'hourly'")
println ret
ret = new GroovyShell(binding).evaluate("status2 == 'part-time' || status2 == 'hourly'")
println ret
ret = new GroovyShell(binding).evaluate("salary > 10000")
println ret
ret = new GroovyShell(binding).evaluate("employee.status == 'permanent' || employee.status == 'hourly'")
println ret
returns
[status:permanent, status2:part-time, salary:7000, employee:[status:permanent, name:Hugo]]
false
true
false
true
the usual call of groovy script:
import groovy.lang.Binding;
import groovy.lang.Script;
import groovy.lang.GroovyShell;
Binding binding = new Binding();
binding.setProperty("status", "part-time");
GroovyShell shell = new GroovyShell(binding);
Script script = shell.parse(" status == 'part-time' || status == 'hourly' ");
Object result = script.run();
after run the binding will be populated with new values of the variables.
you can cache the parsed script (or class of the parsed script) because parsing/compiling is expensive process.
as alternative - the easiest script evaluation:
Object result = groovy.util.Eval.me("status", "part-time",
" status == 'part-time' || status == 'hourly' ");

NoraUI - "Cannot infer Type argument" error using Result.Warning<> in a custom step

I need to raise a warning during one of my scenario but i don't stop to have this error appearing : "Cannot infer type arguments for Result.Warning<>"
I actually tried to raise the Warning the same way i was raising Failure until now :
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, oscarAccesClientPage.getCallBack());
The custom step i am using it inside is the following : I'm trying to go over a list of Element and checking that the existing value of them is the same or not as the one saved before.
protected void checkXyResourcesValue(Integer xyIterator, List<WebElement> elements, String keyParameter) throws TechnicalException, FailureException {
try {
Integer resIterator = 1;
for(WebElement element : elements) {
String targetKey = "XY" + xyIterator + "RES" + resIterator + keyParameter;
String new_value = element.getAttribute(VALUE) != null ? element.getAttribute(VALUE) : element.getText();
String existing_value = Context.getValue(targetKey) != null ? Context.getValue(targetKey) : targetKey;
if (new_value != existing_value) {
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, oscarAccesClientPage.getCallBack());
}
resIterator++;
}
} catch (Exception e) {
new Result.Failure<>(e.getMessage(), Messages.format(TaroMessages.FAIL_MESSAGE_ACCES_CLIENT_XY_CHECK_RESOURCES_VALUE, keyParameter, xyIterator), true, oscarAccesClientPage.getCallBack());
}
}
For the method to check and saved value I actually inspired myself for the piece of code from NoraUI to save a value on Context or read it from.
I'm using Eclipse Luna 4.4.2 and i try to compile using JDK1.8.0_131.
It may be more related to me not knowing how this work in Java than a real problem so thank you in advance for your help or insights. Don't hesitate to ask if you need more information on the piece of code or the context.
new Result.Warning<>(targetKey, Messages.format(TaroMessages.WARNING_RESOURCES_VALUE_DIFFERENCE_AFTER_REAFFECTATION, existing_value, new_value), true, 0);
use 0 if you do not use any Model (data serialized) or use id of your Object in the serial.

Flexible search with parameters return null value

I have to do this flexible search query in a service Java class:
select sum({oe:totalPrice})
from {Order as or join CustomerOrderStatus as os on {or:CustomerOrderStatus}={os:pk}
join OrderEntry as oe on {or.pk}={oe.order}}
where {or:versionID} is null and {or:orderType} in (8796093066999)
and {or:company} in (8796093710341)
and {or:pointOfSale} in (8796097413125)
and {oe:ecCode} in ('13','14')
and {or:yearSeason} in (8796093066981)
and {os:code} not in ('CANCELED', 'NOT_APPROVED')
When I perform this query in the hybris administration console I correctly obtain:
1164.00000000
In my Java service class I wrote this:
private BigDecimal findGroupedOrdersData(String total, String uncDisc, String orderPromo,
Map<String, Object> queryParameters) {
BigDecimal aggregatedValue = new BigDecimal(0);
final StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("select sum({oe:").append(total).append("})");
queryBuilder.append(
" from {Order as or join CustomerOrderStatus as os on {or:CustomerOrderStatus}={os:pk} join OrderEntry as oe on {or.pk}={oe.order}}");
queryBuilder.append(" where {or:versionID} is null");
if (queryParameters != null && !queryParameters.isEmpty()) {
appendWhereClausesToBuilder(queryBuilder, queryParameters);
}
queryBuilder.append(" and {os:code} not in ('");
queryBuilder.append(CustomerOrderStatus.CANCELED.getCode()).append("', ");
queryBuilder.append("'").append(CustomerOrderStatus.NOT_APPROVED.getCode()).append("')");
FlexibleSearchQuery query = new FlexibleSearchQuery(queryBuilder.toString(), queryParameters);
List<BigDecimal> result = Lists.newArrayList();
query.setResultClassList(Arrays.asList(BigDecimal.class));
result = getFlexibleSearchService().<BigDecimal> search(query).getResult();
if (!result.isEmpty() && result.get(0) != null) {
aggregatedValue = result.get(0);
}
return aggregatedValue;
}
private void appendWhereClausesToBuilder(StringBuilder builder, Map<String, Object> params) {
if ((params == null) || (params.isEmpty()))
return;
for (String paramName : params.keySet()) {
builder.append(" and ");
if (paramName.equalsIgnoreCase("exitCollection")) {
builder.append("{oe:ecCode}").append(" in (?").append(paramName).append(")");
} else {
builder.append("{or:").append(paramName).append("}").append(" in (?").append(paramName).append(")");
}
}
}
The query string before the search(query).getResult() function is:
query: [select sum({oe:totalPrice}) from {Order as or join CustomerOrderStatus as os on {or:CustomerOrderStatus}={os:pk}
join OrderEntry as oe on {or.pk}={oe.order}} where {or:versionID} is null
and {or:orderType} in (?orderType) and {or:company} in (?company)
and {or:pointOfSale} in (?pointOfSale) and {oe:ecCode} in (?exitCollection)
and {or:yearSeason} in (?yearSeason) and {os:code} not in ('CANCELED', 'NOT_APPROVED')],
query parameters: [{orderType=OrderTypeModel (8796093230839),
pointOfSale=B2BUnitModel (8796097413125), company=CompanyModel (8796093710341),
exitCollection=[13, 14], yearSeason=YearSeasonModel (8796093066981)}]
but after the search(query) result is [null].
Why? Where I wrong in the Java code? Thanks.
In addition, if you want to disable restriction in your java code. You can do like this ..
#Autowired
private SearchRestrictionService searchRestrictionService;
private BigDecimal findGroupedOrdersData(String total, String uncDisc, String orderPromo,
Map<String, Object> queryParameters) {
searchRestrictionService.disableSearchRestrictions();
// You code here
searchRestrictionService.enableSearchRestrictions();
return aggregatedValue;
}
In the above code, You can disabled the search restriction and after the search result, you can again enable it.
OR
You can use sessionService to execute flexible search query in Local View. The method executeInLocalView can be used to execute code within an isolated session.
(SearchResult<? extends ItemModel>) sessionService.executeInLocalView(new SessionExecutionBody()
{
#Override
public Object execute()
{
sessionService.setAttribute(FlexibleSearch.DISABLE_RESTRICTIONS, Boolean.TRUE);
return flexibleSearchService.search(query);
}
});
Here you are setting DISABLE RESTRICTIONS = true which will run the query in admin context [Without Restriction].
Check this
Better i would suggest you to check what restriction exactly applying to your item type. You can simply check in Backoffice/HMC
Backoffice :
Go to System-> Personalization (SearchRestricion)
Search by Restricted Type
Check Filter Query and analysis your item data based on that.
You can also check its Principal (UserGroup) on which restriction applied.
To confirm, just check by disabling active flag.
Query in the code is running not under admin user (most likely).
And in this case the different search Restrictions are applied to the query.
You can see that the original query is changed:
start DB logging (/hac -> Monitoring -> Database -> JDBC logging);
run the query from the code;
stop DB logging and check log file.
More information: https://wiki.hybris.com/display/release5/Restrictions
In /hac console the admin user is usually used and restrictions will not be applied because of this.
As the statement looks ok to me i'm going to go with visibility of the data. Are you able to see all the items as whatever user you are running the query as? In the hac you would be admin obviously.

avoid null pointer excpetion while parsing the xml

This is my xml to parse
<metadata>
<groupId>org.chromium</groupId>
<artifactId>chromedriver-win32</artifactId>
<versioning>
<release>2.14</release>
<versions>
<version>2.14</version>
</versions>
<lastUpdated>20150610112540</lastUpdated>
</versioning>
</metadata>
While I am trying to parse the above XML, I am getting NullPointerException even though I have handled the null check. Below is the code
private String getVersionFromNode(Element eElement) {
String version = null;
// Get the latest version
String tagName = "latest";
try {
version = eElement.getElementsByTagName(tagName).item(0).getTextContent();
// If latest version is not available take the release
// version
if ( version.isEmpty() || null == version || "null" == version) {
tagName = "release";
version = eElement.getElementsByTagName(tagName).item(0).getTextContent();
}
}
catch (NullPointerException e) {
System.out.println("not able to parse " + tagName + " tag " + e.getMessage());
}
return version;
}
When the version is null, it should enter in below block.
if ( version.isEmpty() || null == version || "null" == version) {
tagName = "release";
version = eElement.getElementsByTagName(tagName).item(0).getTextContent();
}
What should be solution for this problem?
Your String tagName is "latest" and in your xml file, there is no element named latest and so your version remains null and therefore a NullPointerException is generated when the code:
version.isEmpty()
is executed in your if statement. Because version is null. And your code tries to check if null is empty. Which it cannot. And so, a NullPointerException is generated here.
To handle this situation, first check if version is null. Secondly check if the string version is equal to string "null". And thirdly check if it is empty. So change the sequence of conditions in your if statement from:
if ( version.isEmpty() || null == version || "null" == version)
to
if (null == version || "null" == version || version.isEmpty())
By the way, as a side tip, use:
"null".equals(version)
rather than
"null" == version
Change your condition
if ( version.isEmpty() || null == version || "null" == version)
to
if (null == version || "null".equals(version) || version.isEmpty())
When chaining together method calls, you risk a NullPointerException at every step. For example, in your line
version = eElement.getElementsByTagName(tagName).item(0).getTextContent();
there are 4 opportunities for a NullPointerException:
if eElement is null, trying to call getElementsByTagName(tagName)
if calling getElementsByTagName(tagName) when tagName is null
if getElementsByTagName(tagName) returns null, trying to call item(0)
if item(0) returns null, trying to call getTextContent()
Not all of these will be possible in your code because tagName is specified, but you should always beware.
An alternative approach for your problem would be to use XPath
See also How to read XML using XPath in Java

Why equals might not return true

I have this string: "no_questions_by_user" in a variable named result.
than I do this check:
if ( result != null && result.equals( "no_user_id" ) )
{
Log.d( "Post execute: " , "NOOOT OKKKK - no user id" );
}
else
if ( result != null && result.equals( "database_error" ) )
{
Log.d( "Post execute: " , "NOOOT OKKKK - database error" );
}
else
if ( result != null && result.equals( "no_questions_by_user" ) )
{
Log.d( "Post execute: " , "NOOOT OKKKK - no questions by user so far" );
}
else
{
Log.d( "MyQuestionsActivity" , "In JSON parsing area.." );
}
and it always goes to the last else. But in my understanding it should really go to the block which checks result.equals( "no_questions_by_user" )
any idea why that block does not get executed?
Thanks!!
The code looks good. Your variable result must have another value.
My guess is that there are some whitespaces at the end or beginning of your result string.
Personally, I think this code is a hot mess.
I'd write one method that took in a result and looked up a message in a Map. All those if tests are making my eyes bleed:
private static final Map<String, String> LOG_MESSAGE_MAP;
static {
LOG_MESSAGE_MAP = new HashMap<String, String>();
// put all your result, message pairs in here
}
public void logResultDependentMessage(String result) {
log.debug(LOG_MESSAGE_MAP.get(result));
}
Now adding new result, message pairs just means inserting into the map. If you're using something like Spring you can do it in configuration and not touch the code.
Try:
result.trim().equals( "no_questions_by_user" )
Did you see "no_questions_by_user" in a debbugger ?
You can try to trim it before the test, as spaces are hard to detect in debuggers.
Make sure there are no white spaces in the value of the "result" variable.
Before entering the if statements, you can do a print line like this one.
System.out.println("The Value of result variable is=\"" + result + "\"");
You might as well do this
if ( result != null && result.trim().equals( "no_questions_by_user" ) )
{
Log.d( "Post execute: " , "NOOOT OKKKK - no questions by user so far" );
}
I advise you to use some static variables to store your strings, so you avoid typing errors.

Categories

Resources