Neo4jClient Transaction Error - neo4j

When I try to update an existing Node in Neo4JClient without using transaction, which has a Unique Constraint on Id and Name property, I receive this Exception:
CypherExecutionException: Node 6 already exists with label User and property "Name"=[Mike]
But when I try to update a Node in transaction, I receive this Exception:
Received an unexpected HTTP status when executing the request.
The response status was: 404 Not Found
The response from Neo4j (which might include useful detail!) was: {"results":[],"errors":[{"code":"Neo.ClientError.Transaction.UnknownId","message":"Unrecognized transaction id. Transaction may have timed out and been rolled back."}]}
My Code is like this:
using (var transaction = client.BeginTransaction())
{
client.Cypher
.Merge("(user:User { Id: {id}})")
.OnCreate().Set("user = {user}")
.OnMatch().Set("user = {user}")
.WithParams(new { id = user.Id, user = user })
.ExecuteWithoutResults();
transaction.Commit();
}
My question is: Is there a way to get the actual error when using transaction, like I get one when I don't use transaction?
Thanks
EDIT 1:
It looks like the NULL Id in not being handled correctly. After drilling down, I managed to pull the actual error. The first exception in is:
errors = {[
{
"code": "Neo.ClientError.Statement.InvalidSemantics",
"message": "Cannot merge node using null property value for Id"
}
]}
The stack trace for this exception is:
at Neo4jClient.Serialization.CypherJsonDeserializer1.GetRootResultInTransaction(JObject root) in [PATH_HIIDEN]\Neo4jClient\Serialization\CypherJsonDeserializer.cs:line 316
at Neo4jClient.Serialization.CypherJsonDeserializer1.CheckForErrorsInTransactionResponse(String content) in [PATH_HIIDEN]\Neo4jClient\Serialization\CypherJsonDeserializer.cs:line 291
at Neo4jClient.GraphClient.<>c__DisplayClass84_01.<PrepareCypherRequest>b__0(Task1 responseTask) in [PATH_HIIDEN]\Neo4jClient\GraphClient.cs:line 933
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
And after that there is the exception with 404 NOT Found error. For that the stack trace is:
at Neo4jClient.Execution.HttpResponseMessageExtensions.EnsureExpectedStatusCode(HttpResponseMessage response, String commandDescription, HttpStatusCode[] expectedStatusCodes) in [PATH_HIIDEN]\Neo4jClient\Execution\HttpResponseMessageExtensions.cs:line 41
at Neo4jClient.Execution.HttpResponseMessageExtensions.EnsureExpectedStatusCode(HttpResponseMessage response, HttpStatusCode[] expectedStatusCodes) in [PATH_HIIDEN]\Neo4jClient\Execution\HttpResponseMessageExtensions.cs:line 14
at Neo4jClient.Execution.ResponseBuilder.<>c__DisplayClass21_0.b__0(Task1 requestTask) in [PATH_HIIDEN]\Neo4jClient\Execution\ResponseBuilder.cs:line 127
at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
Can this error be fixed in the next release please?
EDIT 2
using (var transaction = client.BeginTransaction())
{
manifest.Users = client.Cypher
.Merge("(n:User { Id: '8be0b8fd-c433-44d3-a7e2-3f0d1a03fefa'}) " +
"ON CREATE " +
"SET n = { " +
"Id: '8be0b8fd-c433-44d3-a7e2-3f0d1a03fefa', " +
"UserName: 'test.user', " +
"Name: 'Test User', " +
"Active: true " +
"} " +
"ON MATCH " +
"SET n = { " +
"Id: '8be0b8fd-c433-44d3-a7e2-3f0d1a03fefa', " +
"UserName: 'test.user', " +
"Name: 'Test User', " +
"Active: true " +
"}")
.Return(n => n.As<User>())
.Results
.ToList();
transaction.Commit();
}
Meaning fluent Api is causing the error.

So the problem is that in Neo4j 2.2.6 a change was introduced whereby any ClientError (Constraint Violation etc) resulted in an automatic Rollback of a transaction on the server.
Neo4jClient already did an auto-rollback on error, and continued to do so. With 2.2.6 this resulted in a 404 error as the transaction was no longer there (previous versions were fine).
So, I've made a fix and published an updated Nuget package, so version 1.1.0.12 of Neo4jClient will now give you the correct response.

