Thursday, March 6, 2014

Quick Tip: Best Way to Loop Through View Object Rows Programatically

You may have noticed there are multiple ways to do one task in ADF in many situations. Especially once you get involved on the Java side of ADF. While there are multiple ways to do something, it doesnt mean all of them are necessarily the best.

One question, which can be fairly common among new ADF developers, whats the best way to programatically loop through a View object's rows without affecting the View Object's root RowSetIterator? After all, you have what seems to be too many ways to do this:
  • ViewObjectImpl.getAllRowsInRange, returning Row[]
  • ViewObjectImpl.getRowSet, returning RowSet
  • ViewObjectImpl.getRowSetIterator, returning RowSetIterator
  • ViewObjectImpl.createRowSetIterator, returning RowSetIterator
While all ways could work per the above, only one is the best, ViewObjectImpl.createRowSetIterator. It delivers the most consistent results and it won't affect the currently selected row of the View Object.

Here's how we use it:

  1. Create RowSetIterator from your View Object class: ViewObjectImpl.createRowSetIterator()
  2. Reset the RowSetIterator - just in case
  3. Loop through the iterator: while(RowSetIterator.hasNext()) { .. }
  4. After your loop is finished, close the RowSetIterator: RowSetIterator.closeRowSetIterator()

See this example, where i look up a view object row by attribute value:

public Row getRowByAttribute(ViewObjectImpl vo, String attributeName, Object attributeValue) {
RowSetIterator rsi = vo.createRowSetIterator(null);
rsi.reset();
Row currRow=null;
while(rsi.hasNext()) {
currRow = rsi.next();
if (currRow.getAttribute(attributeName).equals(attributeValue)) {
rsi.closeRowSetIterator();
return currRow;
}               
}
rsi.closeRowSetIterator();
return null;        
}

Happy JDeveloping!

A Better ADF Mobile Development Experience on Android

Silly me, i forgot to publish this post that i wrote back in August :)

ADF Mobile developers will relate to this when I say, the Android Emulator is the definition of "painful". A day in a typical life of an ADF Mobile developer working with Google's Android Emulator is:
Develop an app in JDeveloper. Start the deploy process. 7 minutes later the app is deployed - unless you use the release mode trick i showed you. Next, go to your emulator start the app launch process. And 10 minutes later you'll get to see your app... as you later realize you forgot to write a critical line of code - and you die a little bit inside.

Unless you intend on playing a game of cricket or grill hotdogs and hamburgers for your office during each deployment cycle, you're probably itching to get your hands on a more efficient emulator. This is your answer.

AndroVM or what it will later be called, Genymotion. Genymotion will be a commercialized version of AndroVM. AndroVM is a product which runs on Oracle's virtualization software, VirtualBox. While, this is not supported by ADF Mobile and has some shortcomings, as reported by ADF Product Manager Chris Muir, it definitely eases the pain of quickly testing code you write for your ADF Mobile application.   As a AndroVM user, I can testify that apps run wicked fast compared to the emulator. Below are steps on how you can get started with AndroVM and ADF Mobile.


  1. Download and Install Virtual Box. I installed version, 4.2.12.
    Download Link: https://www.virtualbox.org/wiki/Downloads
  2. Consult the AndroVM Documentation and download an AndroVM with gapps & houdini & flash.
    vbox86p VMs are built for Phones, 480x800 default resolution
    vbox86t VMs are built for tablets, 1024x600 default resolution
    vbox86tp VMs are tablets with phone capabilities, 1024x600 default resolution.
  3. Once the AndroVM is downloaded, double click on it to import your AndroVM into VirtualBox. I accept all the defaults.
  4. Before you start AndroVM, you need to update the Network Settings to allow the Android SDK to connect to the VM. Select your VM, click on Settings > Network > Adapter 1. Set the Attached To field to Host-only Adapter. Click OK.


  5. Startup the AndroVM
  6. Allow approximately a minute for Android to boot up.
  7. For the first time starting up Android, you'll be prompted to specify your android settings, as you normally would during an initial Android boot process.When you complete the first time configuration settings, your screen should look like the screen below. From here, you're ready to deploy apps onto AndroVM!
  8. From there you're ready to deploy apps onto the AndroVM!






Wednesday, August 7, 2013

Use WLST For WebLogic Startup and Shutdown Scripts

There are multiple ways to have an automated WebLogic Server startup process for your servers. You can have a process the run the startWebLogic.cmd/sh and startManagedWebLogic.cmd/sh scripts, create a semi-Windows Service to start WebLogic, and you could configure Node Manager to automatically startup servers when Node Manager is first being started. However, there are significant drawbacks to all of these methods. The most reliable method is using WLST to start WebLogic via Node Manager.

