Screencast 9 – ADF Mobile and WebCenter Content Simple Example

Any discussion around user interface capability inherently entails a discussion around mobile enablement. Organizations are making concerted efforts to understand how to develop and extend user experiences to a wide range of mobile devices.

Oracle’s ADF Mobile allows companies to develop leverage the power of declarative development and data binding to enable mobile experiences for new and existing systems.

In this episode of the Enterprise 2.0 Workbench we take a look if using ADF Mobile to create an interface on top of WebCenter Content. We do this using a web service data control that is being generated on top of a Java Bean connecting to Content Server. Our Java Bean uses RIDC to connect to content server and although it is not necessarily best practice to layer a web service on top of a bean using RIDC (RIDC uses services to call into Content Server – creating additional service traffic), it gives us a sense of how we can use existing services or services that are quickly enabled through a plain old job object to create our mobile interfaces.

Simple Example Scenario

In our example to create a mobile interface on top of the sales library to enable our sales people in the field to get the most recent, approved content items to help them do their job.

For organizations looking for true production mobile capabilities for WebCenter Content should review

Let’s dive in and review the various components within our simple example solution.

WebCenter Content

The basic sales library that we will expose via our mobile interface is supplied using WebCenter Content to secure and categorize the sales assets.

AMX Mobile Pages

Our solution only consists of two pages. These pages are created using ADF Mobile’s AMX tags. The DocView.amx will recursively call itself if a user chooses to drill into a folder within the interface. If a user selects a document the view will be routed to DocView.amx.

Document List Views – amx:setPropertyListener and amx:listView
For each selection we will store the relevant ID code in a managed bean associated with our application. This is done by including an amx:setPropertyListener within each list item to set the selected node. Once the row is selected, the managed bean’s GetCollection method will be called to refresh the data bound to 2 amx:listView components.

DocView.amx



  
    
      
        
        
          
            
              
            
            
              
            
          
        
      
    
    
      
        
        
        
          
            
              
            
            
              
            
          
          
            
              
            
          
        
      
    
    
      
    
    
      
    
    
    
  

DetailView.amx



  
    
      
    
    
      
    
    
    
    

    
  

Data Controls used to Create amx:listView

The 2 amx:listView components in the DocView.amx were declaratively based on the following controls that were dragged and dropped into the AMX page. The data controls were created by creating a new “Web Service Data Control” in our project based on a WSDL from our service layer on top of Content Server.

Managed Bean in ADF Mobile

Our managed bean does the heavy lifting in our example. It contains a series of methods that are called from our AMX page using actionListener attributes of our components.
Managed Bean DocBean.java

package mobile;

import java.util.ArrayList;
import java.util.List;

import javax.el.ValueExpression;

import oracle.adfmf.amx.event.ActionEvent;
import oracle.adfmf.framework.api.AdfmfContainerUtilities;
import oracle.adfmf.framework.api.AdfmfJavaUtilities;

import oracle.adfmf.framework.exception.AdfInvocationException;
import oracle.adfmf.java.beans.PropertyChangeListener;
import oracle.adfmf.java.beans.PropertyChangeSupport;

public class DocBean {

    // Start node for the document viewer (dCollectionID)
    private String rootCollectionNode = "727456639941000002";

    // Track the currently selected node
    private String selectedNode = rootCollectionNode;

    // Link to converted content
    private String docURL = "";

    // Name of content item that has been selected
    private String docName = "";

    private transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    public DocBean() {
        super();
    }

    // Store the seclected node for a given folder in the UI
    public void setSelectedNode(String selectedNode) {
        String oldSelectedNode = this.selectedNode;
        this.selectedNode = selectedNode;
        propertyChangeSupport.firePropertyChange("selectedNode", oldSelectedNode, selectedNode);
    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.removePropertyChangeListener(l);
    }

    public String getSelectedNode() {
        return selectedNode;
    }

    // Set selected node to the root of the content systems as set above
    public void GoHome(ActionEvent actionEvent) {
        // Change the bean attribute of selectedNode to the root
        ValueExpression ve =
            AdfmfJavaUtilities.getValueExpression("#{pageFlowScope.DemoBean.selectedNode}", String.class);
        String selectedNode =
            String.valueOf(rootCollectionNode);
        ve.setValue(AdfmfJavaUtilities.getAdfELContext(), selectedNode);
    }

    // Set the current folder that we will query
    public void GetCollection(ActionEvent actionEvent) {
        ValueExpression ve =
            AdfmfJavaUtilities.getValueExpression("#{pageFlowScope.DemoBean.selectedNode}", String.class);
        String selectedNode = (String)ve.getValue(AdfmfJavaUtilities.getAdfELContext());
        ve.setValue(AdfmfJavaUtilities.getAdfELContext(), selectedNode);
    }

    // Call custom Javascript to inject an iFrame
    public void callFramedDocumentJS(ActionEvent actionEvent) {
        AdfmfContainerUtilities.invokeContainerJavaScriptFunction("DocB", "showFramedDocument",
                                                                  new Object[] { "" + docURL + "" });
    }

    // Set the URL for the web viewable version of a document / content item
    public void setDocURL(String docURL) {
        String oldDocURL = this.docURL;
        this.docURL = docURL;
        propertyChangeSupport.firePropertyChange("docURL", oldDocURL, docURL);
    }

