How to access SAP OData messages in Kapsel offline app? - error-handling

We are developing an SAP Fiori App to be used on the Launchpad and as an offline-enabled hybrid app as well using the SAP SDK and its Kapsel Plug Ins. One issue we are facing at the moment is the ODATA message handling.
On the Gateway, we are using the Message Manager to add additional information to the response
" ABAP snippet, random Gateway entity method
[...]
DATA(lo_message_container) = me->mo_context->get_message_container( ).
lo_message_container->add_message(
iv_msg_type = /iwbep/cl_cos_logger=>warning
iv_msg_number = '123'
iv_msg_id = 'ZFOO'
).
" optional, only used for 'true' errors
RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
EXPORTING
message_container = lo_message_container.
In the Fiori app, we can directly access those data from the message manager. The data can be applied to a MessageView control.
// Fiori part (Desktop, online)
var aMessageData = sap.ui.getCore().getMessageManager().getMessageModel().getData();
However, our offline app always has an empty message model. After a sync or flush, the message model is always empty - even after triggering message generating methods in the backend.
The only way to get some kind of messages is to raise a /iwbep/cx_mgw_busi_exception and pass the message container. The messages can be found, in an unparsed state, in the /ErrorArchive entity and be read for further use.
// Hybrid App part, offline, after sync and flush
this.getModel().read("/ErrorArchive", { success: .... })
This approach limits us to negative, "exception worthy", messages only. We also have to code some parts of our app twice (Desktop vs. Offlne App).
So: Is there a "proper" to access those messages after an offline sync and flush?

For analyzing the issue, you might use the tool ILOData as seen in this blog:
Step by Step with the SAP Cloud Platform SDK for Android — Part 6c — Using ILOData
Note, ILOData is part of the Kapsel SDK, so while the blog above was part of a series on the SAP Cloud Platform SDK for Android, it also applies to Kapsel apps.
ILOData is a command line based tool that lets you execute OData requests and queries against an offline store.
It functions as an offline OData client, without the need for an application.
Therefore, it’s a good tool to use to test data from the backend system, as well as verify app behavior.
If a client has a problem with some entries on their device, the offline store from the device can be retrieved using the sendStore method and then ILOData can be used to query the database.
This blog about Kapsel Offline OData plugin might also be helpful.

Related

How to add double tap detection to sample app gatt_sensordata_app?

I am developing an Android app that gets data from Movesense using the GATT profile from the sample app GATT Sensor Data App here.
I followed the tutorial available here. Building the app and getting the DFU worked fine. I can get IMU, HR and temperature data with no issues.
Now I'd like add a tap detection feature to my app. I understand that I have to subscribe to 'System/States', but first I need to be able to receive the system state data.
I understand that I need a modified DFU for that, but I don't understand what changes I should make in which files of the gatt_sensordata_app before rebuilding and generating the new DFU.
What changes should I make in order to broadcast /System/State data?
(I usually just deal with Android so apologies for the very basic question.)
I tried adding #include "system_states/resources.h" to GATTSensorDataClient.cpp but I don't know how to continue.
The normal data straming in the gatt_sensordata_app uses the sbem-encoding code that the build process generates when building the firmware. However /System/States is not among the paths that the code can serialize. Therefore the only possibility is to implement the States-support to the firmware.
Easiest way is to do as follows:
In your python app call data subscription with "/System/States/3" (3 == DOUBLE_TAP)
Add a special case to the switch in onNotify which matches the localResourceId to the WB_RES::LOCAL::SYSTEM_STATES_STATEID::LID
In that handler, return the data the way you want. Easiest is to copy paste the "default" handler but replace the code between getSbemLength() & writeToSbemBuffer(...) calls with your own serialization code
Full disclosure: I work for the Movesense team

How do I handle and return a human readable error in a Java Azure Function app?

