Xamarin Forms - iOS not processing correctly - ios

I am using the CrossDownManager plugin for Xamarin Forms
Here
When I run the method on Android it processes as expected. On iOS Debug.Writeline("Success!") isn't being hit like it was on Android.
Here is the code:
void ViewImage(string imageLink)
{
var downloadManager = CrossDownloadManager.Current;
downloadManager.PathNameForDownloadedFile = new System.Func<IDownloadFile, string>(file =>
{
string path = DependencyService.Get<IImageSaver>().Save("YHTS" + DateTime.Today.Ticks.ToString() + ".jpg");
Debug.WriteLine("Success!");
return path;
});
try
{
var file = downloadManager.CreateDownloadFile(imageLink);
Debug.WriteLine("file created");
downloadManager.Start(file);
Debug.WriteLine("downloadstarted");
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
For the life of me I can't figure out why the that code block isn't processed. Any ideas?

This is an interesting issue as technically your code should work as expected. I've done a little digging and found a reply to a similar question here.
your options are many... including:
DEBUG preprocessor as you show in your question.
Use System.Diagnostic.Debug.WriteLine: Any calls to Debug.* will be
removed by the compiler due to the [Conditional("DEBUG")] attribute
being applied.
Create your own "Logger" class as a wrapper to the stdout writers and
[Conditional("DEBUG")] it
Use Fody and re-weave the assemblies to remove/NOP/redirect the
WriteLine I do this to redirect the calls to in internal log and upon
crash or user stat requests, forward this log to our crash reporting
servers. etc, .....
So there are a few alternatives to consider, one of the common suggestions I've seen is to use the fully qualified reference for WriteLine(); as such:
System.Console.WriteLine("woop woop");
I would suggest giving the above a try first.

Related

Q: Using Circuit Breaker in SAP Cloud SDK resilience

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.

RxSwift .asDriverOnErrorJustComplete() not being part of core/utility library

Trying to figure out how to make an app with RxSwift and exploring multiple open source projects (namely CleanArchitectureRxSwift and SwiftHub) I often find usage of
extension ObservableType {
func asDriverOnErrorJustComplete() -> Driver<E> {
return asDriver { error in
return Driver.empty()
}
}
}
Given that this method is useful in many situation and literally copied in mentioned projects I wonder why is it not a part of some utility library (like for example RxSwiftExt) or even RxSwift itself.
I find it really suspicious that given how many Rx pods there are in SwiftHub Podfile none of them actually contain this function.
My question is that are there any real reasons behind that? Does asDriverOnErrorJustComplete somehow violates come Rx contracts or considered bad practice etc?
Am I biased in sense that those two projects are most likely copied architecture from each other and are not representative? If so, are there any good open source projects that demonstrate RxSwift+MVVM and maybe avoid asDriverOnErrorJustComplete or approach problems solved by asDriverOnErrorJustComplete differently?
I wouldn't call the method bad practice per se but it allows for an error that will get silently ignored which I don't particularly like. Using such a construct is rather pernicious in that your chain will silently fail without any notice at all. It could be a problem if your QA department (you with a different hat on?) doesn't notice the fact that the label isn't updating anymore.
I'm also not a big fan of the particular GitHub repos you call out because they add a lot of IMHO unnecessary boilerplate. I prefer code that is more direct.
In my sample app RxEarthquake, I use the following:
public func asDriverLogError(_ file: StaticString = #file, _ line: UInt = #line) -> SharedSequence<DriverSharingStrategy, E> {
return asDriver(onErrorRecover: { print("Error:", $0, " in file:", file, " atLine:", line); return .empty() })
}
So at least a record of the error is made in debug.
I also think the following is an excellent alternative:
public func asDriverOrAbort(_ file: StaticString = #file, _ line: UInt = #line) -> SharedSequence<DriverSharingStrategy, E> {
return asDriver(onErrorRecover: { fatalError("Error: \($0) in file: \(file) atLine: \(line)") })
}
By using such a method, you are making it clear to the reader that you are absolutely sure that the chain won't produce an error.
I think asDriverOnErrorJustComplete is not included in the standard library, because with any type of observable except void, the application will be crashed when receiving an error.
When I started writing SwiftHub, I couldn’t understand why the application crashes when I got an error from the server :)

Vaadin "A connector with id xy is already registered"

Somewhere in my Vaadin application, I'm getting this exception as soon as I connect using a second browser
Caused by: java.lang.RuntimeException: A connector with id 22 is already registered!
at com.vaadin.ui.ConnectorTracker.registerConnector(ConnectorTracker.java:133)
It happens always in the same place but I don't know why exactly as the reason for this must be somewhere else.
I think I might be stealing UI components from the other session - which is not my intention.
Currently, I don't see any static instances of UI components I might be using in multiple sessions.
How can I debug this? It's become quite a large project.
Any hints to look for?
Yes, this usually happens because you are attaching a component already attached in other session.
Try logging the failed connector with a temporal ConnectorTracker, So the next time that it happens, you can catch it.
For example:
public class SomeUI extends UI {
private ConnectorTracker tracker;
#Override
public ConnectorTracker getConnectorTracker() {
if (this.tracker == null) {
this.tracker = new ConnectorTracker(this) {
#Override
public void registerConnector(ClientConnector connector) {
try {
super.registerConnector(connector);
} catch (RuntimeException e) {
getLogger().log(Level.SEVERE, "Failed connector: {0}", connector.getClass().getSimpleName());
throw e;
}
}
};
}
return tracker;
}
}
I think I might be stealing UI components from the other session - which is not my intention. Currently, I don't see any static instances of UI components I might be using in multiple sessions.
That was it. I was actually stealing UI components without prior knowledge.
It was very well hidden in a part which seems to be same for all instances. Which is true: the algorithm is the same.
Doesn't mean I should've reused the same UI components as well...
Thanks to those who took a closer look.
Here is how I fixed it -
1) look for components you have shared across sessions. For example if you have declared a component as static it will be created once and will be shared.
2) if you are not able to find it and want a work around until you figure out the real problem, put your all addComponent calls in try and in catch add following code -
getUI().getConnectorTracker().markAllConnectorsDirty();
getUI().getConnectorTracker().markAllClientSidesUnititialized();
getPage().reload():
This will clear old connectors and will reload the page properly only when it fails. For me it was failing when I was logged out and logged in back.
Once you find the real problem you can fix it till then inform your customers about the reload.
**** note - only solution is to remove shared components this is just a work around.
By running your application in debug mode (add ?debug at the end of URL in browser) you will be able to browse to the component, e.g:
-UIConnector(0)
--VerticalLayoutConnector(1)
---...
---LabelConnector(22)
where 22 is id from your stack trace. Find this component in your code and make sure that it is not static (yes, I saw such examples).