Firstly, why use it? You can start your WebLogic servers in a proper order, waiting for one to start after the next. Since WebLogic provides a great Pytyhon API, i find it is the most reliable method for starting the servers. However, the most important reason is when you use WLST to start your servers via Node Manager, you can utilize a great feature of Node Manager called "Crash Recovery". If your WebLogic Servers crash or if the physical Server loses power, Node Manager will automatically boot back up.

After all, if theres one more thing to make WebLogic more reliable, you have to do it!

I found that theres plenty of articles on using WLST to start servers, however most of them had invalid python syntax and WLST commands! This solution can apply to WebLogic Servers that utilize most Fusion Middleware Technologies as well: ADF Servers, 11g Forms/Reports, Oracle Access Manager, and the list goes on...

My example focuses on a UNIX based solution but you can adapt it to use batch pretty easily.  Enough blabbering, lets get started!

Part 1: WebLogic Preparations


WebLogic needs a few properties initialized before we can consider using WLST Scripting. First we initialize the weblogic username/password credentials required by Node Manager. Next, we can generate an encrypted username and password store-file to avoid hardcoding the weblogic username/password into the WLST scripts. Next, we enroll the Node Manager with the WebLogic Domain - to ensure proper Node Manager operations. Lastly, we update the Node Manager configuration file to enable Crash Recovery and to use the startWebLogic.sh/cmd script when starting servers.

  1. Make sure AdminServer is running.
  2. Login to the Admin Console.
  3. Enter Lock & Edit mode.
  4. Click on your Domain Name from the Domain Structure Panel. For example my domain name is ReportsDomain.
  5. Click on the Security tab.
  6. Expand the Advanced Settings panel and fill out your weblogic username/password credentials in the NodeManager Username and NodeManager Password fields
  7. Click Save and Activate Changes.
  8. Go to Environment > Servers
  9. Enter Lock & Edit mode.
  10. For each server: click on the server, then open the sub tab Server Start
  11. For User Name and Password fields, specify your weblogic username and password respectively.
  12. Once you've updated all your server's with this change, Activate Changes.
  13. Make sure your WebLogic Servers are configured with a Machine. Respectively, makes sure the machine element has the proper Node Manager port configurations.
  14. Open a command-line session to your server where WebLogic is installed.
  15. Run the $DOMAIN_HOME/bin/setDomainEnv.sh script to set your command line's shell/batch environment
  16. Open WLST via the command: java weblogic.WLST
  17. Run the command similar to: connect('weblogic_username','weblogic_password','t3://hostname:7001')
  18. Run the command to enroll the domain with Node Manager: nmEnroll(domainDir='<WebLogic_Domain_Home>',nmHome='<Node_Manager_Home>')
    nmHome should be <WebLogic_Server_Home>/common/nodemanager
  19. Run the command similar to the following to generate an encrypted username and password credential file:
    storeUserConfig('<WebLogic_Domain_Home>/userCred','<WebLogic_Domain_Home>/passCred')
  20. To exit, run the command: exit()
  21. Go to the Node Manager Home directory and open nodemanager.properties
  22. Update the values:
    StartScriptEnabled=true
    CrashRecoveryEnabled=true
  23. Shutdown Node Manager and all WebLogic Servers


Part 2: Set OS User Profile

The WLST Scripts depend on some environment variables - to make them more configurable for mass server deployment. Set the following environment variables in your OS user's environment profile:

  • DOMAIN_HOME => Set this to the WebLogic Domain directory. For example /opt/oracle/middleware/user_projects/domains/ReportsDomain
  • MW_HOME => Set this to the middleware home directory. For example, /opt/oracle/middleware
  • NM_PORT => Set this to the port your Node Manager runs on. By default it runs on 5556.
  • DOMAIN_NAME => Set this to the logical name of your WebLogic Domain. For example, ReportsDomain
  • HOSTNAME => If not already set, set this to the hostname of the physical machine.


Part 3: Create and Run Scripts

This is the easiest part! Simply call the WebLogic scripts from shell or batch environment.


1.) Create a start all WLST Script on the server: wlst_startall.py

print '==================================='
print 'Starting WebLogic Domain ...'
print '==================================='

#Pull All Script configuration values from OS user's environment variables
import os
wlsDomainDir = os.getenv('DOMAIN_HOME')
mwHomeDir = os.getenv('MW_HOME')
nmPort=os.getenv('NM_PORT')
wlsDomainName=os.getenv('DOMAIN_NAME')
hostName=os.getenv('HOSTNAME')

