Tuesday, November 18, 2014

MAF 2.0 : Loading Images in a Background Process - Part I

Images are heavily used in Mobile apps. For instance a list that contains employees usually shows the images of these employees. This works well when you have a WIFI connection, but what if you are using slower connections ? If you look at a mobile twitter app you will see that, depending on connectivity, images are loaded instantaneously or delayed. In this post I explain how you can load the images of a List in a background process, after the other content has been loaded.

Tuesday, October 14, 2014

OOW14 : One week in a nutshell

Two weeks ago I visited Oracle Open World in San Francisco. A glimpse of my activity during Oracle Open World can be found in this post. If you want to hear more, please visit the AMIS Oracle Open World Review Session at October 16th.


Saturday
After a one hour delay at Amsterdam Schiphol Airport the airplane with, amongst others, several AMIS employees took of for San Francisco. There we met with our colleagues who flew in earlier this week.

Book : Oracle Mobile Application Framework Developer Guide

It has been a while since my previous post, and I have a very good reason for that. I have been busy, very busy. But now, after a long time of writing and rewriting I can finally announce that my book, Oracle Mobile Application Framework Developer Guide, is available for you to buy. Many thanks to my reviewers Chris Muir, Frank Nimphius and Joe Huang who guided and helped me all the way.















If you are starting with Oracle MAF development, this book will give you a jump start. You will learn the concepts of MAF and MAF development and learn tips and tricks for MAF development.
In Oracle Mobile Application Framework Developer Guide, I explain how to use this powerful framework to create multiplatform mobile apps based on a single code base. Detailed examples and ready-to-use code are provided throughout the book. A complete, step-by-step sample application highlights the robust functionality of Oracle Mobile Application Framework, including data visualization, UX patterns, geographical maps, push notifications, and more.
A glimpse of the content:
  • Configure your IDE for Android and Apple iOS application development
  • Build AMX pages and task flows for mobile applications
  • Work with the binding layer and data controls
  • Create application features and configure access to them in the springboard and navigation bar
  • Call web services using a data control and create an on-device database
  • Implement device interaction.
  • Debug, test, and secure Oracle Mobile Application Framework applications
And finally you will learn how to build an interactive sample app.
Table of contents
Part One: Understanding the Oracle Mobile Application Framework
1: Introduction to Mobile Application Development
2: Setting Up JDeveloper and Your Development Platform
3: Oracle JDeveloper for Mobile Application Framework Development
4: Building AMX Pages
5: Bindings and Data Controls
6: Application Features
7: Using Web Services and Local Database
8: Device Interaction
9: Debugging and Testing Mobile Application Framework Applications
10: Security and Deployment
Part Two: Developing the Sample Application
11: Explaining the TAMCAPP Sample Application
12: Developing the Springboard
13: Building the Conference Session Feature
14: Building the Attendees Feature
15: Developing the Maps and Social Network
16: Configuring Security and Preferences
17: Implementing Push Notifications
18: Enhancing TAMCAPP
If you want to read the book, You can buy it at the #oow14 bookstore or on-line :
http://www.mhprofessional.com/product.php?isbn=0071830855
Here you can also read the The of Contents and the first chapter to get a glimpse of the book.
The book is also available at Amazon.com
http://www.amazon.com/gp/aw/d/0071830855/ref=mp_s_a_1_1?qid=1411508554&sr=1-1

Tuesday, June 18, 2013

ODTUG KScope 2013 : I'm Speaking

Next week the ODTUG KScope conference kicks of in New Orleans.


During this conference I will present 3 sessions:
Keep your eyes on this weblog for more information on ADF and Mobile stories of ODTUG KScope13.
 

Friday, May 31, 2013

ADF Mobile : Oracle eCourse available

Today Oracle published the first in a series of online eLearning training materials. The ADF Academy presents free and online : Developing Applications with ADF Mobile. The main goal is to deliver technical training material to everybody that needs it. You get an online training, where you can view audio and video to learn ADF. Whenever you want to you can stop the recordings to try out everything that you learned so far, or perhaps to get a drink.



