How to handle errors while using Glib.Settings in Vala? - vala

I am using Glib.Settings in my Vala application. And I want to make sure that my program will work okay even when the schema or key is not available. So I've added a try/catch block, but if I'm using the key that doesn't exist, the program segfaults. As I understood, it doesn't even reach the catch statement.
Here is the function that uses settings:
GLib.Settings settings;
string token = "";
try
{
settings = new GLib.Settings (my_scheme);
token = settings.get_string("token1");
}
catch (Error e)
{
print("error");
token = "";
}
return token;
And the program output is:
(main:27194): GLib-GIO-ERROR **: Settings schema 'my_scheme' does not contain a key named 'token1'
Trace/breakpoint trap (core dumped)
(of course I'm using my real scheme string instead of my_scheme)
So can you suggest me where I'm wrong?

I know this is super late, but I was looking for the same solution so I thought I'd share one. As #apmasell said, the GLib.Settings methods don't throw exceptions—they just abort instead.
However, you can do a SettingsSchemaSource.lookup to make sure the key exists first. You can then also use has_key for specific keys. For example,
var settings_schema = SettingsSchemaSource.get_default ().lookup ("my_scheme", false);
if (settings_schema != null) {
if (settings_schema.has_key ("token1")) {
var settings = new GLib.Settings ("my_scheme");
token = settings.get_string("token1");
} else {
critical ("Key does not exist");
}
} else {
critical ("Schema does not exist");
}

The methods in GLib.Settings, including get_string do not throw exceptions, they call abort inside the library. This is not an ideal design, but there isn't anything you can do about it.
In this case, the correct thing to do is fix your schema, install into /usr/share/glib-2.0/schemas and run glib-compile-schemas on that directory (as root).
Vala only has checked exceptions, so, unlike C#, a method must declare that it will throw, or it is not possible to do so. You can always double check the Valadoc or the VAPI to see.

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.

How to know if data was persisted during database transaction after method returning?

I have a method written in a Grails service, which processes a lot of data.
I noticed that, sometimes, the method returns success but the data is not persisted to the database.
I debugged it, following all the data till the end of the method and everything is fine, however data is not persisted.
The following image demonstrates the what I just explained. You can see the end of the method, in which a Map object is filled with persistent object metadata. Even you can see the console which contains the printend Hibertate SQL
How can I detect whether a rollback mechanism is thrown after successful method returning?
This is my connection properties for Oracle 12c database. Others configurations are Grails defaults
dataSource.pooled=true
hibernate.jdbc.use_get_generated_keys=true
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=false
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
dataSource.driverClassName=oracle.jdbc.driver.OracleDriver
dataSource.dialect=org.hibernate.dialect.OracleDialect
dataSource.url=jdbc:oracle:thin:#172.16.1.20:1521:db
dataSource.username=<USER>
dataSource.password=<PASS>
hibernate.default_schema=<SCHEMA>
The service is anotated as #Transactional
#Transactional
class SincronizacionService {
}
Any Idea?
When using GORM's save method, also use failOnError:true. By default, save method silently fails. However, if you use failOnError:true, it will throw an exception if the data is not persisted.
If you do not want to stop the program when the data fails to save, you can use the try-catch block to log data that failed to save and let the algorithm continue to do it work.
Hope that helps.
I found the problem. In this method actaDenunciaService.generarActaDenuncia(denuncia), there is a peculiarity. In a part of the method is located the following snippet:
try {
DNomenclador nomenclador = nomencladorService.obtenerNomencladorDNomenclador(meta.valor.toLong())
if (!nomenclador) {
return toReturn(limpiarTexto(meta.valor))
} else {
return toReturn(nomenclador.valor)
}
} catch (Exception e) {
return toReturn(limpiarTexto(meta.valor))
}
A team member changed this line nomencladorService.obtenerNomencladorDNomenclador(meta.valor.toLong()). The change represented a huge improvement of memory saving. However, the team member did not take into account a business process, which does not take into account the method he used.
Yes, a runtime exception is being thrown.
And the treatment, depending on the objective of the method, is correct
For the future, this is how the method will be from now on:
try {
DNomenclador nomenclador = nomencladorService.obtenerNomencladorDNomencladorLibre(meta.valor.toLong())
if (!nomenclador) {
return toReturn(limpiarTexto(meta.valor))
} else {
return toReturn(nomenclador.valor)
}
} catch (Exception e) {
e.printStackTrace()
return toReturn(limpiarTexto(meta.valor))
}
nomencladorService.obtenerNomencladorDNomencladorLibre(meta.valor.toLong()) for the business process
e.printStackTrace() for tracing any other peculiarity
Thanks a lot to everybody who had collaborated on finding this error
I found the error!
An error thrown inside a method for generating a PDF document with data, appearsto be failing. The second line shows this
try {
denuncia.xmlFirmadoServ = dfileManagerService.guardarDFile(signatureResponse.resultado, "xmlfirmadoservidor.xml", usuario)
denuncia = actaDenunciaService.generarActaDenuncia(denuncia).denuncia
} catch (Throwable t) {
denunciaUtilService.incrementarNumeroDenuncia(true)
throw t
}
Now, the new question is: If the method is encapsulated inside a try/catchblock, why the catch block is not excecuting?
When I comment the 2nd line inside try/catch block, data is persisted on database
With no comments, generation PDF method is executed till the end, doing all what it must do

Xamarin Forms - iOS not processing correctly

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.

How do I test if a file is writable (CLI)

I am taking my first steps in Dart today, and the first thing I am not sure about how to proceed is how to test whether a file that is passed as an argument to a CLI tool I'm writing is writable.
So the idea is that I have a tool that accepts an input directory and an output filename. What it does is parsing some files in the input directory, compiles the data into a meaningful JSON config and saves it in the output file.
However, before doing anything, I want to run a sanity check to see that the given output file argument can actually be used as a writable file.
The way I decided to solve this is by opening the file for Append in a try-catch block:
try {
new File(output).writeAsStringSync('', mode: FileMode.APPEND, flush: true);
} on FileSystemException catch(e) {
// do something
}
However, I don't like this solution. Mainly that it creates a file if it doesn't already exist. Also, I don't see why I should write anything into a file when I just want to know whether it is writable or not.
What is the right way to do it in Dart?
You can use file.statSync().mode or file.statSync().modeString(). See FileStat.
This is actually quite hard to do reliably in any language. As Eiko points out, knowing the file permissions is only half the story, since the current user, group and process determines how those permissions apply.
Some edge cases that can occur are:
The file is writable when checked, but becomes unwritable by the time the writing needs to happen (e.g. another process changed the permissions).
The file is not writable when checked, but becomes writable by the time the writing needs to happen.
The file is write-only: it exists and is not readable, but can be written to.
The file doesn't exist and the user/process is not permitted to create a new file in that directory.
The file system has been mounted in read-only mode.
The parent directory/directories don't exist.
So anything you write may produce false positives or false negatives.
Your method of appending nothing is a good simple test. It can be made more complicated to address some of the issues, but there will always be cases where the answer is not what you might want.
For example, if you don't like creating the file before the actual writing, test if it exists first:
bool isWritable;
final f = File(filename);
if (f.existsSync()) {
try {
// try appending nothing
f.writeAsStringSync('', mode: FileMode.APPEND, flush: true);
isWritable = true;
} on FileSystemException {
isWritable = false;
}
} else {
isWritable = ???; // do you prefer false positive or false negative
// check if the parent directory exists?
}
// isWritable now, but might not be by the time writing happens
Or delete it after testing:
bool isWritable;
final f = File(filename);
final didExist = f.existsSync();
try {
// try appending nothing
f.writeAsStringSync('', mode: FileMode.APPEND, flush: true);
isWritable = true;
if (didExist) {
f.deleteSync();
}
} on FileSystemException {
isWritable = false;
}
// isWritable now, but might not be by the time writing happens
Dart introduces an extra complication, with asynchronous code.
If using the openWrite method. It opens a stream, so any problems writing to the file are not raised when the file is opened. They occur later when using the stream or closing it, which can be far away from the file opening code where you want it detected. Or worse, it occurs in a different zone and cannot be caught.
One useful trick there is to open it twice. The first is used to detect if the file is writable when it is closed. The second is to obtain the stream that will be used for writing.
try {
final f = File(filename);
f.parent.createSync(recursive: true); // create parent(s) if they don't exist
final tmp = f.openWrite(mode: FileMode.append);
await tmp.flush();
await tmp.close(); // errors from opening will be thrown at this point
// Open it again
sinkForWritingToTheFile = f.openWrite(mode: FileMode.append);
} on FileSystemException catch (e) {
// exception from `close` will be caught here
// exception from the second `openWrite` cannot be caught here
...
}

Is this a valid way to code up an MVC Service Layer?

In my MVC service layer I have code such as the following to validate:
protected bool ValidateAccount(Account account)
{
var accounts = _accountRepository.GetPk(account.PartitionKey);
if (accounts.Any(b => b.Title.Equals(account.Title) &&
!b.RowKey.Equals(account.RowKey)))
_validationDictionary.AddError("", "Duplicate title");
return _validationDictionary.IsValid;
}
However in the "action type" methods I absorb exceptions with code like this:
public bool Create(Account account)
{
if (!ValidateAccount(account))
return false;
try
{
_accountRepository.AddOrUpdate(account);
}
catch
{
return false;
}
return true;
}
My controller is coded like this:
public ActionResult Create(BaseViewModel vm)
{
_accountService = new AccountService(new ModelStateWrapper(this.ModelState), vm.Meta.DataSourceID);
if (ModelState.IsValid)
{
_accountService = new AccountService(new ModelStateWrapper(this.ModelState), vm.Meta.DataSourceID);
if (!_accountService.Create(vm.Account))
return View("CreateEdit", vm);
else
return RedirectToAction("Created");
}
return RedirectToAction("Home");
}
return View("CreateEdit", vm);
}
Is this a reasonable approach to take? My one concern is that I might be losing exception information in the service layer.
You should at the very least log your exception somewhere (event log, file system, using Elmah, etc).
The problem with your code is that you'll never know if something bad happened in production environment or you won't be able to discover what failed exactly (just that the code returned false).
Plus, you should never handle all exceptions like you do (unfiltered catch) but only the one you can revert back to a normal state. It's far better to let the application crash than to keep it online unstable.
Avoid handling errors by catching non-specific exceptions, such as System.Exception, System.SystemException, and so on, in application code. There are cases when handling errors in applications is acceptable, but such cases are rare.
See this MSDN article on best practices for handling exceptions and Design Guidelines for Exceptions
Since you are not doing anything with the exception in your Create method in the service layer, I would suggest removing the try/catch from it.
I would still return true or false to indicate whether the create operation was successful. I will however add a try/catch in the caller to make sure exceptions are handled. In your case that could be in your controller action (or the OnException in your base controller.)
Another approach is to leave the try/catch in your Create method but as #Stephane suggested do something with it (like log it) but you could also log it wherever you catch it.

Resources