#More Script Configuration Values - However, these shouldnt have to be touched
nmHomeDir=mwHomeDir + '/wlserver_10.3/common/nodemanager'
nmPropFile=nmHomeDir + '/nodemanager.properties'
userCred = wlsDomainDir + '/userCred'
passCred = wlsDomainDir + '/passCred'

# Connect to Node Manager, if it is running. Otherwise Start it up. This will take a minute or so.
#... instead of using hard coded username/passwords, we'll use an encrypted file, hence the "configFile" parameters
print '==================================='
print 'Connecting to Node Manager ...'
print '==================================='
try:
nmConnect(userConfigFile=userCred,userKeyFile=passCred,host=hostName,port=nmPort,domainName=wlsDomainName,domainDir=wlsDomainDir)
except:
startNodeManager(NodeManagerHome=nmHomeDir,PropertiesFile=nmPropFile)
nmConnect(userConfigFile=userCred,userKeyFile=passCred,host=hostName,port=nmPort,domainName=wlsDomainName,domainDir=wlsDomainDir)
# Now that we're connected to Node Manager, we can startup the servers.
# Start Admin Server
print '==================================='
print 'Starting AdminServer ...'
print '==================================='
nmStart('AdminServer')

# Start Managed Server - ms_adf_1
print '==================================='
print 'Starting ms_adf_1 ...'
print '==================================='
nmStart('ms_adf_1')

#ADD MORE SERVERS HERE!!!

#Startup and operations are complete, disconnect from Node Manager
nmDisconnect()

print '==================================='
print 'End of Startup Script'
print '==================================='


2. ) Create a stop all WLST Script on the server: wlst_stopall.py

print '==================================='
print 'Stopping WebLogic Domain ...'
print '==================================='

#Pull All Script configuration values from OS user's environment variables
import os
wlsDomainDir = os.getenv('DOMAIN_HOME')
mwHomeDir = os.getenv('MW_HOME')
nmPort=os.getenv('NM_PORT')
wlsDomainName=os.getenv('DOMAIN_NAME')
hostName=os.getenv('HOSTNAME')

#More Script Configuration Values - However, these shouldnt have to be touched
nmHomeDir=mwHomeDir + '/wlserver_10.3/common/nodemanager'
nmPropFile=nmHomeDir + '/nodemanager.properties'
userCred = wlsDomainDir + '/userCred'
passCred = wlsDomainDir + '/passCred'

print '==================================='
print 'Connecting to Node Manager ...'
print '==================================='
try:
nmConnect(userConfigFile=userCred,userKeyFile=passCred,host=hostName,port=nmPort,domainName=wlsDomainName,domainDir=wlsDomainDir)
except:
startNodeManager(NodeManagerHome=nmHomeDir,PropertiesFile=nmPropFile)
nmConnect(userConfigFile=userCred,userKeyFile=passCred,host=hostName,port=nmPort,domainName=wlsDomainName,domainDir=wlsDomainDir)

print '==================================='
print 'Stopping ms_adf_1 ...'
print '==================================='
try:
nmKill('ms_adf_1')
except:
print 'Error stopping ms_adf_1, it may already be down'

#ADD MORE SERVERS HERE!!!
print '==================================='
print 'Stopping AdminServer ...'
print '==================================='
try:
nmKill('AdminServer')
except: 
print 'Error stopping AdminServer, it may already be down'

nmDisconnect()
exit()

print '==================================='
print 'End of Stop Script'
print '==================================='


3.) Configure a shell script (or a batch version of this) to run the startall script:

# ADF - swat_domain - environment variables - required for WLST
. $DOMAIN_HOME/bin/setDomainEnv.sh
# ADF - swat_domain - start all servers via WLST
java weblogic.WLST /location/of/wlst_startall.py


4.) Configure a shell script (or batch version of this) to run the stopall script:

# ADF - swat_domain - environment variables - required for WLST
. $DOMAIN_HOME/bin/setDomainEnv.sh
# ADF - swat_domain - start all servers via WLST
java weblogic.WLST /location/of/wlst_stopall.py


5.) Configure your server to run the shell/batch scripts at startup and shutdown. After that you are good to go!


I'll update this later with some more helpful methods, but for now, this should be helpful!


Monday, July 8, 2013

Oracle Case Study Published!

I have been quite busy with customer work and preparing for KScope 13 presentations over the past month. I have some good/unique use cases being written for some future blog posts - stay tuned!

The biggest news to report is I have a case study published with Oracle based on my work with DTE Energy! The case study involves integrating Oracle Forms with ADF. It's one of the many solutions that ADF has to offer for organizations.  For more information, read the case study.

http://www.oracle.com/technetwork/developer-tools/jdev/dte-casestudy-1961637.pdf