Related

From deprecated cliOnline to OnlineNodeCommand

So I created this groovy script but read that the cliOnline() command is deprecated.
But I can't seem to figure out how to actually change my code to use hudson.model.Hudson.instance.OnlineNodeCommand()?
deprecated cliOnline
def nodes_checklist = ["PD100069", "PD100070", "PD100090", "PD10756"]; // List of nodes which should be turned online
def jenkinsNodes = jenkins.model.Jenkins.instance.getNodes() // Get all existing nodes on this Jenkins URL
for(def node_checker: nodes_checklist) {
for(def node: jenkinsNodes) {
if(node.getNodeName().contains(node_checker)) {
println "The node " + node.getNodeName() + "'s offline status: " + node.toComputer().isOffline()
if (node.toComputer().isOffline()){
println "Turning " + node.getNodeName() + " online"
node.toComputer().cliOnline() // If node is offline, turn it online
println node.getNodeName() + "'s online status: " node.toComputer().isOnline()
}
}
}
}
Does anyone know how to rewrite this to use the non-deprecated version?
If you look at this depricated method, it simply calls a non depricated method setTemporarilyOffline(boolean temporarilyOffline, OfflineCause cause). So not sure why this was depricated. Anyway instead of using cliOnline() you can use setTemporarilyOffline. Check the following.
node.getComputer().setTemporarilyOffline(false, null)
Some proper code with a proper cause. Cause is not really needed when setting the node online though.
import hudson.slaves.OfflineCause.UserCause
def jenkinsNodes = Jenkins.instance.getNodes()
for(def node: jenkinsNodes) {
if (node.getComputer().isTemporarilyOffline()){
node.getComputer().setTemporarilyOffline(false, null)
}
}
Setting to temporarily offline
UserCause cause = new UserCause(User.current(), "This is a automated process!!")
node.getComputer().setTemporarilyOffline(true, cause)

Unknown Exception "null- Error while parsing the metadata." While executing DefaultSalesOrderService () - updateSalesOrder ()