May a scenario not have a When in BDD?

I'm currently learning/testing BDD using SpecFlow, and it works great!
Before I choose to ask my question, I have read this one, and I felt like I had to ask my question despite the fact that the same problem is addressed, because of the Exception scenario which is not mentioned.
I'm actually testing this scenario:
Scenario: I should get an error whenever I try to remove an item from an empty stack
Given I have an empty stack
When I pop from it
Then I should get an error
public class StackBehaviour {
public void GivenIHaveAnEmptyStack() { stack = new CustomStack<string>(); }
// This will throw whenever called!
// So the Then method will never be run!
// I feel like I should just put a comment which says why it's empty,
// allowing a fellow programmer to understand the exact intention.
public void WhenIPopFromIt() { stack.Pop(); }
// It is here that it verifies whether the CustomStack meets the expected behaviour.
public void ThenIShouldGetAnError() {
Assert.Throws<IndexOutOfRangeException>(delegate {
stack.Pop();
});
}
private CustomStack<string> stack;
}
public class CustomStack<T> {
public T Pop() {
if (stack.Count == 0)
throw new IndexOutOfRangeException("Cannot pop from an empty stack!");
T item = stack[stack.Count-1];
stack.RemoveAt(stack.Count-1);
return item;
}
private ArrayList stack = new ArrayList();
}
I think that leaving a comment in the When method is correct, so that the business requirement doesn't lack any information, and on the code behind, I put it clear what my intention is exactly by commenting.
What do you think? Any other ideas why I shouldn't make it?
There is another trick that you can use where the bindings help make the feature's meaning a little clearer. In this case, let's start at the end.
Then I should get an error
Your problem is a basically here, you know want an error, but you don't know how to get it. In fact you've already missed it, the error has already occurred in the When step, and in your code example, you moved the action into the then step just so you could get the error.
But what if keep the when performing the action amd re-express our then to reflect what really happens
Then I should have had an error
Seems a trivial change but now our feature reflects that the error should have been associated with the When step and we are simply evaluating it later, and that is something we can code. We just need something to remember the error in the when and deliver it to the then.
private Exception errorFromWhen = null;
public void WhenIPopFromIt()
{
try
{
stack.Pop();
}
catch(Exception ex)
{
errorFromWhen = ex;
}
}
public void ThenIShouldGetAnError()
{
errorFromWhen.ShouldNotBeNull();
errorFromWhen.ShouldBe<IndexOutOfRangeException>();
}
SpecFlow has absolutely no problems with this, in fact due to its mini Dependency injection system, you can even pass this state between binding classes if necessary.
May a scenario not have a When in BDD?
In Specflow, neither given, when or then are mandatory.
However in your example, I don't believe this is a good use of Specflow and BDD. In this answer here Marcus states:
"BDD is about ensuring that we're building the right thing, TDD is about ensuring that we're building it right."
In your example the scope of what is being tested i.e. the CustomStack, should be tested via TDD. It is the end solution that makes use of the CustomStack should be tested via BDD (and hence SpecFlow) e.g. if this CustomStack was being exercised via a certain action on a website.
This answer is also pertinent to your question.

