Thursday Dec 18, 2014

GeneratedPassword: a hidden MAF gem

The transition from ADF Mobile to the Oracle Mobile Application Framework earlier this year brought us many great new features. Some of them were very visible, such as new Data Visualization components or the new Oracle Alta UI skin. Others are more difficult to find. In this post, I want to introduce you to one of the latter, namely the GeneratedPassword class, which is part of the oracle.adfmf.framework.api package.

The sole function of GeneratedPassword is to generate and manage random passwords. Each of the passwords is identified by a key, which will be used to retrieve it when needed. The passwords are saved to an encrypted credential store, similar to the one used to store user passwords related to login connections. To create a password, simply pass the desired key to the appropriate method along with a seed which will add entropy to the generation algorithm. Subsequent calls to that method using the same key and seed will result in a different password every time. 

At this point, maybe you are asking yourself what those random passwords are good for. Personally, I find them very useful to enhance the protection of encrypted SQLite local databases. In the current version of Oracle MAF, it is necessary to provide a password in order to encrypt or decrypt a database. If you hardcode that password, it will be shared by all deployed instances of your application. If one instance is compromised, then all others will be at risk. Using a random password for that use case is a good mitigation measure, since every instance uses a different encryption key. Compromising multiple instance is thus much more time consuming. 

Thursday Jun 20, 2013

Saved by the local database!

In my last post, I told you about my latest ADF Insider Essentials recording on the local database, and pointed you to the companion code sample. I had lots of feedback about both. I am glad to see I have so many viewers and readers!

Among all the questions I got, one was asked very frequently: « How can I transparently retrieve data from the database when a web service call fails? » In other words: how can the local database save my life if the web service doesn't respond? This is a bit different from what I had implemented initially. Thus, I built a new version of the sample application which does exactly that. In the original sample, the code simply detected the presence or absence of a network connection; an available connection meant the web service call was assumed to succeed. Otherwise, an exception was raised and displayed to the user. Thus, the key change to obtain the desired behavior is simply to catch the exception. Then, it is easy to invoke the method that retrieves data from the database instead.

Here is the relevant method in the sample application.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    private CountryBO[] getCountriesFromWS() {
        try {
            GenericType genericReturnValue =
                (GenericType)AdfmfJavaUtilities.invokeDataControlMethod("HR_WS", null, "findCountry", new ArrayList(),
                                                                        new ArrayList(), new ArrayList());
            CountryBO[] returnValue =
                (CountryBO[])GenericTypeBeanSerializationHelper.fromGenericType(CountryBO[].class, genericReturnValue,
                                                                                "result");

            Arrays.sort(returnValue);
            return returnValue;

        } catch (AdfInvocationException aie) {
            if (AdfInvocationException.CATEGORY_WEBSERVICE.compareTo(aie.getErrorCategory()) == 0) {
                AdfmfContainerUtilities.invokeContainerJavaScriptFunction("oracle.adfinsider.localdb.countries",
                                                                          "navigator.notification.alert",
                                                                          new Object[] { "The web service is unavailable. \n\n Data has been retrieved from the local cache.",
                                                                                         "null", "Warning", "Ok" });

                return getCountriesFromDB();
            } else {
                throw new RuntimeException(aie);
            }
        } catch (Exception ex) {
            Utility.ApplicationLogger.severe(ex.getMessage());
            throw new RuntimeException(ex);
        }
    }

Another nice thing this code snippet demonstrates is how to call JavaScript code from Java business logic. At line 15, I invoke a method which is part of the Apache Cordova library to display a warning message to the user. Cordova is an integral component of ADF Mobile, but your AMX pages must be properly configured in order to use it. I added the proper references to the countriesList.amx page like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
  <amx:panelPage id="pp1">
    <amx:verbatim id="v1">
        <script type="text/javascript">if (!window.adf) window.adf = {}; adf.wwwPath = "../../../../www/";</script> 
        <script type="text/javascript" src="../../../../www/js/base.js"></script>
        <script type="text/javascript" src="../../../../www/js/cordova-2.2.0.js"></script>
    </amx:verbatim>
    <amx:facet name="header">
      <amx:outputText value="#{viewcontrollerBundle.COUNTRIES}" id="ot1"/>
    </amx:facet>
...
  </amx:panelPage>

I placed the script references (lines 3 to 5) inside a verbatim tag, which ensures that they will be rendered as is in the page.

While I was at it, I fixed a few other issues with the sample. In the original version, the database connection was closed inside the stop() method of the LifeCycleListenerImpl class. The stop() method is usually called when the use exits the application; there is no guarantee, however. Thus, the connection wouldn't be closed properly in some corner cases. To fix this, I moved the code to the deactivate() method, which doesn't suffer from the same drawback and will be called each time the user switches to another application. This is much better, as the connection will be properly closed even if the device crashes while the application is inactive.

You can download the refreshed sample application here

About

Frédéric Desbiens

The musings of a member of the Mobility and Development Tools Product Management team.

I focus here on my favorite development frameworks, namely Oracle ADF and the Oracle Mobile Application Framework (MAF), but also have a strong interest in SOA and web services.

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.

Search

Archives
« September 2015
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today