Developing Applications with ADF Mobile is available here.
Take to opportunity and learn to work with a great framework to develop mobile applications for iOS and Adroid.

Also keep an eye on lucbors.blogspot.com for more ADF Mobile related content.

Thursday, February 28, 2013

ADF Mobile : Implementing the "Pull to Refresh" Pattern

One very common pattern in Mobile Apps is the use of "pull" to refresh a list of data in an App.
For one of my projects I suggested to use this pattern and I had to figure out a way to implement this in ADF Mobile. In this post I show you a way to implement this. If you are only interested in the refresh part, you might want to skip the first 5 steps. These explain in short the webservice and the basic ADF Mobile app. From step 6 on I explain how to implement the pattern.

1. The webservice
For this example I use a simple webservice that returns a List of Locations. The webservice is a service enabled Application Module. I simply created Business Component (EO and VO) on the Locations table from the HR schema. I exposed the Locations view object as AllLocations, and added a method called getCurrentCount() on the Application Module Impl class.  This method simply invokes the getEstimatedRowCount() to find out the number of rows. Next I created a new Service Interface on the Application Module. And that is about it for the service.
This all resides in a separate application and is deployed on a remote weblogic server. The mobile app will use this webservice.

2. The Mobile App
Create a simple ADF Mobile Application. In this application I need to call out to the webservice. For that I use a webservice datacontrol. Simply invoke the "create webservice" dialog, give the webservice a name and enter the URL of the WSDL.

In the second part of the wizard, I simply select the two operations that I need.

The webservice datacontrol is now finished. Both operations are now available from the datacontrol. The datacontrol looks like this:

3. The custom model
For the application I want to use a custom object model in order to be independent of the webservice data structure. This is common practice and recommended approach. The class that I use for this is called MyLocation.


I use the following properties:

 package nl.amis.technology.mob.objects;  
 public class MyLocation {  
 private int LocationId;  
 private String StreetAddress;  
 private String PostalCode;  
 private String City;  
 private String StateProvince;  
 private String CountryId;  
   public MyLocation() {  
     super();  
   }  
 }  

Simply generate accessors for these and the class is finished.