QTP 11 Extensibility developing (.NET sdk) - calling Record() on the recorder object fails

As far as I looked, there's no answered question about QTP's Ext. sdk on stackoverflow (and almost anywhere else on the net; there isn't even a appropriated tag for it...), so I'm aware it's unlikely I get my problem solved by asking , but whatever, it worth trying.
Anyway, before I lose the attention of anyone who never heard or used the Ext. sdk, maybe I will have more luck asking you to help me figure out how to locate the error log file QTP produces at run-time. I know such a file exists in the new UFT 11.5 version, but I couldn't locate it in QTP 10 or 11 (For the record, I don't talk about QTP's Log Tracking feature, but about the "meta" error log of errors/exceptions produced by QTP itself).
Now for the question:
I'm developing an extension for QTP to support native record and run tests on my application.
I'm currently able to import an object repository, and write test steps using The COM object testing agent I developed.
Problem started when I was trying to implement the IRecordable interface; I'm getting the IRecorder object from qtp, and even able to use it as ISuppressor object to exclude redundant steps from being recorded, but all my attempts to record a step (that is, to add new recorded objects to the repository, and add steps to the test) simply failed.
This is the code that I'm using:
public class MyTestingAgent :
AutInterface.ITestable,
AutInterface.IRecordable
{
QTPInterface.IRecorder recorder;
...
public void AutInterface.IRecordable.BeginRecording(object recorder)
{
IRecordSuppressor recordSuppressor = recorder as IRecordSuppressor;
recordSuppressor.Suppress(MyTestingAgentId,
"<Suppress><Item type=\"HWND\" value=\"[#HWND]\" /></Suppress>".Replace("[#HWND]", getMyAppHWND().ToString()));
this.recorder = recorder as QTPInterface.IRecorder;
...
}
public void recordNewObjStep(string parentName, string objName, string method, Object[] arguments)
{
object[] objectHyrarchy = new object[] { findObjectId(objName), findObjectId(parentName) };
string externalParent = null;
string appDescriptionXml = getDescriptionXml(parentName, objName);
try
{
recorder.Record(MyTestingAgentId, objectHyrarchy , appDescriptionXml, externalParent, method, arguments);
Trace.TraceInformation("Record successfully done.");
}
catch (Exception e)
{
Trace.TraceError("TEAAgent.recordSTElement: " + e.ToString());
}
}
...
}
I'm pretty sure all the arguments I send with the call to Record() are accurate. getDescriptionXml() and findObjectId() are used in different cases in the code, and works fine, the method name and argument are correct.
The annoying thing is that the call to Record doesn't even throw exception, and I get "Record successfully done." in the trace log. Needless to say no new object is created in the repository, and no step is added to the test.
As I can't debug QTP, I'm pretty much in the dark with what I'm doing wrong. That's why I'm asking for help with finding QTP's log file, or any other approach that might shed some light on the subject.
For QTP 11 you can turn on the logs by going to QTP's bin directory and running ClientLogs.exe.
Specifically for TEA extensibility do the following.
select the QTP node from the list on the left
find the LogCatPackTEA from the Available Categories list
Click the > button to move it to Selected Categories
Change TEAs level to Debug2 by selecting the category and changing the level
Click OK and run QTP
The logs will show up as QTP.log in the diretory specified in Path:
I'm curious on what the problem you're facing is, please update if you find the cause.

Resources