A friend's query was failing. Fortunately, he was catching it in his fail callback (you DO have a fail callback for every server call, right?). Here's kind of what he had:
var getPersons = function(personsObservable) {
return EntityQuery.from('Person')
.using(manager).execute()
.then(querySucceeded).fail(queryFailed);
}
function queryFailed(error) {
var msg = 'Error retreiving data. ' + error.message;
logError(msg, error);
throw error;
}
The error.message simply showed the JSON data ... which looked a bit like this:
"[{"$id":"1","$type":"Person, ProjectName","Id":12,"FirstName":"Bob","LastName":"Smith","Email":"bs#contoso.com","Blog":"http://bs.contoso.com","Twitter": ..."
WAT?
He examined the error.XHR which provides the full AJAX XHR object used for this query. He could see that the HTTP Status Code was a 200 ... meaning that everything was cool from the server. The fact that he had real data pretty much said the same thing.
So why is Breeze failing? How does he diagnose the problem?
Breeze might be failing. But there's a good chance that the problem lies elsewhere. Usually if Breeze fails, there is a meaningful error message. This error message is not meaningful. But it does provide clues.
Check your success callback first
The fail callback can be invoked (1) if the operation fails or (2) if the success callback fails. If the operation fails, you've got a Breeze-related problem. If the success callback fails, you probably have an application code problem.
To determine which, put a breakpoint on the first line of the success callback (in his case, the first line of querySucceeded). If you hit the breakpoint, you know Breeze has done its bit and has handed off to you. Step through your callback to find the mistakes which are most likely yours and, therefore, easy to fix.
Check your custom EntityType constructors and initializers
In his case it did not get to the success callback. So something went wrong as Breeze tried to make cached entities out of the JSON data from the server. What could that be?
There are many potential causes. Could be a Breeze bug. Always best, though, to eliminate pilot error first. Did you write a custom constructor or initializer for this EntityType?
He did. He had an initializer that added a fullName calculated property to his Person. It looked sort of like this:
metadataStore.registerEntityTypeCtor('Person', null, personInitializer);
function personInitializer(person) {
person.fullName = ko.computed(function () {
return entity.firstName() + ' ' + person.lastName();
});
}
He didn't see a problem. But following diagnostic procedure, he put a breakpoint on the initializer.
Sure enough ... he had a typo ...
// "entity" does not exist. Null object error
return entity.firstName() + ' ' + person.lastName();
As soon as he changed entity to person, all was well.
I can't explain at the moment why the null object reference manifested as a Q promise fail error with the JSON Person data in the message. Strange stuff happens in JavaScript. But the clues were there:
server delivered the data
failed before getting to the success callback
data are about Person
have a Person initializer (or constructor)
Read the clues and you'll know where to look.
Hope this tip saves you from gray hair and a bald head.
Related
I am trying to access information about completion graph, but everytime it ends with error uk.ac.manchester.cs.jfact.helpers.UnreachableSituationException: Unreachable situation! when I call getObjectLabel(rootNode, false/true). I was trying it on every class expression from the ontology but always ended up with the error message.
Set<OWLClassExpression> types = classSet2classExpSet(hybridSolver.ontology.classesInSignature().collect(toSet()));
for (OWLClassExpression e : types) {
OWLKnowledgeExplorerReasoner.RootNode rootNode = loader.getReasoner().getRoot(e);
System.out.println(loader.getReasoner().getObjectLabel(rootNode, false)); //problem UnreachableSituation !!
Node<OWLObjectProperty> propertyNode = (Node<OWLObjectProperty>) loader.getReasoner().getObjectNeighbours(rootNode, false);
for (OWLObjectProperty p : propertyNode.getEntities()) {
Collection<OWLKnowledgeExplorerReasoner.RootNode> rootNodes = loader.getReasoner().getObjectNeighbours(rootNode, p);
...
}
}
Other method getObjectNeighbours(rootNote, false) works fine.
Can somebody help? Is there any way to access completion graph with OWLAPI? Why it might end with this error?
The labels found for the nodes in question are not named class expressions (e.g., they are AND nodes. These cannot be translated back to OWLClass and there's no current implementation for translating back class expressions.
Tweaking the code to remove the exceptions is doable but for your ontology example you'd always get back empty nodes, which isn't very informative.
I have removed the exception throwing in the latest version 5 branch, however I doubt this is sufficient for your needs.
When I tried to use ResilienceDecorator.executeCallable() to enable circuit breaker, I have to throw out ResilienceRuntimeException in my callable to make the circuit break work. Sample code as below. Without it, circuit breaker is always closed. is this the right way to do it?
response = ResilienceDecorator.executeCallable(() -> {
HttpResponse response1 = tryHttpClient.get().execute(request);
if (response1.getStatusLine().getStatusCode() == 404){
throw new ResilienceRuntimeException("404 error is raised when calling SB api");
}
return response1;
},
ResilienceConfiguration.of(SubscriptionBillingAdapter.class).isolationMode(ResilienceIsolationMode.TENANT_OPTIONAL).timeLimiterConfiguration(ResilienceConfiguration.TimeLimiterConfiguration.of().timeoutDuration(Duration.ofSeconds(6L))).circuitBreakerConfiguration(ResilienceConfiguration.CircuitBreakerConfiguration.of().waitDuration(Duration.ofSeconds(600000L)).failureRateThreshold(1).closedBufferSize(1).halfOpenBufferSize(1)),
e -> {LOG.warn("resiliience fallback call: " + e); return response1;});
I am asking since I don't see any document of it. Also when I check how destination configuration in SCP is retrieved, I saw the following code in com.sap.cloud.sdk.cloudplatform.connectivity.DestinationService . It doesn't throw out ResilienceRuntimeException, when using ResilienceDecorator.executeCallable(). so my question is do I need to throw out ResilienceRuntimeException or not to make circuit breaker work? if I don't need, anything wrong in my code?
return (String)ResilienceDecorator.executeCallable(() -> {
XsuaaCredentials xsuaaCredentials = (new ServiceCredentialsRetriever()).getClientCredentials("destination");
AccessToken accessToken;
if (propagateUser) {
accessToken = xsuaaService.retrieveAccessTokenViaUserTokenExchange(xsuaaCredentials.getXsuaaUri(), xsuaaCredentials.getCredentials(), useProviderTenant);
} else {
accessToken = xsuaaService.retrieveAccessTokenViaClientCredentialsGrant(xsuaaCredentials.getXsuaaUri(), xsuaaCredentials.getCredentials(), useProviderTenant);
}
return this.fetchDestinationsJson(servicePath, accessToken);
}, ResilienceConfiguration.of(DestinationService.class).isolationMode(ResilienceIsolationMode.TENANT_OPTIONAL).timeLimiterConfiguration(TimeLimiterConfiguration.of().timeoutDuration(Duration.ofSeconds(6L))).circuitBreakerConfiguration(CircuitBreakerConfiguration.of().waitDuration(Duration.ofSeconds(6L))));
Steven
I'm not the most experienced in this specific part, but looking at your code it seems fine to me. When a server returns 404 Not found it's not an indication of a service failure or error, but that resource is simply not found. If in your case 404 means that an error took place and the request has to be retried with a resilient approach, you have to throw that exception to inform Resilience4J that smth went wrong.
While we're working on improving our documentation, I recommend you take a look at the existing tutorial explaining resilience within the SAP Cloud SDK context. There we also throw ResilienceRuntimeException for clarity:
public List<BusinessPartner> execute() {
return ResilienceDecorator.executeSupplier(this::run, myResilienceConfig, e -> {
logger.warn("Fallback called because of exception.", e);
return Collections.emptyList();
});
}
private List<BusinessPartner> run() {
try {
return businessPartnerService
.getAllBusinessPartner()
.select(BusinessPartner.BUSINESS_PARTNER,
BusinessPartner.LAST_NAME,
BusinessPartner.FIRST_NAME,
BusinessPartner.IS_MALE,
BusinessPartner.IS_FEMALE,
BusinessPartner.CREATION_DATE,
BusinessPartner.TO_BUSINESS_PARTNER_ADDRESS
.select(BusinessPartnerAddress.CITY_NAME,
BusinessPartnerAddress.COUNTRY,
BusinessPartnerAddress.TO_EMAIL_ADDRESS
.select(AddressEmailAddress.EMAIL_ADDRESS)
)
)
.filter(BusinessPartner.BUSINESS_PARTNER_CATEGORY.eq(CATEGORY_PERSON))
.orderBy(BusinessPartner.LAST_NAME, Order.ASC)
.top(200)
.execute(destination);
} catch (ODataException e) {
throw new ResilienceRuntimeException(e);
}
}
Regarding the code snippet from the DestinationService, I believe that fetchDestinationsJson() method throws an implicit exception thus letting Resilience4J know that smth went wrong. While in your case HttpClient won't throw anything when receiving 404 as it's a correct response code as any other.
I also think that checking CircuitsBreaker examples from Resilience4J library might be helpful.
I hope it helps:)
No you do not have to throw a ResilienceRuntimeException. In fact the SDK only uses that to wrap checked and unchecked exceptions into an unchecked exception which wraps all kinds of failures that occur within a resilient call.
Please expand your question with more details, I'll then expand this answer:
Which version of the SDK are you using?
How (and how often) do you invoke the decorated callable? Please expand the code block.
Please specify the exact behaviour you observe. What exception is thrown when you invoke the decorated callable? If the circuit breaker opens this should be a CallNotPermittedException wrapped inside a ResilienceRuntimeException
Reduce the callable to simply throw an exception in order to simplify the code
Reduce the resilience configuration to only use a circuit breaker (leverage ResilienceConfiguration.empty()). If that works add stuff back in again until it doesn't.
For reference also please find the documentation of resilience4j which the SDK uses under the hood to perform resilient operations.
I understand there are a few similar questions (e.g. here), but they all seem to be in different context. This is what I see in my chrome console:
Unhandled rejection reasons (should be empty):
["TypeError: Cannot read property 'compound' of null…://localhost:1476/Scripts/breeze.debug.js:234:15)", joinBy: function, equals: function, indexByKey: function, getByKey: function, sortOn: function]
I could see this error in my debugger at failed(error):
return manager.executeQuery(query).then(succeeded).fail(failed);
function failed(error) {
logger.logError(error);
}
For a specific object, it happens most of time, but no always (maybe one out of 10 is okay). The query from server returns without exception. As I figured, it seems to be related to the query with a specific include of table. However, in fact, in this case, the included table doesn't have any related entry yet (if there is an entry, it doesn't seem to have any problem). Any idea?
Okay, I accidentally found out what has caused this error. It is metadatastore post-construction initializer like
manager.metadataStore.registerEntityTypeCtor("Result", Result, initialize);
// constructor
function Result() {
}
// post-construction initializer
function initialize(result) {
result.cmpName = result.cs.compound.name;
}
where result.cs could be null sometimes.
Too bad the error message didn't provide any clue.
i'm displaying a server calculated value to the enduser by using propertyChanged event.
i was using breeze 1.4.8 and i'm using the productivity stack (ms sql, web api, ef)
It was working fine.
Recently i've updated to 1.4.12 and i recognized that this event doesn't get fired anymore.
The property "A_ProvisionTotal" gets calculated serverside only.
<snip>
var token = vm.transaction.entityAspect.propertyChanged.subscribe(propertyChanged);
function propertyChanged(propertyChangedArgs) {
var propertyName = propertyChangedArgs.propertyName;
if (vm.transaction.tblEmployees.CalculationMethod == "A" && propertyName == "A_ProvisionTotal")
logSuccess('Provision neuberechnet' + '<br/>' + 'Aktuell: ' + $filter('number')(vm.transaction.Provision, 2), true);
</snip>
Let me know if this is a known regression and if you need more snippets.
A couple of thoughts for how you could accomplish your desired functionality.
The entity could remember the last calculated value in a private field. Then whenever the recalculation gets triggered, you can compare the new value to the last calculated value and if there is no change, ignore the new calculated value.
Alternatively, you could define the properties involved in your calculation as ES5 properties in the entity ctor function and then trigger the calculation in the setter of the relevant properties, when they get set with a new value. More information here: http://www.breezejs.com/documentation/extending-entities#es5-property. ES5 properties are convenient if you want to build behavior such as your calculation into setters.
Update 3
This is not a bug - see the response to this post that describes this as a documented and deliberate behavior.
Update 2 June 2014
I overlooked a key fact in your question ... one that only became clear to me after I looked at the code you included in your comments. Let me extract the key pieces for other readers:
Your test issues a query, then saves an unrelated change to the server (where the property-of-interest is updated server-side), then checks if that telltale property-of-interest raises propertyChanged when the save result is merged back into cache.
var query = EntityQuery.from("Orders").where('id', 'eq', 10248);
query.using(em).execute().then(querySucceeded).then(checkPropertyChanged).fin(start);
// querySucceed receives order 10248, updates an unrelated property (so you can save),
// wires up a propertyChanged listener and saves, returning the saveChanges promise
function checkPropertyChanged(saveResults) {
var saved = saveResults.entities[0];
// this passes because the server-side change to `Freight` was returned
ok(saved && saved.Freight() === 1200.00,
"freight got changed serverside");
// this fails because Breeze did not notify you that the `Freight` had changed
ok(notifications[0].propertyName === "Freight",
"notified serverside change of Freight Property");
}
Summarizing, you expected that a property change on the server would trigger a propertyChanged notification on the client when the entity data are re-retrieved from the server as a by-product of saveChanges.
Do I have that right?
Our documentation was not clear on whether the merge of query, save, and import entity results would raise propertyChanged.
I discussed internally and confirmed that these operations SHOULD raise propertyChanged. I also wrote another (somewhat simpler) test that reveals the bug you discovered: that merged save results may not raise propertyChanged.
We'll look into it and tell you when we've fixed it. Thanks for discovering it.
Original
We have regression tests that show that the Breeze EntityAspect.propertyChanged event is raised in v.1.4.12. For example, you can see it at work in the DocCode sample, "basicTodoTests.js"; scroll to: "Breeze propertyChanged raised when any property changes".
Can you confirm that it really is a Breeze failure? Perhaps the property you are changing is not actually an entity property? Sometimes you think you are changing an entity (e.g, your Transaction entity) but the thing whose property you changed isn't actually an entity. Then the problem is that the data you thought would be mapped to a Transaction was not ... and you can start looking for that quite different problem.
In any case, I suggest that you write a small test to confirm your suspicion ... most importantly for yourself ... and then for us. That will help us discover what is different about your scenario from our scenarios. We'll fix it if you can find it. Thanks.
Actually, I'm not sure that this is a bug. Property change events DO get fired during a save merge but the property name parameter is documented as being 'null' when fired as a result of a save.
http://www.breezejs.com/sites/all/apidocs/classes/EntityAspect.html#event_propertyChanged
From the API Docs for the 'propertyName' parameter returned by EntityAspect.propertyChanged:
The name of the property that changed. This value will be 'null' for operations that replace the entire entity. This includes queries, imports and saves that require a merge. The remaining parameters will not exist in this case either.
What may have happened between 1.4.8 and 1.4.13 is that we actually implemented our design spec more carefully and probably introduced your breaking behavior. ( which we should have documented as such but likely missed).
Update by Ward
I updated the DocCode test which first confirmed the behavior described in your question and then confirmed the documented behavior.
We do regret that we apparently neglected to implement the documented behavior earlier and that we didn't mention the breaking change in our release notes (since updated).
Here's that test:
asyncTest("propertyChanged raised when merged save result changes a property", 3, function () {
var em = newTodosEm();
var todo = em.createEntity('TodoItem', {Description: "Saved description" });
em.saveChanges().then(saveSucceeded).catch(handleFail).finally(start);
ok(todo.entityAspect.isBeingSaved, "new todo is in the act of being saved");
// This change should be overwritten with the server value when the save result is returned
// even though the entity is in an Added state and the MergeStrategy is PreserveChanges
// because save expects to merge server values into an entity it is saving
todo.Description("Changed on client before save returns");
var descriptionChanged = false;
todo.entityAspect.propertyChanged.subscribe(function (changeArgs) {
// Watch carefully! The subscription is called twice during merge
// 1) propertyName === "Id" (assigned with permanent ID)
// 2) propertyName === null (WAT?)
// and not called with propertyName === "Description" as you might have thought.
// Actually 'null' means "merged a lot of properties"
// Documented: http://www.breezejs.com/sites/all/apidocs/classes/EntityAspect.html#event_propertyChanged
// The reason for this: don't want to fire a ton of events on whole entity load
// especially when merging many entities at the same time.
if (changeArgs.propertyName === null || changeArgs.propertyName === 'Description') {
descriptionChanged = true;
}
});
function saveSucceeded(saveResult) {
var saved = saveResult.entities[0];
// passes
equal(saved && saved.Description(), "Saved description",
"the merge after save should have restored the saved description");
// fails
ok(descriptionChanged,
"should have raised propertyChanged after merge/update of 'Description' property");
}
});
i'm pretty new to erlang and i'm trying to get a basic try / catch statement to work. I"m using webmachine to process some requests and all i really want to do is parse some JSON data and return it. In the event that the JSON data is invalid, I just want to return an error msg. Here is the code I have so far.
(the JSON data is invalid)
to_text(ReqData, Context) ->
Body = "{\"firstName\": \"John\"\"lastName\": \"Smith\"}",
try decode(Body) of
_ -> {"Success! Json decoded!",ReqData,Context}
catch
_ -> {"Error! Json is invalid",ReqData,Context}
end.
decode(Body) ->
{struct, MJ} = mochijson:decode(Body).
The code compiles, but when i run it, and send a request for the text, i get the following error back.
error,{error,{case_clause,{{const,"lastName"},
": \"Smith\"}",
{decoder,utf8,null,1,31,comma}}},
[{mochijson,decode_object,3},
{mochijson,json_decode,2},
{webmachine_demo_resource,test,1},
{webmachine_demo_resource,to_text,2},
{webmachine_demo_resource,to_html,2},
{webmachine_resource,resource_call,3},
{webmachine_resource,do,3},
{webmachine_decision_core,resource_call,1}]}}
What exactly am i doing wrong? documentation says the "catch" statement handles all errors, or do i have to do something to catch a specific error that is thrown by mochijson:decode.
Please any leads or advice would be helpful. Thanks.
The catch-clause _ -> ... only catches exceptions of the 'throw' class. To catch other kinds of exceptions, you need to write a pattern on the form Class:Term -> ... (i.e., the default Class is throw). In your case:
catch
_:_ -> {"Error! Json is invalid", ReqData, Context}
end
When you do this, you should always ask yourself why you're catching every possible exception. If it's because you're calling third-party code that you don't know how it might behave, it's usually OK. If you're calling your own code, remember that you're basically throwing away all information about the failure, possibly making debugging a lot more difficult. If you can narrow it down to catching only particular expected cases and let any other exceptions fall through (so you see where the real failure occurred), then do so.