How do I handle and return a human readable error in a Java Azure Function app?
All examples of this on a Google search, are just simple instructions on how to do a try-catch, which is not my question.
More specfically, how do we design the return status code and the response body of the request, in a way that provides the most flexibility to a wide array of situations?
Given that we are not integrating Spring-Boot in this case, and that we do not have access to anything Spring.
Given that my API generally returns an object that we will call Pojo1, on error, what is the best way to return a informative message.
NOTE: Of course, I do know there are situations where you want security through obscurity, in which case I would probably choose logging errors to app insights. This is not my question though.
Well, you can set custom headers while returning the request. This
can be done using a setHeader function.
You can also use azure service bus or event grid which will carry
specific messages regarding the errors.
Also, you can use azure monitoring which collect all the error and
notify you when everything happens.
Refer this article by Eugen Paraschiv for indepth explanation on how to use setheader.
Refer this documentation on azure service bus and this documentation on event grid.
Refer this documentation on azure monitoring logs.

How to auto-refresh a screen in Moqui?

Use case is a regularly updated display of vehicle tracking data retrieved through a REST call, onto a central office screen, with no user interaction.
There is no single answer for this, but some alternatives to consider:
add some JavaScript to your screen that uses the JS setTimeout() method or something similar to reload the page
for a smoother result but a lot more effort write the section of the screen that needs to auto-update as a Vue component and use the standard websocket interface to send data to the browser to update the data in the HTML; this is generally best done using the NotificationMessage interfaces and methods in the Moqui API where the JavaScript client registers on a topic and gets a notification along with any others registered (structure the topic ID as needed to differentiate different feeds) and have a scheduled service job feed the notification topic

Is it possible to allow Worklight users to use app before updating?

Let's say I push new code to the Worklight server for purposes of a Direct Update. Can I allow users to still use the application for a set amount time before they actually have to accept the update or is the application essentially unavailable to them until they download the new code?
If you are developing your application using Worklight 6.2, then you as a developer can take over the entire Direct Update flow and can essentially decide how to handle a received update from the server.
Note that by taking full control, you own the flow end-to-end; the default Worklight framework handling will not be available and the full responsibility is on the developer to ensure the validity of every step.
You can read more about customizing Direct Update, here:
Initial reading, starting slide #14: http://public.dhe.ibm.com/software/mobile-solutions/worklight/docs/v620/05_06_Using_Direct_Update_to_quickly_update_your_application.pdf
In depth reading: http://www-01.ibm.com/support/knowledgecenter/SSZH4A_6.2.0/com.ibm.worklight.dev.doc/dev/c_customizing_direct_update_ui_android_wp8_ios.html
In your scenario, I think you could probably go in a less extreme way and just do some tweaks before letting the Worklight framework handle the update from the server. Meaning, you could use the example provided in the training module (slide #18 from the PDF above), where you intercept the update:
wl_directUpdateChallengeHandler.handleDirectUpdate = function(directUpdateData,
directUpdateContext) {
... // display message or counter
}
And display a message and start a counter, and when time's up just directUpdateContext.start(); the update.

Error which hit the limit of JSONStore

I found Worklight JSONStore has no size limit by Worklight runtime.
Does WL JSONStore API return error/error code if you add to collection and hit the size limit of your mobile device?
Yes, you should get an error, but it will be a generic one like PERSISTENT_STORE_FAILURE (-1). I recommend testing this as part of your regular unit, funcional, etc. tests and QA process for your application. Report back if you see something unexpected.
Recently I answered a similar question "Can the JSON offline device store be size restricted?". I'll add my answer here because I believe it could be helpful.
While this functionality is not baked into the core API, it should be fairly straightforward to implement.
JSONStore has an enhance method you can use to add functions to the JSONStoreInstance prototype. There's an example inside that should help.
Cordova has a File API
Note: "size: The size of the file in bytes. (long)"
JSONStore stores its data here:
iOS: [app]/Documents/wljsonstore/jsonstore.sqlite
Android: /data/data/com.[app-name]/databases/wljsonstor/jsonstore.sqlite
I talked a bit about that file in these StackOverflow answers:
What are the recommended ways to debug Worklight applications?
JSONStore difference between 'number' and 'integer' in searchFields
Check the file size of jsonstore.sqlite using Cordova's File API before you add more data to your JSONStore collection.
Basically you would do something like this:
if(checkFileSize(collection.name+'.sqlite') < LIMIT){
collection.add(...);
}
Using enhance you can wrap that logic into its own method (e.g. collection.addWithSizeCheck(....)) that checks the file size and calls collection.add(...).
Note that the default username is jsonstore, hence jsonstore.sqlite. If you pass a username to init it will create a new .sqlite file with that username.