We have many try-catch blocks in our code handling the exceptions of the api calls. Since most of the catch blocks are identical we want to refactor them and only them (because the try blocks should stay in the place they are). How is this possible in Flutter?
Example code:
try {
_userData = apiService.call("user_data");
} on ResourceNotFoundException {
handleResourceNotFoundException();
} on NetworkException {
handleNetworkException();
}
The best solution I found is using a general catch, fit everything into a handleException function, and in there rethrow the exception again.
try {
_userData = apiService.call("user_data");
} on catch (e) {
handleException(e);
}
void handleException(e) {
try {
throw e;
} on ResourceNotFoundException {
handleResourceNotFoundException();
} on NetworkException {
handleNetworkException();
}
}
This way it is possible to reuse the exception handling logic and also extend it.
You should add some abstraction to your API call, meaning you should add a function that takes in the API call you are trying to call as a parameter and surround it with a try-catch block and handle all your exceptions there.
This way you have separated your API calls logic from handling exceptions.
Related
coming from the JS world I'm having a bit of problem wrapping my head around promise kit flavor of promises, I need a bit of help with the following.
Assume I have a function that returns a promise, say an api call, on some super class I await for that promise, then do some other action (potentially another network call), on that parent call I also have a catch block in order to set some error flags for example, so in the end I have something close to this:
func apiCall() -> Promise<Void> {
return Promise { seal in
// some network code at some point:
seal.fulfill(())
}
}
// in another class/object
func doApiCall() -> ? { // catch forces to return PMKFinalizer
return apiCall()
.done {
// do something funky here
}
.catch {
print("Could not do first request"
}
}
now I'm trying to write some unit tests for this functionality, so the response is mocked and I know it will not fail, I just need to await so I can verify the internal state of my class:
// on my test file
doApiCall().done {
// test my code, but I get an error because I cannot pipe a promise that already has a `.catch`
}
How would one go about solving this problem? I could use finally to chain the PMKFinalizer but that feels wrong
Another tangential question would be, is it possible to re catch the error on a higher level, let's say a UI component so it can hold some temporary error state? as far as I see I did not see a way to achieve this.
Many thanks 🙏
I have a "big" completable that does some error checking, and then does a two processing steps.
It looks like this:
// someProcessorClass
public Completable checkAndProcessFile(InputStream file, ...) {
return checkHeaders(file, ...).andThen(processFile(file, ...));
}
private Completable checkHeaders(InputStream file, ...) {
// checks the first line for the right headers
// ...
if(firstLineIsGood) {
return Completable.complete();
}
return Completable.error(new Error('bad headers');
}
private Completable processFile(file, ...) {
return writeFile(file).andThen(writeMetadata(...));
}
What I want to do is for the Completable to break on the first Completable checkHeaders(), but instead, what seems to happen is writeFile() occurs regardless of whether there is an error or not. The writeMetadata() does not get called.
So it seems like processFile() is acting eager to order to evaluate the the Completable. I tried wrapping the second half in a Completable.fromCallable(), but then that requires an inner subscribe like so, which seems... not the right way to do it.
private Completable processFile(file, ...) {
return Completable.fromCallable(()-> {
return writeFile(file).andThen(writeMetadata(...)).subscribe();
}
}
So my question is, is there a way to chain Completables in a lazy way? Kind of like flatMap?
You don't provide your writeFile and writeMetadata. But I think they may like:
public Completable writeFile(InputStream file) {
try {
// write file here
} catch (IOException e) {
return Completable.error(e);
}
return Completable.complete();
}
That is totally wrong usage. You should do your work in Completable, not just return a Completable. The right usage is
public Completable writeFile(InputStream file) {
return Completable.fromAction(() -> {
// write file here
});
}
So from what I understand (newbie here),
What I thought I was doing is
checkHeaders.andThen(writeFile).andThen(writeMetadata)
But by wrapping writeFile.andThen(writeMetadata) within another Completable (processFile), rxJava treated it more like
checkHeaders.andThen((writeFile.andThen(writeMetadata))
where it starts evaluating the inner parenthesis first.
So by just chaining .andThen(), you get the expected result of the Completable breaking onError.
There's a lisp function in ResearchCyc called random-assertion. I want to call that from some Java code. I'm using the Cyc Core API Suite v1.0.0-rc5 (from http://dev.cyc.com), but I don't see any way to call underlying Lisp code.
In the old OpenCyc API there was an object called CycAccess that you could use for this, but I can't figure out how to get one. If I could find it, I'd call this
access.converseObject("(random-assertion)");
At least in ResearchCyc, this would retrieve a pseudo-random assertion from the Cyc knowledge base. Not sure if it would work in OpenCyc, but it might also work there.
Can someone explain how to call lisp-code like this through Cyc's java API?
(Disclaimer: I am one of the developers of the Cyc APIs...)
The reference implementation of the Core API Suite is the Core Client, which is based on the Base Client... which, in turn, is derived from the old OpenCyc API. So, it's absolutely possible to call arbitrary lisp (SubL) code on ResearchCyc, in several different ways...
First of all, there already is a method which wraps random-assertion:
try {
CycAccess access = CycAccessManager.getCurrentAccess();
CycAssertion cycAssertion = access.getLookupTool().getRandomAssertion();
} catch (SessionException ex) {
// Do something with the exception...
} catch (CycConnectionException connEx) {
// Do something else...
}
Speaking to the general case, though, you'll find that the syntax is fairly similar to the OpenCyc API:
try {
CycAccess access = CycAccessManager.getCurrentAccess();
Object cycAssertion = access.converse().converseObject("(random-assertion)");
} catch (SessionException ex) {
// Do something with the exception...
} catch (CycConnectionException connEx) {
// Do something else...
}
Or, if it's safe to assume that the result will be a CycObject:
...
CycAccess access = CycAccessManager.getCurrentAccess();
CycObject cycAssertion = access.converse().converseCycObject("(random-assertion)");
...
However, the Base Client adds a new way of encapsulating SubL functions, via the com.cyc.baseclient.subl.SublFunction interface. The SublFunction interface itself is pretty minimal, but there are a number of classes under com.cyc.baseclient.subl.subtypes which provide implementations for you to extend. For example, if you're calling a no-arg function and expect back a CycObject, you could extend SublCycObjectNoArgFunction like so:
public static final SublCycObjectNoArgFunction RANDOM_ASSERTION_FUNCTION =
new SublCycObjectNoArgFunction("random-assertion");
...
try {
CycAccess access = CycAccessManager.getCurrentAccess();
CycObject cycAssertion = RANDOM_ASSERTION_FUNCTION.eval(access);
} catch (SessionException ex) {
// Do something with the exception...
} catch (CycConnectionException connEx) {
// Do something else...
}
(For other examples of this, see com.cyc.baseclient.subl.functions.* in the Base Client.)
This approach makes it fairly simple to define SubL functions as static fields without writing (or re-writing) much code. We expect the Core Client to gradually migrate towards this approach.
Lastly, you can use the implementation classes in the KB Client to convert your results to KBObjects. For example:
try {
CycAccess access = CycAccessManager.getCurrentAccess();
CycObject cycAssertion = RANDOM_ASSERTION_FUNCTION.eval(access);
// To convert to a com.cyc.kb.Assertion:
Assertion assertion = AssertionImpl.get(cycAssertion);
// Or, to convert to a more general KBObject:
KbObject kbObj = KbObjectImpl.get(cycAssertion);
} catch (SessionException ex) {
// Do something with the exception...
} catch (CycConnectionException connEx) {
// Do something else...
} catch (KbTypeException ex) {
// Potentially thrown by AssertionImpl#get() & KbObjectImpl#get()
} catch (CreateException ex) {
// Also potentially thrown by AssertionImpl#get() & KbObjectImpl#get()
}
While using Akka's data-flow DSL, I have twice encountered a need to throw an exception inside future, conditionally. This is how I am doing it:
flow {
// ...
if (someCond)
shiftUnit(throw new SomeException)
else
Future().apply()
// ...
}
Is this the correct way to do it? Or is there a better approach?
The approach seems correct (although my knowledge is a bit rusty), you can even leave out the other branch, the following works for me (Scala 2.10.1):
flow { if (x == 2) shiftUnit(throw new Exception) }
which results in a Future[Unit].
Is there a hook in NUnit to execute code only when assertion fails without catching the exception itself. Basically, it should accept action delegate to be executed when assertion fails and then re-throw exception. Why do I need this?
I need to compare two objects and dump the result on the screen, for easier debugging, when assertion fails.
Something like this works but is a bad hack, The problem is that it eagerly evaluates ProcessCompareError so I have unnecessary overhead, plus it does it no matter if there is an error or not. So, is there overload that will accept the delegate that would be executed when assertion fails?
Assert.That(benefitLimitComparer.Compare(copyBenefitLimit, origBenefitLimit), Is.EqualTo(0),limitError, ProcessCompareError(origBenefitLimit, copyBenefitLimit));
}
}
}
private string ProcessCompareError(BenefitLimit origBenefitLimit, BenefitLimit copyBenefitLimit)
{
Console.WriteLine("Original: ");
ObjectDumper.Write(origBenefitLimit);
Console.WriteLine("Copy");
ObjectDumper.Write(copyBenefitLimit);
return "";
}
I'm not sure how it might be done through a delegate. One alternative is to store the result of the Compare. If the result is false, write out the contents of the objects and then call Assert.Fail()
There is a possibilty to wrap an assert as an Action in a try-catch. In the catch you can handle the additional compare:
public static void ExecuteAssert(Action assert)
{
if (assert == null) return;
try
{
assert();
}
catch (Exception ex)
{
// perform the compare
}
}
As remark: I use a similar method to continue test execution and avoid the entire test to stop, if some non-fatal checks fail. Actually I iterate through a number of actions:
private static void VerifyAll(params Action[] asserts)