Friday, November 30, 2012

Oracle Java and Database Cloud Services in Action


Yesterday the long awaited  Oracle Cloud became reality (at least for me)! Thanks Oracle! Of course I could not wait any longer and had to do a test drive with the Oracle Database and Java Cloud Services. In order to start we need the following

Getting started
Once you confirm your activation link for the trial request you will receive an email with Service Details for
  • Identity Domain (which actually is a logical group for associated Users and Cloud Services)
  • Oracle Database Cloud Service
  • Oracle Java Cloud Service
  • Domain FTPs Account Details
In the mail there also will be a temporary password which must be changed after first login at the Identity Console. One thing really overwhelmed me is the fact that for every service you get dedicated user credentials. So there is a lot of stuff that is to be handled.

Identity Domain / Console
The Identity Domain actually is a logical group for associated Users and Cloud Services that is managed by the Identity Domain Administrator. The Identity Console is a web based application for 
  • Manage  User Profile
  • Create / Delete Users, Reset Passwords
  • Create / Delete Roles, Assign to Users
The Identiy Console is build with ADF. It looks like that


Oracle Database Cloud Service 
The Oracle Database Cloud Service runs Oracle DB 11gR2 and is managed by Apex 4.1.1.00.23. So logically no ADF here. Imagine you are running Oracle XE. Same here.

RESTful Services (by Application Express Listener)
RESTful services are created inside Apex and are delivered right from the Database through the Apex Listener

The defined RESTful Services can be tested right from the browser:

As you can imagine this allows pretty rapid development of RESTful Services! Beside JSON, CSV Format is supported. No XML!


As a sample DB application the following Apex App is installed and by default to demo key features of Oracle Apex! Further Apex applications can be easily deployed from the apex Workspace.


DB Export
In order to export Database strucure + data it is possible to trigger a data pump job with a single Mouse Click. After the job is completed the Dumpfile can be grabbed through SFTP from the /download user directory. The created files are automatically cleaned up after about 2 days. So do not try to archive your data here.


My test worked well without any trouble! The download speed was acceptable to although I did not download Gigs of data.


Access DB Schema
Now let us come to the  interesting part. How can we access the DB Schema from - e.g. SQLDeveloper or JDeveloper. In this case I will demo it from the new JDeveloper 11.1.1.6 (Build 6229) 

In order to access the Database Cloud service from the IDE we need a so called "Cloud Connection User" to be created in the database service console (Apex) with the SQL Developer Group as stated in the JDeveloper context help. This can can be easily done through the Apex Admin Tools (Manage users and groups). I won't go into further details here.

Now it is possible to create the connection from JDeveloper/SQLDeveloper

Enter your service details


and we are up and running, being able to see the structure and contents of the cloud database instance. 

Access for example the table 'DEPT' and browse the data.
(The Tables EMP and DEPT are included in the cloud db schema)

The interesting part here is that it is not possible to change any database objects.

Deploying DB Objects is only possible through the newly introduced "Database Cart" which is accessible from "View > Database > Database Cart". 

That is a very new concept which needs a separate focus. More on that in a follow up post (Deploying Database Objects to Oracle Cloud using JDeveloper). Follow me on twitter to get updated in time (@multikoop)

Oracle Java Cloud Service Control
To monitor, deploy/undeploy start/stop Java and ADF Applications. It looks pretty simple and easy to use: Performance, Data Sources, Applications. Everything you need to get started.

This control is a subset of Oracle Enterprise Manager Cloud Control 12cR2 (12.1.0.2) as you can see in the about page.

In one of the next posts I am going to show how to "Deploying ADF Applications into the Oracle Cloud". Stay tuned.

Conclusion

In its current stage Oracle Cloud is promising Cloud Foundation for PaaS and SaaS. It includes
  • Identity Management / WebBased Identity Console (ADF Application)
  • Java Cloud Service Control to Monitor and Deploy your Java Applications (ADF Application)
  • Apex Control to Administer and Monitor Apex DB Applications and Cloud Connection Users
  • IDE Integration in JDeveloper 11.1.1.6 (Build 6229)
  • Oracle Cloud Java SDK Command Line Interface
  • IDE Integration in Oracle Enterprise Pack for Eclipse.
  • IDE Integration in Netbeans is on its way....
References

Start your cloud experience now! Goto http://cloud.oracle.com