As part of a PoC, I am currently trying to build a prototype for a side-by-side extension of S/4HANA Cloud, consisting of two layers: A SAPUI5 Frontend decoupled from a Java backend using the S/4HANA Cloud SDK.
On the whole it works great as well. But I often had trouble with the UPDATE commands, so I wrote a small servlet for demo purposes. Now I always get the same exception during the update, namely "Error while parsing the metadata".
I have already tried everything and now have no idea what could be the trigger for this exception.
I was trying to add more dependencies in the pom.xml, but that was without success. Also unsuccessful was the attempt to get all fields with the GET command and to update the filled object. The ETag is also not the problem, this is handled since the latest release by the "versionIdentifier" excellent.
If one of you has any idea of where my mistake lies, I would be very grateful!
Thanks in advance for your help!
[OLD] Code Snippet: public class UpdateService extends HttpServlet
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Test-Run: UPDATE
response.getWriter().write("Test-Run: UPDATE" + "\n");
// Prepare the S/4HANA Cloud Service
DefaultSalesOrderService service = new DefaultSalesOrderService();
// Prepare the required Variables
String salesOrderKey = "1";
String deliveryBlockReason = "01";
SalesOrder salesOrder;
try {
// Get the Sales Order
response.getWriter().write("Step 1: Get old data.." + "\n");
salesOrder = service.getSalesOrderByKey(salesOrderKey).select(SalesOrder.DELIVERY_BLOCK_REASON).execute();
// Output: OLD DATA
response.getWriter().write(new Gson().toJson(salesOrder) + "\n");
// Change the Data
response.getWriter().write("\n" + "Step 2: Set new data.." + "\n");
salesOrder.setDeliveryBlockReason(deliveryBlockReason);
// Output: NEW DATA
response.getWriter().write(new Gson().toJson(salesOrder) + "\n");
// Save the Changes
response.getWriter().write("\n" + "Step 3: Save new data.." + "\n");
service.updateSalesOrder(salesOrder).execute();
// Success Message
response.getWriter().write("\n" + "Update successful!");
} catch (final ODataException e) {
// Handle Errors
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("\n" + "Update failed!" + "\n");
response.getWriter().write("Error Code: " + e.getCode() + "\n");
response.getWriter().write("Message: " + e.getMessage() + "\n");
}
}
[OLD] Http-Response
Test-Run: UPDATE
Step 1: Get old data..
{"DeliveryBlockReason":"","versionIdentifier":"W/\"datetimeoffset\u00272017-06-19T08%3A31%3A55.6635100Z\u0027\""}
Step 2: Set new data..
{"DeliveryBlockReason":"01","versionIdentifier":"W/\"datetimeoffset\u00272017-06-19T08%3A31%3A55.6635100Z\u0027\""}
Step 3: Save new data..
Update failed!
Error Code: null
Message: Error while parsing the metadata.
UPDATE - 2018-04-18
First of all, thanks for your help!
I reprogrammed the code a bit and implemented Henning's workaround. At first glance, everything seems to work. There are no exceptions and no warnings.
However, in the backend you can see that, that the actual values remain unchanged. Would you have another advice for me?
[NEW] Code Snippet: public class UpdateService extends HttpServlet
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// Test-Run: UPDATE
response.getWriter().write("Test-Run: UPDATE" + "\n");
// Prepare the S/4HANA Cloud Service
DefaultSalesOrderService service = new DefaultSalesOrderService();
// Prepare the Sales Order Object
SalesOrder salesOrder = null;
// Prepare the required Variables
String salesOrderKey = "163";
// GET
try {
salesOrder = service.getSalesOrderByKey(salesOrderKey).select(SalesOrder.ALL_FIELDS).execute();
// Success Message
response.getWriter().write("\n" + "GET successful!:" + "\n");
// Output: OLD DATA
response.getWriter().write("Old Data:" + "\n");
response.getWriter().write(new Gson().toJson(salesOrder) + "\n");
} catch (ODataException e) {
// Handle Errors
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("\n" + "GET failed!" + "\n");
response.getWriter().write("| Error Code: " + e.getCode() + "\n");
response.getWriter().write("| Message: " + e.getMessage() + "\n");
}
// CHANGE
salesOrder.setSalesOrderType("SO");
// Success Message
response.getWriter().write("\n" + "CHANGE successful!:" + "\n");
// Output: NEW DATA
response.getWriter().write("New Data:" + "\n");
response.getWriter().write(new Gson().toJson(salesOrder) + "\n");
// UPDATE
try {
// Workaround - Henning Heitkötter -
// https://stackoverflow.com/questions/49862888/unknown-exception-null-error-while-parsing-the-metadata-while-executing-defa
SalesOrderUpdateFluentHelper updateHelper = new SalesOrderUpdateFluentHelper(salesOrder) {
#Override
public ODataUpdateRequest toQuery() {
ODataUpdateRequestBuilder requestBuilder = getQueryBuilder()
.withErrorHandler(new ODataVdmErrorResultHandler());
getEntity().setSalesOrder(null);
final Map<String, Object> params = new ODataJsonMapResolver(getEntity()).withoutNullValues();
return requestBuilder.withBodyAsMap(params).build();
}
};
// EXECUTE
updateHelper.execute();
// Success Message
response.getWriter().write("\n" + "UPDATE successful!" + "\n");
} catch (ODataException e) {
// Handle Errors
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write("\n" + "UPDATE failed!" + "\n");
response.getWriter().write("| Error Code: " + e.getCode() + "\n");
response.getWriter().write("| Message: " + e.getMessage() + "\n");
}
}
[NEW] Http-Response
Test-Run: UPDATE
GET successful!:
Old Data:
{"SalesOrder":"163","SalesOrderType":"OR","SalesOrganization":"1010","DistributionChannel":"10","OrganizationDivision":"00","SalesGroup":"","SalesOffice":"","SalesDistrict":"","SoldToParty":"1000355","CreationDate":1516752000000,"CreatedByUser":"CB9980000321","LastChangeDateTime":1516793069586,"PurchaseOrderByCustomer":"110","CustomerPurchaseOrderType":"","CustomerPurchaseOrderDate":1516752000000,"SalesOrderDate":1516752000000,"TotalNetAmount":35.00,"TransactionCurrency":"EUR","SDDocumentReason":"","PricingDate":1516752000000,"RequestedDeliveryDate":1516752000000,"ShippingCondition":"","CompleteDeliveryIsDefined":false,"ShippingType":"","HeaderBillingBlockReason":"","DeliveryBlockReason":"","IncotermsClassification":"CFR","IncotermsTransferLocation":"DE","IncotermsLocation1":"DE","IncotermsLocation2":"","IncotermsVersion":"","CustomerPaymentTerms":"0001","PaymentMethod":"","OverallSDProcessStatus":"A","TotalCreditCheckStatus":"","OverallTotalDeliveryStatus":"","OverallSDDocumentRejectionSts":"A","versionIdentifier":"W/\"datetimeoffset\u00272018-01-24T11%3A24%3A29.5861550Z\u0027\"","AssignmentReference":""}
CHANGE successful!:
New Data:
{"SalesOrder":"163","SalesOrderType":"SO","SalesOrganization":"1010","DistributionChannel":"10","OrganizationDivision":"00","SalesGroup":"","SalesOffice":"","SalesDistrict":"","SoldToParty":"1000355","CreationDate":1516752000000,"CreatedByUser":"CB9980000321","LastChangeDateTime":1516793069586,"PurchaseOrderByCustomer":"110","CustomerPurchaseOrderType":"","CustomerPurchaseOrderDate":1516752000000,"SalesOrderDate":1516752000000,"TotalNetAmount":35.00,"TransactionCurrency":"EUR","SDDocumentReason":"","PricingDate":1516752000000,"RequestedDeliveryDate":1516752000000,"ShippingCondition":"","CompleteDeliveryIsDefined":false,"ShippingType":"","HeaderBillingBlockReason":"","DeliveryBlockReason":"","IncotermsClassification":"CFR","IncotermsTransferLocation":"DE","IncotermsLocation1":"DE","IncotermsLocation2":"","IncotermsVersion":"","CustomerPaymentTerms":"0001","PaymentMethod":"","OverallSDProcessStatus":"A","TotalCreditCheckStatus":"","OverallTotalDeliveryStatus":"","OverallSDDocumentRejectionSts":"A","versionIdentifier":"W/\"datetimeoffset\u00272018-01-24T11%3A24%3A29.5861550Z\u0027\"","AssignmentReference":""}
UPDATE successful!
[NEW] S/4HANA Cloud API
<entry m:etag="W/"datetimeoffset'2018-01-24T11%3A24%3A29.5861550Z'"">
<id>
...../sap/opu/odata/sap/API_SALES_ORDER_SRV/A_SalesOrder('163')
</id>
<title type="text">A_SalesOrder('163')</title>
<updated>2018-04-18T16:03:24Z</updated>
<category term="API_SALES_ORDER_SRV.A_SalesOrderType" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<link href="A_SalesOrder('163')" rel="edit" title="A_SalesOrderType"/>
<link href="A_SalesOrder('163')/to_Item" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/to_Item" type="application/atom+xml;type=feed" title="to_Item"/>
<link href="A_SalesOrder('163')/to_Partner" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/to_Partner" type="application/atom+xml;type=feed" title="to_Partner"/>
<link href="A_SalesOrder('163')/to_PricingElement" rel="http://schemas.microsoft.com/ado/2007/08/dataservices/related/to_PricingElement" type="application/atom+xml;type=feed" title="to_PricingElement"/>
<content type="application/xml">
<m:properties xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices">
<d:SalesOrder>163</d:SalesOrder>
<d:SalesOrderType>OR</d:SalesOrderType>
<d:SalesOrganization>1010</d:SalesOrganization>
<d:DistributionChannel>10</d:DistributionChannel>
<d:OrganizationDivision>00</d:OrganizationDivision>
<d:SalesGroup/>
<d:SalesOffice/>
<d:SalesDistrict/>
<d:SoldToParty>1000355</d:SoldToParty>
<d:CreationDate>2018-01-24T00:00:00</d:CreationDate>
<d:CreatedByUser>CB9980000321</d:CreatedByUser>
<d:LastChangeDate m:null="true"/>
<d:LastChangeDateTime>2018-01-24T11:24:29.5861550Z</d:LastChangeDateTime>
<d:PurchaseOrderByCustomer>110</d:PurchaseOrderByCustomer>
<d:CustomerPurchaseOrderType/>
<d:CustomerPurchaseOrderDate>2018-01-24T00:00:00</d:CustomerPurchaseOrderDate>
<d:SalesOrderDate>2018-01-24T00:00:00</d:SalesOrderDate>
<d:TotalNetAmount>35.00</d:TotalNetAmount>
<d:TransactionCurrency>EUR</d:TransactionCurrency>
<d:SDDocumentReason/>
<d:PricingDate>2018-01-24T00:00:00</d:PricingDate>
<d:RequestedDeliveryDate>2018-01-24T00:00:00</d:RequestedDeliveryDate>
<d:ShippingCondition/>
<d:CompleteDeliveryIsDefined>false</d:CompleteDeliveryIsDefined>
<d:ShippingType/>
<d:HeaderBillingBlockReason/>
<d:DeliveryBlockReason/>
<d:IncotermsClassification>CFR</d:IncotermsClassification>
<d:IncotermsTransferLocation>DE</d:IncotermsTransferLocation>
<d:IncotermsLocation1>DE</d:IncotermsLocation1>
<d:IncotermsLocation2/>
<d:IncotermsVersion/>
<d:CustomerPaymentTerms>0001</d:CustomerPaymentTerms>
<d:PaymentMethod/>
<d:AssignmentReference/>
<d:OverallSDProcessStatus>A</d:OverallSDProcessStatus>
<d:TotalCreditCheckStatus/>
<d:OverallTotalDeliveryStatus/>
<d:OverallSDDocumentRejectionSts>A</d:OverallSDDocumentRejectionSts>
</m:properties>
</content>
</entry>
The error while parsing metadata occurs because the key field SalesOrder is not set on your entity. You would need to retrieve it as part of the get-by-key as follows, and then you can change the fields that allow changes in SAP S/4HANA, such as the requested delivery date:
SalesOrder salesOrder = service.getSalesOrderByKey(salesOrderKey)
.select(SalesOrder.SALES_ORDER)
.execute()
salesOrder.setRequestedDeliveryDate(Calendar.getInstance());
service.updateSalesOrder(salesOrder).execute();
As of version 1.11.1 of the SAP S/4HANA Cloud SDK, this will only send changed fields (or any field that you explicitly specify via includingFields).
Note: Some fields such as the SalesOrderType or DeliveryBlockReason cannot be changed via the API.
Make sure to use the most recent version of the SAP S/4HANA Cloud SDK, at least version 1.11.1.
Which version of the S/4HANA Cloud SDK are you using?
If you're not using 1.10.0, kindly upgrade to this version (latest version currently) and retry.
I assume you're connecting to a current SAP S/4HANA release, am I right?
Kindly reproduce the error and open transaction /n/iwfnd/error_log.
Look for respective error messages and provide them here along with the corresponding response header and body.
Make sure that you omit any confidential information.

