Error in getting user nodes while giving no. of hops as an input using spring with neo4j query - spring-data-neo4j

I am executing the query using spring with neo4j..
#Query(value = "START me=node({0}) MATCH me-[:ACTIVEFRIEND*1..{1}]->friend RETURN friend")
public Iterable<User> searchUserInNHops(User a, int hops);
where the depth threshold which the search should go is given as an input hops..
It is not working and giving the error..
The server encountered an internal error that prevented it from fulfilling this request
Request processing failed; nested exception is org.neo4j.rest.graphdb.RestResultException: Properties on pattern elements are not allowed in MATCH
Neo4j Version: 1.9.0
I will appreciate if someone can help me on this.
Thanks
Hemant

You can't specify the depth as a paramater. If you want this to be dynamic, you might want to consider alternative approaches. Some of them are:
Let your repository class extend from CypherDslRepository. Use should use the neo4j-cypher-dsl module to build a query object.
Use the Neo4jTemplate class. You could provide a composed query string to the query method.
Use the traversal API of Neo4j core, like
Traversal:
for (final Path position : Traversal.description().depthFirst() .relationships(RelationType.ACTIVE_FRIEND, Direction.OUTGOING),
Direction.INCOMING).evaluator(Evaluators.fromDepth(1))
.evaluator(Evaluators.toDepth(yourDynamicValue))
.evaluator(Evaluators.excludeStartPosition()).traverse(node)) {
position.endNode();
}

Related

Regex in #Path matches only only 1 of 2 two routes specified, resulting in 404