Sunday, November 4, 2012

ADF: Smart Input Date Client Converter


Environment
  • Tested with JDeveloper / ADF 11.1.2.3
  • (Should also work for 11.1.1.x)
Use Case

To improve the User Experience in heavy data entry ADF applications for "extreme keyboard users" it would be great to have the ability to enter dates by some typical conventions, e.g.

  • Type t or T or today, tab out the input field and get the current date: 2012-11-04
  • Type +7, tab out the input field and get the current date +7 days: 2012-11-11
  • Type -7, tab out the input field and get the current date -7 days: 2012-10-28
The following use cases shows the +16 feature entered on 2012-11-04

How to do it

We are going to implement a custom client converter to get the desired result. The default functionality will be inherited from the given trinidad org.apache.myfaces.trinidadinternal.convert.DateTimeConverter since we want to keep the default conversion behavior for a given pattern. 

The server side implementation is quite easy. The only thing we override is the getClientConversion(..) and getClientLibrarySource(..) methods which are part of the org.apache.myfaces.trinidad.convert.ClientConverter interface.

The most interesting part is to wrap the default client converter implementation and put it into our own client javascript converter. The default date pattern can be set in the constructor.

The javascript Converter version uses the given default converter as a delegate and just implements to handle the special cases.

/resources/js/smartdate.converter.js

/**
 * Custom Client-Converter for smart date entry
 *
 * Copyright 2012 - enpit consulting OHG, www.enpit.de
 */


function EnpitSmartDateTimeConverter(trDateTimeConverter){
    this._trDateTimeConverter = trDateTimeConverter;
}

EnpitSmartDateTimeConverter.prototype = new TrConverter();


EnpitSmartDateTimeConverter.prototype.getAsObject = function(
  parseString,
  label){  

      try {
      if( parseString == "t" || parseString == "T" || parseString == "today"){
          return new Date();    
      }

      if( this._startsWith(parseString, "+") || this._startsWith(parseString, "-")){
          if(parseString.length == 1){
              // delegate to TrDateTimeConverter
              return this._trDateTimeConverter.getAsObject(parseString,label);
          }
          var _parsedDate = new Date();
          var _parseDays = parseInt(parseString.substring(1,parseString.length));
          var _millis =  _parseDays*86400000;
          if(this._startsWith(parseString, "-")){
            _millis = _millis*-1; 
          }
          _parsedDate.setMilliseconds( _parsedDate.getMilliseconds() + _millis );
          return _parsedDate;
      }

      } catch (e){
          // delegate to TrDateTimeConverter
          return this._trDateTimeConverter.getAsObject(parseString,label);
      }

    // delegate to TrDateTimeConverter
    return this._trDateTimeConverter.getAsObject(parseString,label);
}


EnpitSmartDateTimeConverter.prototype.getAsString = function( formatTime ){
    return this._trDateTimeConverter.getAsString(formatTime );
}

EnpitSmartDateTimeConverter.prototype.getFormatHint = function() {
    return this._trDateTimeConverter.getFormatHint();
}

EnpitSmartDateTimeConverter.prototype.setDiffInMins = function( offset )
{
    this._trDateTimeConverter.setDiffInMins(offset);
}

EnpitSmartDateTimeConverter.prototype.getDiffInMins = function()
{
  return this._trDateTimeConverter.getDiffInMins();
}

EnpitSmartDateTimeConverter.prototype.getLocaleSymbols = function()
{
  return this._trDateTimeConverter.getLocaleSymbols();
}

EnpitSmartDateTimeConverter.prototype._startsWith = function(
  value,
  prefix
  )
{
    if(value == null){
        return false;
    }
    return (value.indexOf(prefix) == 0);
}

Register the custom converter in faces-config.xml





Enter ID: enpit.faces.SmartDate
Enter Class: enpit.faces.converter.SmartDateConverter

Now we are able to use the smart DateConverter on our inputDate components, all declaratively with IDE support.

Just drag and drop the f:converter from the component palette onto the desired inputDate component 

so that it looks like

Let users enjoy the smart date input. They will love it!

Conclusion / Summary
  • Implement Custom Server Side Faces Converter
  • Implement JavaScript Client Converter
  • Register Converter in faces-config.xml
  • Use Converter from Component Palette

Further Information

Download Sample