Timeout Notification for Asynchronous Request

I am sending SPARQL queries as asynchronous requests to a SPARQL endpoint, currently DBpedia using the dotNetRDF library. While simpler queries usually work, more complex queries sometimes result in timeouts.
I am looking for a way to handle the timeouts by capturing some event when they occur.
I am sending my queries by using one of the asynchronous QueryWithResultSet overloads of the SparqlRemoteEndpoint class.
As described for SparqlResultsCallback, the state object will be replaced with an AsyncError instance if the asynchronous request failed. This does indicate that there was a timeout, however it seems that it only does so 10 minutes after the request was sent. When my timeout is, for example, 30 seconds, I would like to know 30 seconds later whether the request was successful. (35 seconds are ok, too, but you get the idea.)
Here is a sample application that sends two requests, the first of which is very simple and likely to succeed within the timeout (here set to 120 seconds), while the second one is rather complex and may easily fail on DBpedia:
using System;
using System.Collections.Concurrent;
using VDS.RDF;
using VDS.RDF.Query;
public class TestTimeout
{
private static string FormatResults(SparqlResultSet results, object state)
{
var result = new System.Text.StringBuilder();
result.AppendLine(DateTime.Now.ToLongTimeString());
var asyncError = state as AsyncError;
if (asyncError != null) {
result.AppendLine(asyncError.State.ToString());
result.AppendLine(asyncError.Error.ToString());
} else {
result.AppendLine(state.ToString());
}
if (results == null) {
result.AppendLine("results == null");
} else {
result.AppendLine("results.Count == " + results.Count.ToString());
}
return result.ToString();
}
public static void Main(string[] args)
{
Console.WriteLine("Launched ...");
Console.WriteLine(DateTime.Now.ToLongTimeString());
var output = new BlockingCollection<string>();
var ep = new SparqlRemoteEndpoint(new Uri("http://dbpedia.org/sparql"));
ep.Timeout = 120;
Console.WriteLine("Server == " + ep.Uri.AbsoluteUri);
Console.WriteLine("HTTP Method == " + ep.HttpMode);
Console.WriteLine("Timeout == " + ep.Timeout.ToString());
string query = "SELECT DISTINCT ?a\n"
+ "WHERE {\n"
+ " ?a <http://www.w3.org/2000/01/rdf-schema#label> ?b.\n"
+ "}\n"
+ "LIMIT 10\n";
ep.QueryWithResultSet(query,
(results, state) => {
output.Add(FormatResults(results, state));
},
"Query 1");
query = "SELECT DISTINCT ?v5 ?v8\n"
+ "WHERE {\n"
+ " {\n"
+ " SELECT DISTINCT ?v5\n"
+ " WHERE {\n"
+ " ?v6 ?v5 ?v7.\n"
+ " FILTER(regex(str(?v5), \"[/#]c[^/#]*$\", \"i\")).\n"
+ " }\n"
+ " OFFSET 0\n"
+ " LIMIT 20\n"
+ " }.\n"
+ " OPTIONAL {\n"
+ " ?v5 <http://www.w3.org/2000/01/rdf-schema#label> ?v8.\n"
+ " FILTER(lang(?v8) = \"en\").\n"
+ " }.\n"
+ "}\n"
+ "ORDER BY str(?v5)\n";
ep.QueryWithResultSet(query,
(results, state) => {
output.Add(FormatResults(results, state));
},
"Query 2");
Console.WriteLine("Queries sent.");
Console.WriteLine(DateTime.Now.ToLongTimeString());
Console.WriteLine();
string result = output.Take();
Console.WriteLine(result);
result = output.Take();
Console.WriteLine(result);
Console.ReadLine();
}
}
When I run this, I reproducibly get an output like the following:
13:13:23
Server == http://dbpedia.org/sparql
HTTP Method == GET
Timeout == 120
Queries sent.
13:13:25
13:13:25
Query 1
results.Count == 10
13:23:25
Query 2
VDS.RDF.Query.RdfQueryException: A HTTP error occurred while making an asynchron
ous query, see inner exception for details ---> System.Net.WebException: Der Rem
oteserver hat einen Fehler zurückgegeben: (504) Gatewaytimeout.
bei System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
bei VDS.RDF.Query.SparqlRemoteEndpoint.<>c__DisplayClass13.<QueryWithResultSe
t>b__11(IAsyncResult innerResult)
--- Ende der internen Ausnahmestapelüberwachung ---
results == null
Obviously, the exact times will be different, but the crucial point is that the error message based on the second query is received approximately 10 minutes after the request was sent, nowhere near the 2 minutes set for the timeout.
Am I using dotNetRDF incorrectly here, or is it intentional that I have to run an additional timer to measure the timeout myself and react on my own unless any response has been received meanwhile?
No you are not using dotNetRDF incorrectly rather there appears to be a bug that the timeouts set on an endpoint don't get honoured when running queries asynchronously. This has been filed as CORE-393
By the way even with this bug fixed you won't necessarily get a hard timeout at the set timeout. Essentially the value you set for the Timeout property of the SparqlRemoteEndpoint instance that value is used to set the Timeout property of the .Net HttpWebRequest. The documentation for HttpWebRequest.Timeout states the following:
Gets or sets the time-out value in milliseconds for the GetResponse
and GetRequestStream methods.
So you could wait up to the time-out to make the connection to POST the query and then up to the time-out again to start receiving a response. Once you start receiving a response the timeout becomes irrelevant and is not respected by the code that processes the response.
Therefore if you want a hard timeout you are better off implementing it yourself, longer term this may be something we can add to dotNetRDF but this is more complex to implement that simply fixing the bug about the timeout not getting honoured for the HTTP request.