4. Invoking the webservice
Now I create a new class that I use in my mobile application to provide the app with data. This class is called LocationInfoDC. In this class I create a list of locations that I can display in the mobile app.

 public class LocationInfoDC {  
   private static List s_locationsList;   
   private transient ProviderChangeSupport providerChangeSupport =   
               new ProviderChangeSupport(this);  
   public LocationInfoDC() {  
     super();  
     if (s_locationsList == null) {  
       s_locationsList = new ArrayList();  
       retreiveLocationInformation();  
     }  
   }  
   public void AddLocation(MyLocation l) {  
     s_locationsList.add(l);  
   }  
   public MyLocation[] getAllLocations() {  
     MyLocation locs[] = null;  
     locs = (MyLocation[])s_locationsList.toArray(new MyLocation[s_locationsList.size()]);  
     return locs;  
   }  
  ......  

For webservice invocation I use AdfmfJavaUtilities.invokeDataControlMethod(). This enables me to invoke a Datacontrol Method whithout having a page Definition available. It is a powerful mechanism.

 // This calls the DC method and gives us the Return  
    GenericType result =  (GenericType)  
       AdfmfJavaUtilities.invokeDataControlMethod("HrWsDc"  
                                          , null  
                                          ,"findAllLocations"  
                                          ,pnames, params, ptypes);  

The AdfmfJavaUtilities.invokeDataControlMethod() returns a GenericType. This response needs to be "converted" to the custom object model described in step 3.

  // The Return wraps the findAllLocations Result, so get that out of the Result  
   s_locationsList.clear();          
    for (int i = 0; i < result.getAttributeCount(); i++)   
    {  
      GenericType row = (GenericType)result.getAttribute(i);  
      MyLocation locationInformation = (MyLocation)  
             GenericTypeBeanSerializationHelper.fromGenericType(MyLocation.class, row);  
      AddLocation(locationInformation);  
    }  

Another important part is the invocation of the client page refresh. The ProviderChangeSupport class is used for sending notifications relating to collection elements, so that components update properly when a change occurs in a Java bean data control. I refresh the collection delta, using the ProviderChangeSupport class. Since the provider change is required only when you have a dynamic collection exposed by a data control wrapped bean, there are only a few types of provider change events to fire:
  • fireProviderCreate—when a new element is added to the collection
  • fireProviderDelete—when an element is removed from the collection
  • fireProviderRefresh—when multiple changes are done to the collection at one time and you decide it is better to simply ask for the client to refresh the entire collection (this should only be used in bulk operations)
I use the fireProviderRefresh, asking for the client to refresh the entire collection.

The trick that does the magic:

 providerChangeSupport.fireProviderRefresh("allLocations");  

For this class I also generate a datacontrol so I can use it on the mobile page.

5. The Mobile Page
The view for the list is a simple amx page.
Create the page and drag the AllLocations collection from the datacontrol onto the page. In the popup menu pick "ADF Mobile List View".


Actually that is all that needs to be done. Now after deploying, the app looks like this.


Now it is time to implement the "pull to refresh".

6. Implementing the pull to refresh: Calling the service
In order to refresh the list, I need to know if there are actually new records available in the database.
This information is provided by the getCurrentCount webservice operation. First I create a new pageflowscoped backing bean to hold all logic involved in this functionality. In this bean I have one property. This is used to store the latest record count. This count is used to make sure that the findAllLocations webservice is only invoked if necessary.

 public class LocationsBackingBean {  
   String count="0";  
   private transient PropertyChangeSupport propertyChangeSupport =   
           new PropertyChangeSupport(this);  
   public LocationsBackingBean() {  
   }  
   public void setCount(String count) {  
     String oldCount = this.count;  
     this.count = count;  
     propertyChangeSupport.firePropertyChange("count", oldCount, count);  
   }  
   public String getCount() {  
     return count;  
   }  


To call the webservice that returns the current record count (getCurrentCount) I also use AdfmfJavaUtilities.invokeDataControlMethod().
The returned value (= the current number of rows in the database table) is compared to the previous amount returned by this service call. If there are more rows in the database table, I want to refresh the List. To do that, I simply call out to the  "findAllLocations" service. After successful invocation, the count is updated to the new value.

   public void checkForUpdates(ActionEvent ea) {  
    ......  
   String result;  
     try {  
       // This calls the DC method and gives us the Return  
       result = (String)   
             AdfmfJavaUtilities.invokeDataControlMethod("HrWsDc"  
                                                , null  
                                                , "getCurrentCount"  
                                                , pnames, params, ptypes);  
       // After service call, compare result to current count  
       // If new records are available, refresh the list by calling the webservice via invoking     
       // the corresponding method binding   
       if (Integer.valueOf(this.count).compareTo(Integer.valueOf(result))<0){  
         AdfELContext adfELContext = AdfmfJavaUtilities.getAdfELContext();  
         MethodExpression me =   
                AdfmfJavaUtilities.getMethodExpression(  
                     "#{bindings.retreiveLocationInformation.execute}"  
                    , Object.class, new Class[]{});  
         me.invoke(adfELContext, new Object[]{});  
         // after succesfully refreshing the list, update the current number of rows  
         setCount(result);  
        }  
     } catch (AdfInvocationException e) {  
        ............    }   
       catch (Exception e2) {  
       ...............    }  
   }  

7. Implementing the pull to refresh: Configure the Listview
I want to refresh the list with Locations whenever the list is pulled down.
For this I use the amx:actionlistener component. This component allows you to declaratively invoke an action. This component is meant to be a child component of any tag that has some kind of listener attribute like actionListener, or valueChangeListener, etc. The type attribute defines which listener of the parent this actionListener should be fired for. These methods fire before the listener on the parent component fires.
In the actionListener I invoke the checkForUpdates method that was described earlier.

The component has two attributes: type and binding. Type is set to swipeDown and in the binding attribute I use the checkForUpdates method that is implemented in the locationsbean.

  <amx:actionListener type="swipeDown"   
                  binding="#{pageFlowScope.locationsBackingBean.checkForUpdates}" />  

The complete code for this simple Listview now looks like this:
   <amx:listView var="row" value="#{bindings.allLocations.collectionModel}"  
          fetchSize="#{bindings.allLocations.rangeSize}"   
          id="lv1">  
    <amx:listItem id="li1">  
    <amx:actionListener type="swipeDown"   
                     binding="#{pageFlowScope.locationsBackingBean.checkForUpdates}" />  
     <amx:tableLayout width="100%" id="tl1">  
      <amx:rowLayout id="rl1">  
       <amx:cellFormat width="10px" id="cf3"/>  
       <amx:cellFormat width="60%" height="43px" id="cf1">  
        <amx:outputText value="#{row.streetAddress}" id="ot2" inlineStyle="font-size:x-small;"/>  
       </amx:cellFormat>  
       <amx:cellFormat width="10px" id="cf2"/>  
       <amx:cellFormat width="40%" halign="end" id="cf4">  
        <amx:outputText value="#{row.city}" styleClass="adfmf-listItem-highlightText" id="ot3"  
                inlineStyle="font-size:small;"/>  
       </amx:cellFormat>  
      </amx:rowLayout>  
     </amx:tableLayout>  
    </amx:listItem>  

8. The result
After deploying the app it is time to test the behavior. After starting the app and the list shows some Locations.

Now add 1 or 2 Locations to the database and commit these changes.



Swipe the list down, release  and see what happens.......

The new Locations are displayed.

9. Some Final Notes
This example (and actually the pattern) works for lists that show rather static data (no update or deletes). Every "pull down" gesture checks the server for new rows. That is, it checks if there are more rows then during the last call, and if so, the new rows are returned and added to the list. So whenever there are deleted or changed rows, this is not reflected in this sample. I could have implemented a service only returning the new Locations and add those to the list, but for this example I decided to simply fetch all Locations and rebuild the list. One other improvement is to only invoke the webservices if the "pull down" is invoked on the first row in the list.

Thursday, December 27, 2012

ADF Mobile : Device Interaction API - Pictures, GPS and Email With Attachments

During the AMIS ADF Masterclass I showed how to take a picture from within an ADF Mobile application, attach it to an Email and send that email out to several recipients. To top it of, I even added the GPS coordinates to the subject, so you know where the picture was taken. And all of that with the push of one single button. Sounds complicated ? Well actually it is very simple.

There are two ways to interact with device services. One is by using the page Definition, the second is by using the API.I decided not to use the pageDef, but to invoke the device datacontrol from java by using the API. Then it is also possible to invoke multiple actions in one java method. In this case I take a picture, get the coordinates and send an email.

How to take a picture ?
Taking a picture is easy. Just call the getPicture() method, and make sure (for this use case) to set Destination Type to File.
 public String getPicture(){  
   //destinationType = 1 so that the image is returned as a filename      
   String theImage = DeviceManagerFactory.getDeviceManager().getPicture(  
            100  
           ,DeviceManager.CAMERA_DESTINATIONTYPE_FILE_URI  
           ,DeviceManager.CAMERA_SOURCETYPE_CAMERA  
           , false  
           ,DeviceManager.CAMERA_ENCODINGTYPE_PNG  
           ,0  
           ,0);  
   return theImage;  
   }  

That takes care of taking the picture.

How to get the current coordinates ?
By invoking getCurrentPosition it is very easy to get the GPS coordinates. Simply call the getCurrentPosition() method, and you will get the current coordinates. The coordinates are refreshed every 60 seconds.
 public Location getPosition(){  
   Location currentPosition = DeviceManagerFactory.getDeviceManager().getCurrentPosition(  
                                    60000  
                                   , true);  
   return currentPosition;  
 }  


How to send an email ?
First take a look at the signature of the sendEmail() method. This immediately makes clear how to proceed from here...
 DeviceManagerFactory.getDeviceManager().sendEmail(  
         java.lang.String to  
         ,java.lang.String cc  
         ,java.lang.String subject  
         ,java.lang.String body  
         ,java.lang.String bcc  
         ,java.lang.String attachments  
         ,java.lang.String mimeTypes)  

The signature explains how it works. All that is needed are Strings. If you want to use multiple recipients, you need to separate them by comma's. The final question is: "how to attach the image that was just created ?".

Attaching the image.
You can do two things. Either use the String that is returned by calling getPicture(), or directly attach the file from the Temporary Directory which I do in this case.
 public void sendEmail(String attachment, Location here){  
   String directoryPathRoot = AdfmfJavaUtilities.getDirectoryPathRoot(0); //TemporaryDirectory  
   String content = "Amis wishes you all the best for 2013. This email contains an image as attachment. ";  
       content = content + "The picture was taken at: latitude=" + here.getLatitude() +  
            ", longitude=" + here.getLongitude();  
   attachment = directoryPathRoot+"/Pic.png";  
   DeviceManagerFactory.getDeviceManager().sendEmail("my.mail@company.org"  
                            , null  
                            , "Merry Xmas and a Happy new year"  
                            , content  
                            , bcc  
                            , attachment  
                            , "image/jpg");  

The content and bcc in the above code sample are Strings that can be set in the method.

Putting it all together
The only thing you need is a button to invoke a method in the bean.
 amx:commandButton text="Take Picture" id="cb3"  
                actionListener="#{pageFlowScope.interactionBean.executeLogic}"  

The method executeLogic() does the magic by invoking all three methods described above.
 public void executeLogic(ActionEvent actionEvent) {  
   String att = getPicture();    
   Location whereAmI = getPosition();  
   sendEmail(att, whereAmI);  
   }  


Push the button, the camera is invoked, and after that, the email client is invoked, showing an email with the attachment, the content (including GPS coordinates) and the recipients.

Sunday, December 16, 2012

Book Review : Oracle ADF Real World Developer's Guide

In October 2012 yet another ADF Book was published. This book "Oracle ADF Real World Developer's Guide" is authored by Jobinesh Purushothaman. Jobinsh works with Oracle as a Principal Solutions Architect for the Oracle Application Development Framework. The book is full of essential tips and tricks for building ADF applications. In this post I will share my book review with you and I give you the chance to win a free copy.



This book is suitable for ADF developers who are looking forward to build healthy and better performing applications using Oracle ADF. A book filled with step-by-step instructions and real-time examples with illustrations, diagrams, and tips that help developers learn the visual and declarative programming model offered by ADF. Using this book, readers will learn to get started with building business services using ADF business components, validate business data in different layers of an application and understand the use of EJB and web services in an ADF application.

The book contains 12 Chapters containing anything from getting started to Advcance topics.

Before I go into each chapter, I must say that this book has a couple of outstanding ways of explaining the ADF Framework. First of all there are many simple diagrams (and images) explaining the framework and parts of the framework. These diagrams are easy to understand, because thay only contain relevant information. You are not being distracted by colors or misleading images. It is just simple images, but very clear.

Next there are the sequence diagrams. These diagrams explain what exactly happens (at class level) when for instance you issue execute query from an ADF Application. As far as I know this is the first book that uses these sequence diagrams to explain ADF in a very clear way.

Finally I need to point out the valuable code samples that are in the book. Get yourself a digital copy so you can easy copy and past these code snippets into your ADF application.

Now lets take a look at the chapters.

Part I : getting started

1 : Getting Started with Oracle ADF
The most interesting part for me is the section on "Comparing the Fusion web application technology stack to the Java EE web application". This is explaining ADF in the context of a Java EE application. Currently I am involved in a project where we need to "rebuild" a Java EE application in ADF. There is a lot of discussion in this project about responsiblity of eaach layer. This chapter can help Java EE developers understand the ADF framework. The image on page 13 of the book ADF and Java EE by putting both in one diagram next to eachother.

Also the part about the generated Metadata files is valuable. Ussualy these files (like adf-settings, weblogic-application) are taken for granted, but Jobinesh explains what all the metadata files are about.

Part II : ADF Business Components

2 : Introduction to ADF Business Components
3 : Introducing Entity Object
4 : Introducing View Object
5 : Advanced Concepts on Entity Objects and View Objects
6 : Introducing the Application Module
This part provides a detailed look at how entities, view objects and application modules are defined and how they work at runtime. I was impressed by the level of detail in chapter 2. It is great that I have a couple of more chapters that go even into more detail.  This chapter really made me wanna continue reading. Chapters 3 and 4 are introducing the basic concepts of View Objects and Entity Objects. Both chapters contain very helpful sequence diagrams explaining what happens internally within entity objects and view objects.

At the start of chapter 5 Jobinesh tells the reader to "Take a deep breath and prepare yourself".  The part that follows takes a deep dive into entity objects. This chapter is full of in depth Entity Object knowledge. Allthough I have been working with ADF for many many years there were some interesting featured in this chapter that I did not know about. (mainly because I never had to use these). For instance, did you know that you can call getAttribute(attrIndex,EntityImpl.ORIGINAL_VERSION) on an entity object to read the originally retrieved value for an attribute ? I allways use(d) getPostedAttribute(int attribIndex).

At the end of the Entity Object section there is an interesting part on "Building programmatically managed entity objects" including code samples.

The most interesting part of the View Object section is about working with ViewCriteria Programmatically. Also the section about working with XML data is a noce one. I never got to use this functionallity in real life. Jobinesh explains very well how to do this, and I hope to get a use case soon. The chapter ends with a section about "Building business components dynamically".

After reading chapter 5 I can only say one thing: "I am impressed !".

Chapter 6 covers important topics like properties, passivation, activation, application module pooling.

7 : Binding Business Services with the User Interface
Chapter 7 really contained nothing new to me. However, if you are new to ADF, this chapter contains very good explanation of the binding layer. There is an interesting part about "Invoking an application module from a Java servlet". I did use this approach in several occassions. It is good to have a section on this in the book. Again in this chapter there are several simple diagrams that help you understand what happens in the binding layer.

8 : Building Data Bound Web User Interfaces

This is about building data bound web user interfaces. It has a small section on layout components. It also talks about working with tree and treetables programmatically. One of the things I learned form this chapter is how to use the "RowCountThreshold" attribute in an iterator binding. Never did that before.... On page 327 there is a "best practice" that you should know about: "If the scope of the managed bean is higher than the request, then you should not bind the UI components' elements in the JSF page with the UI component instances defined in a managed bean using the binding attribute in the component tag"

9 : Controlling the Page Navigation
For me there really wasn't anything new but, if you are new to ADF, it is again a very nice chapter.

10: Taking a Closer Look at the Bounded Task Flow
This chapter takes a deep dive into the bounded taskflow. There are sections on "dynamic taskflow calls, Lazy Loading and there is even a section on Contextual events.

11: More on Validations and Error Handling
Yet another chapter containing very valuable tips. Very interesting is the part where you learn how to vreate a custom validator containing client side java scriupt validation.
Also you learn how to define model layer validation which is in fact rarely used. And there is an interesting diagram that helps you understand how the framework engages
DCErrorHandlerImpl during the page life cycle for handling exceptions thrown by business components when accessing them in the binding context

12: Oracle ADF Best Practices
This chapter summarizes the best practices and coding tips that developers will find useful when building ADF applications. Learning the best practices will help you to avoid common pitfalls that others might have faced.  The content for this chapter is based on input from various teams who have successfully used ADF.

My advise is that you should really buy this book ! It is full of valuable tips and tricks ! When you buy this book, all code samples in this book are available online so you can download these and play with them.
The book is available here.

Get yourself a free Christmas present !

For the contest I have two copies of Oracle ADF Real World Developer’s Guide to be given away to two lucky winners.

How you can win:
To win your copy of this book, all you need to do is come up with a comment below highlighting the reason "why you would like to win this book”.

Please note: Winners residing only in the USA and Europe would get a chance to win print copies. Others would be provided with eBook copies.
Duration of the contest & selection of winners:The contest is valid for 7 days (contest ends 23-12-2012 23:59 GMT) , and is open to everyone. Winners will be selected on the basis of their comment posted.