    public String getDocURL() {
        return docURL;
    }

    public void setDocName(String docName) {
        this.docName = docName;
    }

    public String getDocName() {
        return docName;
    }
}

Custom Javascript to Open Iframe

For complete details of our custom Javascript that opens the iframe to our content check out our prior post ADF Mobile Custom Javascript – iFrame Injection.

Sample Application Download

ADF Mobile Development Resources

During this exercise the following resources proved extremely helpful.

15 Comments
  • angelohannes
    Reply
    November 23, 2012

    Thank you very much! This is an excellent video you posted.
    I came across this blog because I have trouble using the <amx:verbatim> tag, which, I thought, does have the exact purpose of embedding pure HTML markup in an amx page. I see, you used the <amx:verbatim> tag to in your DetailView.amx.
    Did you have problems, too? And if not, why did you decided to inject your markup that way?

    • John Brunswick
      Reply
      November 23, 2012

      @angelohannes Thanks for the kind words on the video!
       
      Regarding the amx:verbatim tag – you are correct in that it is used to embed HTML markup in an AMX page.  I found some challenges when 1. Trying to get the layout of the page to incorporate the Verbatim wrapped markup 2. Getting dynamic values within the Verbatim area based on what it being viewed 3. Having markup that the parser would not reject based on tag structure.
       
      I have used a variety of mobile technologies in the past (JQM & Sencha Touch), so I found it pretty natural to look at tweaking the DOM to include the dynamic markup based on what I could pass along to the JS function via the Bean.  I am sure there are some other avenues, I just happened to get this pattern to work in the scenario above.
       
      Hope that this explanation helps.  Good luck of you ADFM project!

      • angelohannes
        Reply
        November 26, 2012

        @John Brunswick  @angelohannes Thank you for your reply.
         
        Did you found any methods to debug your approach. E.g. seeing the javascript console, or the dom tree?

        • John Brunswick
          Reply
          December 5, 2012

          @angelohannes Apologies for the delay – just saw this now for some reason.  There are a few debugging options for live debug sessions.  I have not used them yet, but it appears like a pretty comprehensive approach.  Take a look at http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/debugging.htm for more details – sorry to not be of more help!
           
          Best,
          John

  • JRSim_UIX
    Reply
    February 4, 2013

    Thanks for pointing to Fishbowl’s Mobile Content Management app 🙂
     
    As well as our IOS App our Android App was released a couple weeks ago – https://play.google.com/store/apps/details?id=com.fishbowl.mobilelibrary

    • John Brunswick
      Reply
      February 4, 2013

      @JRSim_UIX Thanks John!  Definitely keep me posted on any other updates.  Would be more than happy to showcase any new versions / platforms.

  • ruchika
    Reply
    March 14, 2013

    Hi, please throw some light on calling a webservice from java code. how can we do that. Whatever methods I have tried don’t work. I have multiple inputs in my webservice and an array of outputs corresponding to that. I have tried AdfmfJavaUtilities.invokeDataControlMethod but without success. Please help

    • angelohannes
      Reply
      March 14, 2013

      @ruchika Maybe you want to look at this Blog Post of Shay Shmeltzer, where he discusses that. https://blogs.oracle.com/shay/entry/developing_with_oracle_adf_mobile
       
      There are also some new posts, also covering Web Services.

      • John Brunswick
        Reply
        March 14, 2013

        @angelohannes  @ruchika Thanks guys – yes – definitely check out Shay’s posts.  In general, if you can leverage the ADF Data Binding, that is the big benefit of using something like ADF Mobile.  So to leverage services some research around the ADF Data Binding capability in general will be a good start.  Shay’s videos are an excellent resource.

  • gokhalenr
    Reply
    March 14, 2014

    Hello John,

    Nice blog. we are trying to develop ADF mobile application where we need to include RIDC jar in mobile application itself instead of webservice . the issue is RIDC need jre1.6 while adf mobile supports Java 1.4 so when we deploy application on mobile it gives unsupported class error. can you suggest any workaround for this

    Nikhil

  • John Brunswick
    Reply
    March 14, 2014

    gokhalenr  I have not tried that, but would be cautious with trying to use the JAR functionality within the app without extensive testing.  I know that some others have created some more extensive samples, but am pretty sure that they also call out to remote services using traditional routes.  Hope that helps!

  • ravinmarch
    Reply
    May 1, 2014

    John Brunswick angelohannes  

    John,

    Thanks for the wonderful write up. 
    I have an issue while viewing the document, i get the login page of UCM.
    From your video, i do not see you logging in. Can you please clarify?

    Regards,
    Ravi

  • ravinmarch
    Reply
    May 1, 2014

    John,

    Thanks for the wonderful write up. 
    I have an issue while viewing the document, i get the login page of UCM.
    From your video, i do not see you logging in. Can you please clarify?

    Regards,
    Ravi

  • John Brunswick
    Reply
    May 1, 2014

    ravinmarch  Thanks – in my example I used documents that were publicly visible, so no authentication was required to open the documents.  I created this when this version of ADF Mobile was released, so take a look at some work from Fishbowl to see if there might be some newer sample code from partners.  Good luck!

  • ravinmarch
    Reply
    May 7, 2014

    John Brunswick ravinmarch  Thanks John!!!

Leave a comment