Result.to(NodeEntity.class): stack overflow error

while trying to retrieve my nodes back to my domain objects I'm getting this strange error:
Exception in thread "main" java.lang.StackOverflowError
at sun.nio.ch.NativeThreadSet.remove(NativeThreadSet.java:76)
at sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:678)
at org.neo4j.kernel.impl.nioneo.store.PersistenceRow.readFullWindow(PersistenceRow.java:158)
at org.neo4j.kernel.impl.nioneo.store.PersistenceRow$State$1.transition(PersistenceRow.java:115)
at org.neo4j.kernel.impl.nioneo.store.PersistenceRow.lock(PersistenceRow.java:59)
at org.neo4j.kernel.impl.nioneo.store.PersistenceWindowPool.acquire(PersistenceWindowPool.java:193)
at org.neo4j.kernel.impl.nioneo.store.CommonAbstractStore.acquireWindow(CommonAbstractStore.java:520)
at org.neo4j.kernel.impl.nioneo.store.NodeStore.getRecord(NodeStore.java:76)
at org.neo4j.kernel.impl.nioneo.xa.ReadTransaction.nodeLoadProperties(ReadTransaction.java:239)
at org.neo4j.kernel.impl.persistence.PersistenceManager.loadNodeProperties(PersistenceManager.java:113)
at org.neo4j.kernel.impl.core.NodeManager.loadProperties(NodeManager.java:682)
at org.neo4j.kernel.impl.core.NodeImpl.loadProperties(NodeImpl.java:132)
at org.neo4j.kernel.impl.core.Primitive.ensureFullProperties(Primitive.java:584)
at org.neo4j.kernel.impl.core.Primitive.ensureFullProperties(Primitive.java:567)
at org.neo4j.kernel.impl.core.Primitive.getProperty(Primitive.java:153)
at org.neo4j.kernel.impl.core.NodeImpl.getProperty(NodeImpl.java:51)
at org.neo4j.kernel.impl.core.NodeProxy.getProperty(NodeProxy.java:155)
at org.springframework.data.neo4j.support.typerepresentation.AbstractIndexingTypeRepresentationStrategy.readAliasFrom(AbstractIndexingTypeRepresentationStrategy.java:106)
at org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor.readAliasFrom(TRSTypeAliasAccessor.java:36)
at org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor.readAliasFrom(TRSTypeAliasAccessor.java:26)
at org.springframework.data.convert.DefaultTypeMapper.readType(DefaultTypeMapper.java:96)
at org.springframework.data.convert.DefaultTypeMapper.getDefaultedTypeToBeUsed(DefaultTypeMapper.java:144)
at org.springframework.data.convert.DefaultTypeMapper.readType(DefaultTypeMapper.java:121)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.read(Neo4jEntityConverterImpl.java:76)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.read(Neo4jEntityPersister.java:170)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.createEntityFromState(Neo4jEntityPersister.java:189)
at org.springframework.data.neo4j.support.Neo4jTemplate.createEntityFromState(Neo4jTemplate.java:180)
at org.springframework.data.neo4j.fieldaccess.RelationshipNodeFieldAccessorFactory$RelationshipNodeFieldAccessor.getValue(RelationshipNodeFieldAccessorFactory.java:102)
at org.springframework.data.neo4j.fieldaccess.DefaultEntityState.getValue(DefaultEntityState.java:97)
at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyEntityStatePropertyValue(SourceStateTransmitter.java:90)
at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.access$000(SourceStateTransmitter.java:40)
at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter$2.doWithAssociation(SourceStateTransmitter.java:61)
at org.springframework.data.mapping.model.BasicPersistentEntity.doWithAssociations(BasicPersistentEntity.java:207)
at org.springframework.data.neo4j.support.mapping.SourceStateTransmitter.copyPropertiesFrom(SourceStateTransmitter.java:57)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.loadEntity(Neo4jEntityConverterImpl.java:100)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityConverterImpl.read(Neo4jEntityConverterImpl.java:92)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister$CachedConverter.read(Neo4jEntityPersister.java:170)
at org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister.createEntityFromState(Neo4jEntityPersister.java:192)
at org.springframework.data.neo4j.support.Neo4jTemplate.createEntityFromState(Neo4jTemplate.java:180)
at org.springframework.data.neo4j.fieldaccess.GraphBackedEntityIterableWrapper.underlyingObjectToObject(GraphBackedEntityIterableWrapper.java:41)
at org.springframework.data.neo4j.fieldaccess.GraphBackedEntityIterableWrapper.underlyingObjectToObject(GraphBackedEntityIterableWrapper.java:27)
at org.neo4j.helpers.collection.IterableWrapper$MyIteratorWrapper.underlyingObjectToObject(IterableWrapper.java:57)
at org.neo4j.helpers.collection.IteratorWrapper.next(IteratorWrapper.java:47)
at org.neo4j.helpers.collection.IteratorUtil.addToCollection(IteratorUtil.java:324)
at org.neo4j.helpers.collection.IteratorUtil.addToCollection(IteratorUtil.java:341)
at org.springframework.data.neo4j.fieldaccess.RelatedToViaCollectionFieldAccessorFactory$RelatedToViaCollectionFieldAccessor.getValue(RelatedToViaCollectionFieldAccessorFactory.java:122)
at org.springframework.data.neo4j.fieldaccess.DefaultEntityState.getValue(DefaultEntityState.java:97)
For example, this is my cypher query which tries to get a user node entity:
public MyUser getUserByUserId(String userId){
Long t1 = System.currentTimeMillis();
if(existsUserByUserId(userId)){
HashedMap params = new HashedMap();
params.put("userId", userId);
String query = "START x=node:searchByUserId(userId = {userId})" +
" RETURN x";
Result<Map<String,Object>> result = neo4jTemplate.query(query, params);
MyUser user = result.to(MyUser.class).single();
Long t2 = System.currentTimeMillis();
logger.info("get user by user id exec time: " + (t2-t1) + " ms");
return user;
}
Long t2 = System.currentTimeMillis();
logger.info("get user by id exec time: " + (t2-t1) + " ms");
return null;
}
where searchByUserId is a node index and existsUserByUserId is a helper method which checks whether the the specified user exists or not. The problem is that when I try to call the result.to() method I get this error randomly. With randomly I mean that I'm not getting this error always. To be more concrete, I inserted all my node/relationships using the native Neo4j Java API and now I'm trying to retrieve these objects with Spring Data Neo4j (repository approach). This is how I'm inserting my node entities:
public Node createAndIndexMyUserNode(MyUser user){
Map<String,Object> properties = new HashMap<String, Object>();
properties.put("userId", user.getUserId());
properties.put("baseID" , user.getBaseID());
properties.put("__type__", MyUser.class.getName());
properties.put("canUpdate", false);
Node node = neo4jTemplate.getOrCreateNode("searchByUserId", "userId", user.getTwitterId(), properties);
return node;
}
This is probably the problem but I don't know how I could solve it. I suspect that bad database shutdowns or relationships creation (afterwards) could be also one reason, but I'm not sure though.
This is the reason why I'm inserting "manually" all nodes instead of using the repository save method. Any suggestions or ideas?
Thank you all in advance!

Validation failed for one or more entities

I have following code in my asp.net MVC3 application:
string msg = "Beginning report run for: ";
msg += " Obligor Registry ID: " + obligorID;
msg += " Requesting Organization Registry ID:" + requestingOrgID;
msg += " Requesting Agent Registry ID: " + requestingAgentID;
TransactionLog lg = new TransactionLog();
lg.TransactionTypeId = 2;
lg.Message = msg;
context.TransactionLogs.Add(lg);
long referenceNumber = context.SaveChanges();
return referenceNumber;
and I am getting following error:
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
While you are in debug mode within the catch {...} block open up the "QuickWatch" window (ctrl+alt+q) and paste in there:
((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors
This will allow you to drill down into the ValidationErrors tree. It's the easiest way I've found to get instant insight into these errors.
catch (DbEntityValidationException dbEx)
{
foreach (var validationErrors in dbEx.EntityValidationErrors)
{
foreach (var validationError in validationErrors.ValidationErrors)
{
Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
}
}
}
You need the namespace: System.Data.Entity.Validation
#GONeale helped me out in this regard. Moreover cause for this exception in my case is that I have certain not null db fields which I didnt included in the partial response update for certain transaction. context.Database.ExecuteSQLCommand would be my suggestion in this case.

Resources