Thursday, May 30, 2013

Setup ADF Mobile on Android For Release Mode


Props go to Shay and Joe with the ADF Team at Oracle for this post.

If you have begun developing mobile apps with ADF Mobile on Windows, you have already begun deploying onto the Android Emulator and/or a physical Android Device on hand. To speed up the deployment process and overall performance of the ADF Mobile app, deploy your apps using Release Mode. Overall, you'll never get the android emulator to run like a physical device or like the iOS emulator, but you can improve the performance of apps by deploying them in Release Mode.

Below are steps to get your Android Apps running in Release mode (developed on a Windows PC). Essentially, you'll be creating a self-signed certificate with Java's keytool command and deploying apps based on your self-signed certificate.


  1. Open your command-line utility on Windows.
  2. Add the %JDK_Home%/bin directory to the front of your PATH environment variable.
    Note: the JDK Home should be the JDK Home which your JDeveloper is using.
  3. cd to a directory where you want store your self-signed certificate. I put it in the JDeveloper Home, for example C:\Oracle\JDeveloper
  4. Enter the following command to generate a self-signed certificate:
    keytool -genkey -v -keystore %Keystore_Name%.keystore -alias %Alias_Name% -keyalg RSA -keysize 2048 -validity 10000

    Replace %keystore_name% with the a

    ctual filename that you want to specify for the keystore
    Replace %Alias_Name%  with the alias name you want to specify. Since it's a self-signed certificate, you can name this whatever you want.
  5. You'll be prompted to specify keystore passwords and additional certificate fields. When you're prompted to enter an alias-key password, just hit enter to have the alias-key password setup to be the same as your keystore password (It keeps things simple).
    See the example below.

  6. Open your JDeveloper. Go to Tools > Preferences. Go to the ADF Mobile > Platforms configuration screen. Click on the Release Tab. Make the following configurations:
    Keystore Location: Specify your keystore file's location in Keystore
    Keystore Password: Specify your password
    Key Alias: Specify your key-alias
    Key Password: If you hit enter when prompted to enter a alias-key password and didnt enter any values, use the Keystore Password value. Otherwise, enter what you put for hte alias-key password.

  7. Go to your Mobile Application's Deployment Profile Properties window. Click on Android Options. Switch Build Mode from Debug to Release. Click OK to apply your changes.

  8. Deploy your app!

This concludes the end of another post. Keep ADF'ing!

Thursday, May 16, 2013

JDeveloper and Android SDK Incompatibility

While writing a quick test ADF Mobile app to verify a new training pc, I ran into an ADF Mobile deployment error below:

Cannot run program "... platform-tools\aapt"
CreateProcess error=2, The system cannot find the file specified.



This started happening because Android SDK Tools was updated from Rev. 21.1 to Rev 22. 


What revision 22 did was it moved aapt.exe to a different directory. The catch is that you can't configure or tell JDeveloper where to find this. 

To fix the issue, I took my SDK version back to Rev. 21.1, by extracting the Rev 21.1 zip and using that one. I did have to re-install/load the Android API, but 10 minutes and i was back in business. However, if you want use Rev 22, copy the contents of %SDK_Home%/build-tools/android-4.2.2 to %SDK_Home%/platform-tools. The only downside of this, is that Android SDK won't be able to maintain/update the platform-tools section. Which is why i'm using Rev 21.1 - theres nothing significant that you're missing by sticking with Rev. 21.1 vs Rev. 22.

Until Oracle changes how JDeveloper can find these libraries, you can use this workaround!

Update (05/21/2013): Per Chris Muir, ADF Product Manager, this issue has been officially logged at Oracle as a bug 168376554. They're working on it!
Source: https://blogs.oracle.com/onesizedoesntfitall/entry/adf_mobile_deploying_to_android





Silly JDeveloper - Android SDK Location Change

I was briefly tricked by this for a few minutes. And there's bound to be at least one other person out there whom will get tricked as well. This is for you :)

It appears Android made a slight change in their file structure. As a result, it sort of tricks JDeveloper and otherwise you as the developer, when its time to configure your Android SDK settings.

When selecting "Android SDK Location" under "Preferences > ADF Mobile > Platforms > Android", you are asked to select "%Root_Drive%/Android/android-sdk" for the location, like for example "D:\Android\android-sdk".

For some of you, selecting the suggested path by JDeveloper, you'll be greeted with an error message "Unable to locate Android SDK in the specified location %some_path%. Do you want to use the specified Android SDK location anyway?"




This is because, I had to select the "Android/android-sdk/sdk" directory, instead of "Android/android-sdk", as shown below.



Selecting the proper SDK location, lets you continue error free :)

Have fun ADF Developers!