Here is what dropwizard logs to the console in terms configured resources and their paths:
INFO [07:07:13.741] i.d.jersey.DropwizardResourceConfig: The following paths were found for the configured resources:
DELETE /apps/affiliate/internal/v1/templates/ (aff.affiliate.http.internal.AffiliateURLTemplatesInternalAPIEndpoint)
GET /apps/affiliate/internal/v1/templates/ (aff.affiliate.http.internal.AffiliateURLTemplatesInternalAPIEndpoint)
POST /apps/affiliate/internal/v1/templates/ (aff.affiliate.http.internal.AffiliateURLTemplatesInternalAPIEndpoint)
GET /apps/affiliate/v1/generate-url (aff.affiliate.http.AffiliateEndpoint)
GET /apps/affiliate/v1/redirect-search-url (aff.affiliate.http.AffiliateEndpoint)
GET /openapi.{type:json|yaml} (io.swagger.v3.jaxrs2.integration.resources.OpenApiResource)
GET /{path: apps/affiliate/v1/redirect|api/affiliate/v1/redirect} (aff.affiliate.http.RedirectEndpoint)
The problem is with the last path, specified as a regular expression.
My expectation is that it should trigger for incoming requests to both /apps/affiliate/v1/redirect and /api/affiliate/v1/redirect.
However, visiting /apps/affiliate/v1/redirect results in a 404, but visiting api/affiliate/v1/redirect results in a 200. How can I get my resource to respond to either of those paths?
The code is hard to provide but this is essentially the scaffolding (fwiw, all methods work/api works, I'm just having trouble having one of the methods respond to the regex (my actual problem)).
// AffiliateURLTemplatesInternalAPIEndpoint.kt
#Path("/apps/affiliate/internal/v1/templates")
#Produces(MediaType.APPLICATION_JSON)
public class AffiliateURLTemplatesInternalAPIEndpoint() : DropwizardResource() {
#GET
#Path("/")
public fun methodA()
#POST
#Path("/")
public fun methodB()
#DELETE
#Path("/")
public fun methodC()
}
// AffiliateEndpoint.kt
#Path("/apps/affiliate/v1")
class AffiliateEndpoint() : DropwizardResource() {
#GET
#Path("generate-url")
fun methodA()
#GET
#Path("redirect-search-url")
fun methodB()
// RedirectEndpoint.kt
#Path("/{path: apps/affiliate/v1/redirect|api/affiliate/v1/redirect}")
#Produces(MediaType.APPLICATION_JSON)
class RedirectEndpoint() : DropwizardResource() {
#GET
fun methodA()
The 404 is indeed being correctly returned.
Why? JAX-RS’ URL Matching Algorithm.
It was only after #Paul Samsotha asked me to paste my code that I finally realized the reason for the 404. 🤦
The Dropwizard/Jersey output I was relying on shows all the routes it found, but leaves out critical context about how paths have been structured in the code. Due to the way JAX-RS has implemented route matching sorting and precedence roles, code structure is essential in determining which routes will be triggered. So in this case the helpful output ended up being mostly misleading.
Read Section 3.7 - Matching Requests to Resource Methods of JAX-RS Spec 3.0 if you dare, but the answers are there.
Also, Chapter 4 of Bill Burke's RESTful Java with JAX-RS 2.0 gives great insight into route matching behavior. Unfortunately it doesn't go into clarifying an important distinction (the exact situation I got into) which is that you can't simply combine a resource and its methods paths (like the output) when applying JAX-RS url matching rules. Actually, I went through a bunch of JAX-RS write ups and none of them mentioned this actual distinction.
Instead you first try to find a match a root resource class, then look at resource methods. If you don't find a match either at the root or method level, you must return a 404.
Still, I found it to be a great resource at shining light on the spec and is much less intimidating that the spec.
Now to the actual explanation of the 404.
Jersey (which implements the JAX-RS spec), first collects all the paths associated with root resources:
/apps/affiliate/internal/v1/templates
/apps/affiliate/v1
/{path: apps/affiliate/v1/redirect|api/affiliate/v1/redirect}
It then applies its sorting and precedence logic according the spec (paraphrased from Burke's book):
The primary key of the sort is the number of literal characters in the full URI matching pattern. The sort is in descending order.
If two or more patterns rank similar in the first, then the secondary key of the sort is the number of template expressions embedded within the pattern. This sort is in descending order.
Finally, if two or more patterns rank similar in the second, then the tertiary key of the sort is the number of non-default template expressions. A default template expression is one that does not define a regular expression.
When an incoming GET request to /apps/affiliate/v1/redirect arrives, both
/apps/affiliate/v1
/{path: apps/affiliate/v1/redirect|api/affiliate/v1/redirect}
match, but the first pattern takes precedence because it has the greatest number of literal characters that match (18 vs 1).
Now that a root resource is selected, it looks at root resource's methods and compiles a list of available paths/http methods that match the incoming request. A bit of an extra detail, but for pattern matching purposes at the method level, the root resource's path will be concatenated to the resource method's path.
The following patterns are available to select from:
GET /apps/affiliate/v1/generate-url
GET /apps/affiliate/v1/redirect-search-url")
Since the request was a GET to /apps/affiliate/v1/redirect neither of the above routes match. Hence my 404 :(.
It makes complete sense, but I got into this rabbit hole because my assumptions about routing rules and precedence from experience working with other routing libraries did not align with the actual JAX-RS specs. I expected the library to have a master list for each and every method available (much like the initial output from Dropwizard/Jersey) and for each request to run through sorting and precedence rules on that master list. Alas, that is not the case.

Unable to call object from a List located in external BeanShell script [Jmeter]

My end goal here is to get a string from a list that is created dynamically from a JSON response. I am having troubles calling a value from the list that is created in an external BeanShell script. The external script reads the JSON response and creates the list from the filtered response.
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Filter;
try{
String json = new String(prev.getResponseDataAsString());
List allPositiveAffects = JsonPath.read(json, "$.affectTags[?(#.value > 0.0)].key", new Filter[]{});
vars.putObject("allPositiveAffects",allPositiveAffects);
log.info("allPositiveAffects: " + allPositiveAffects);
int positiveAffectCount = allPositiveAffects.size();
vars.put("positiveAffectCount",Integer.toString(positiveAffectCount));
} catch (Throwable ex){
log.error("Error:\n", ex);
}
allPositiveAffects returns the expected values, so now I want to get one of those values into a subsequent JSON POST.
My Jmeter test setup:
- Thread Group
+ JSON GET request
- BeanShell PostProcessor
+ JSON POST request
Attempting to get a value from allPositiveAffects has proven to be not as easy as calling allPositiveAffects.get(n) like I can within my BeanShell script.
I haven't figured out an easy way to get the contents of the Lists. Am I missing something? I have tried several different things in my JSON POST request. The latest being:
//json POST data
{
"entries":[
"id": -1,
"key": "${__BeanShell(${allPositiveAffects}.get(1))}"]
}
Which returns the following error:
java.lang.ClassCastException: net.minidev.json.JSONArray cannot be cast to java.lang.String
Any help on a solution or workaround for this would be greatly appreciated. It would be a lot easier for me to be able to call a List instead of creating various variables.
I believe that you could just add .toString() to your expression like:
`${__BeanShell(${allPositiveAffects}.get(1).toString())}`
By the way, Beanshell has some performance overhead so I would rather suggest going for JSON Path Extractor which is available via Extras with Libs Set of JMeter Plugins package, it should be more convenient and less resource consuming.
See Using the XPath Extractor in JMeter (scroll down to "Parsing JSON") for installation instructions and some JSON Path language reference examples.

Get all PrettyFaces mapping ids before FacesContext is available?

I need to test some strings against the existing mapping ids, I would like to get all the mapping ids before runtime (statically), is this possible ?
In theory PrettyFaces would only have to parse the pretty-config.xml in order to allow this, but currently calling PrettyContext.getCurrentInstance().getConfig().getMappings() will fail as the faces context is not available...
In this case, you should use: PrettyContext.getCurrentInstance(final HttpServletRequest request)
This will give you access to the configuration without using .getCurrentInstance() - which is only one way of obtaining the PrettyContext, and happens to require an active FacesContext.

Designing of a WebService API for paths between two points

I have a Web Service which returns details of path between given two input points if exists. The Web Service API is something like getPath(Point start,Point end). Now if the path doesn't exist between given start & end points, how should API behave among below options
Return a null object
Throw a PathNotFoundException
Always include a status code in the response along with path details. In this case return empty path and status code as appropriate error code like "PATH_NOT_FOUND" / "ERROR"
Any other option? Please suggest.
Please let me know your views
Thanks,
Harish
Suggestion: 1. return null or empty path.
Throwing exceptions across http is probably not the best idea and returning status codes is a way to workaround throwing exceptions. The lack of a path is not something that should occur as error at the client side.
I would reserve exceptions/status codes for wrong parameters, wrong number of parameters, some server-side problems like inaccessible database etc.
Suppose you are querying the database for a list of customers from NY. Would you throw an exception if the list is empty or just return an empty list? This sounds exactly like your scenario.

CAML query in getLIstItems method returns no rows of items

I am invoking Sharepoint's List Web services and using the getListItems() method. In particular, I am keen on specifying a CAML query because I really want it to just retrieve one item that I am specifically interested in. This I am doing by specifying a query in my XML string, in varying degrees of combinations, either by specifying the EncodedAbsUrl, the LinkFileName, the URL or the FileRef, with most results returning 0.
The XML query looks like this :
<?xml version="1.0" ?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body><GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/"><listName>{5cbc4407-3851-4e00-964a-bb7e9b430f9f}</listName> <viewName></viewName> <rowLimit>1000</rowLimit> <webID></webID>
**<query><Query><Where><Eq><FieldRef Name = "FileRef"/><Value Type = "Text">"/Shared%20Documents/Ashish/Word_feb27.doc"</Value></Eq></Where></Query></query>**
<viewFields><ViewFields><FieldRef Name="FSObjType"/><FieldRef Name="LinkFilename"/><FieldRef Name="UniqueId"/><FieldRef Name="FileRef"/><FieldRef Name="FileRef"/><FieldRef Name="EncodedAbsUrl"/><FieldRef Name="FileSizeDisplay"/><FieldRef Name="_UIVersionString"/><FieldRef Name="_owshiddenversion"/></ViewFields></viewFields></GetListItems> </S:Body></S:Envelope>
Without the tags this Soap request does infact work, and it retrieves all the items that area available in the List. The frustration begins when i specify the query tag. In particular the Following combinations have been attempted by me
FieldRef.name = {LinkFileName, EncodedAbsUrl, URL,FileRef} and Value.type = {Text, URL}
Either they yield results with no 0 fields in it or they return internal errors. I figure, this is a syntactical issue and would rather shoot this question to you guys who have probably dunnit in the past to see where I am possibly messing it up.
Thanks
I would recommend using CAML Query Builder and Fiddler. Query builder can connect SP using Web services and you can build the query with that. After you got your expected results, capture the Web service request with Fiddler and use it :)
BTW: Have you considered using Sharepoint Client Object model? You do not have to worry about SOAP messages.
Remove the <query><Query> tags.