Wednesday, December 11, 2013

Issue creating Connection Pool for Oracle on Glassfish3


As part of ADF Essentials setup on Glassfish, you need to create JDBC Pool. This is documented on http://docs.oracle.com/middleware/1212/adf/ADFAG/ap_glassfish.htm#ADFAG20931.

First make sure that you copy ojdbc6.jar to your Glassfish servers's domain-home\lib folder.

C:\glassfish3\bin>asadmin
Use "exit" to exit and "help" for online help.
asadmin> create-jdbc-connection-pool --datasourceclassname oracle.jdbc.pool.OracleDataSource --restype javax.sql.DataSource --property user=user1:password=welcome1:url=jdbc:oracle:thin:@localhost:1521:XE SampleDSPool
remote failure: Invalid property syntax, missing property value: oracleInvalid property syntax, missing property value: oracle
Usage: create-jdbc-connection-pool [--datasourceclassname=datasourceclassname] [--restype=restype] [--steadypoolsize=8] [--maxpoolsize=32] [--maxwait=60000] [--poolresize=2] [--idletimeout=300] [--initsql=initsql] [--isolationlevel=isolationlevel] [--isisolationguaranteed=true] [--isconnectvalidatereq=false] [--validationmethod=table] [--validationtable=validationtable] [--failconnection=false] [--allownoncomponentcallers=false] [--nontransactionalconnections=false] [--validateatmostonceperiod=0] [--leaktimeout=0] [--leakreclaim=false] [--creationretryattempts=0] [--creationretryinterval=10] [--sqltracelisteners=sqltracelisteners] [--statementtimeout=-1] [--statementleaktimeout=0] [--statementleakreclaim=false] [--lazyconnectionenlistment=false] [--lazyconnectionassociation=false] [--associatewiththread=false] [--driverclassname=driverclassname] [--matchconnections=false] [--maxconnectionusagecount=0][--ping=false] [--pooling=true] [--statementcachesize=0] [--validationclassname=validationclassname] [--wrapjdbcobjects=true] [--description=description] [--property=property] jdbc_connection_pool_id
Command create-jdbc-connection-pool failed.

This kept failing for me, as it seems to parse URL for properties as URL has : character. Modifying the command as shown below resolved the issue. Notice URL is not specified as URL="jdbc\:oracle\:thin\:@localhost\:1521\:XE".

C:\glassfish3\bin>asadmin create-jdbc-connection-pool --datasourceclassname oracle.jdbc.pool.OracleDataSource --restype javax.sql.DataSource --property user=user1:password=welcome1:URL="jdbc\:oracle\:thin\:@localhost\:1521\:XE" SampleDSPool
JDBC connection pool SampleDSPool created successfully.
Command create-jdbc-connection-pool executed successfully.


Sunday, November 24, 2013

Getting Started with ADF Mobile

At Fusion Development User Group even in Milwaukee, there was a general question on Getting Started with ADF Mobile. I am sure Google can find all this, but here is quick blog on Getting Started with ADF Mobile.

Development Environment

  • Use JDeveloper 11.1.2.4 with ADF Mobile Extension
  • You must use Mac for iOS testing and development. iOS Simulator works fine for testing and debugging.
    • Enroll in iOS developer program.
  • Download and Install Android SDK for Android build and testing. 

Examples

Learning Videos

Blogs


Java Source for JDK classes in JDeveloper 12c

If you try to open standard Java class from JDK in JDeveloper 12c, you will notice that it does not open Source.


This happens as there is no JDK 7 source included in default installation. You can see this by using Tools - Manage Libraries menu. Select Java SE Definitions tab, you will notice there is no Source Path.


You can first download JDK 7 Source from http://sourceforge.net/projects/jdk7src/files/jdk7u9/2012-10-27/. Download src-jdk.zip file and place it in oracle_common/jdk folder as shown below.


Now go back to JDeveloper. Go to Java SE Definitions under Tools - Manage Libraries. Select 1.7.* definition under User (not under Extension), and add src-jdk.zip to Source Path. JDK definition under Extension is Read Only, but when you restart JDeveloper after this change, Source Path will be updated for Extension JDK as well.


Now restart JDeveloper. You will now see source for JDK 7 java classes.


Tuesday, October 8, 2013

Integrate Quartz with ADF

In this blog entry, I will explain how to use Quartz to execute Background Jobs, where Jobs will eventually execute ADF Application Module methods.

I will be using JDBC Store for Quartz, which will allow me to execute jobs in Cluster environment. In addition, I have also included a Job Listener that will update job execution status in database table, which will help integrate with External Scheduler systems. Many companies have Enterprise Schedulers that control Jobs across various systems. Most of the time, these Enterprise Schedulers would call Shell scripts, and even if they can invoke Web Services, it is better to setup Asynchronous execution to avoid time outs. This approach will also be useful if you don't have an Enterprise Scheduler, in which case Quartz can act as your master scheduler.

1. Install Quart Libraries (1.6.4) in JDeveloper
  • Download - "myextensionsV2.zip".
  • Unzip downloaded myextensionsV2.zip in c:\temp.
  • Using command prompt, go to c:\temp\myextensions.
  • First set JDEVELOPER11_INSTALL_HOME environment variable, which should point to your JDeveloper installation. For example, set JDEVELOPER11_INSTALL_HOME=c:\jdeveloper
  • You can now run setup.bat file to install Jersey Library in your JDeveloper installation.

2. Create Scheduler tables
  • Download quartz-base.sql and quartz-myextension.sql.
  • Create SCHEDULER user using welcome1 password.
  • Create Database Objects using quartz-base.sql and quartz-myextension.sql.
  • This will create necessary tables for Quartz and my extension table for Job Listener.
3. Run JDeveloper Application
  • Download - Example3.zip
  • Unzip Example3.zip and Open using JDeveloper (11.1.1.7.0)
  • Perform Make All using Build menu.
  • Run MyDummyServlet. This is just to start Embedded WebLogic Server.
  • As Server starts, it will also start Quartz Scheduler, which is configured by QuartzInitializerServlet in web.xml.
  • When application and scheduler is started, you will see a new row in SCHEDULER.MY_SCHEDULER_STATE table.
  • Run ExecuteJob.java. This will schedule a Job in database, which will be picked up by running Quartz Scheduler in Embedded WebLogic Server.
  • You will notice output message in console.
  • While job is running, monitor SCHEDULER.MY_JOB_LISTENER table, you will notice State column value will change as Job State changes from Executing to Complete.
4. Next Steps
  • You can create proper implementation of ExecuteJob.java. For example, 
    • supply Input parameters to Job, using JobDataMap.
    • Poll MY_JOB_LISTENER for Status of Job - complete or error.
    • Create Shell script wrapper, which can be executed by External Scheduler.
  • You can create generic implementation of AMInvokeJob, that can take Application Module Definition and Operation Name as input, to invoke any Application Module's method.

Saturday, August 10, 2013

Create REST WebServices using BC4J

JDeveloper 11.1.1.x and ADF does not provide much support for REST Services, but it does recognize JAX-RS annotations and help configure Jersey. Here are simple steps to create REST Service over ADF Business Components.

1. Create Application Structure
Create Generic Application. Delete generated Project. Add Model Project and Web Project (without Faces). Create Connection (hrdb) to HR Schema.

2. Generate Business Components and Prepare Service API
This is similar to what i did for SOAP Web Service Example.

3. Add dependency to Jersey & Jackson
Add Jersey and Jackson libraries to Web Project.
See my blog about Installing Jersey libraries for JDeveloper. Actually, i am just adding following jars to Project.
jackson-all-1.9.11.jar, asm-3.1.jar, jersey-bundle-1.17.1.jar


4. Create WebService POJO Class
Create POJO class with necessary API method(s). This example is not showing any exception handling, but you can throw Checked Exception to indicate Validation, Application or System type error situations to client.


5. Add annotations
5.1 Add @Path("/hrservice") annotation to HRWebService Java class. Import "javax.ws.rs.Path", when prompted by JDeveloper.

5.2 JDeveloper will provide a hint for you to configure web.xml. You will see a Yellow icon in line gutter next to @Path. Accept the hint and JDeveloper will configure web.xml for Jersey servlet.



5.3 Add "com.sun.jersey.api.json.POJOMappingFeature" init param for Jersey servlet in web.xml, value of this init param should be true. This will cause Jersey to use Jackson for generating JSON response. Default implementation (JAXB) has some issues, for example, it will return Object instead of Array if only one item is being returned in List.



5.4 Add GET annotation to getCountryList() method.



6. Add weblogic-application.xml
ADF libraries are included by adding shared library in weblogic-application.xml. This is automatically done if you create Fustion application, otherwise you can add it manually.


7. Test Web Service
Right click Web Service in Application Navigator and select Run or Debug.






Installing Jersey on JDeveloper 11.1.1.x

In order to create REST Services using JDeveloper, you will need to include Jersey jar files in your Projects. I guess you can create other implementations, but Jersey works just fine.

I will be using Jersey 1.17.1, which works great with JDeveloper 11.1.1.x. I have downloaded jersey-archive-1.17.1.zip and jersey-bundle-1.17.1.jar. Ideally you just need jersey-bundle-1.17.1.jar, but it appears that we also need to include asm-3.1.jar from jersey-archive-1.17.1.zip file.

You can just setup Jar files as dependencies on your Project, but it works best if you create a JDeveloper Library. You can install this library on your Developer machine as well as on your Build machine. 

Download - My Extensions Zip Archive

Unzip downloaded myextensions.zip in c:\temp. Using command prompt, go to c:\temp\myextensions. You can now run setup.bat file to install Jersey Library in your JDeveloper installation. You will need to set JDEVELOPER11_INSTALL_HOME environment variable, which should point to your JDeveloper installation.

You can open setup.bat to see what it will copy to your JDeveloper installation. You can obviously modify / extend this to install other types of Libraries.

Once you run setup.bat, start JDeveloper and see Library named My Jersey. (Tools - Manage Libraries).


Sunday, August 4, 2013

Create SOAP WebServices using BC4J

ADF Application Module can be enabled as Service Interface (SDO), but i take a different approach to this as shown below.

1. Create Application Structure
Create Generic Application. Delete generated Project. Add Model Project and Web Project (without Faces). Create Connection (hrdb) to HR Schema.

2. Generate Business Components and Prepare Service API
2.1 Generate ADF Business Components using JDevelolper Wizard. Create Application Module later, otherwise initial wizard adds many entries to Application Module's Data Model.
2.2 Create simple POJO for Country object.


2.3 Create service method to return all Country objects. Expose it to Client Interface.


Using Application module XML Editor, add this service method to Client Interface (Java tab).


3. Create Web Service POJO class
Create POJO class with necessary API method(s). This example is not showing any exception handling, but you can throw Checked Exception to indicate Validation, Application or System type error situations to client.

Alternatively, you can also start by creating WSDL file to represent your Web Service.


4. Generate SOAP Web Service from POJO
Generate Web Service using JDeveloper wizard. This generates SOAP Web Service only with JDeveloper 11.1.1.x, hopefully future versions of JDeveloper will allow generation of REST Services.






Note annotations added by Wizard.


5. Test Web Service
Right click Web Service in Application Navigator and select Run or Debug.


Why this approach?
1. This approach allows for flexibility in exception handling, as you can control types of exception thrown to client. Service Generation approach from Application Module throws Runtime Exceptions which is seen as SOAP Fault by client and it does not have any useful information.
2. You may want to control WSDL and / or Schema to confirm to your Enterprise Standards, which is possible only when using this approach.
3. This approach is little bit clean, as Web Service and BC4J code is organized in separate projects.

And, It is not at all difficult to generate Web Service from POJO with available Wizards.

Sunday, June 30, 2013

Use of Date with ADF

Date creates many confusion & bugs in our applications, some of which are only found when Day Light Savings time changes. :)
There is fundamental issue with how we talk about Date. For example, my date is in Central Time or for this Location my Date is in Eastern Time. As we all know, Date is milliseconds representing GMT time & String value we see in Debugger or Logs is just String representation of Date with respect to some TimeZone.
Here is what i recommend for Date usage with ADF, some of which can very well apply to other frameworks as well.

1. Don't offset date value for Persistence


JDBC driver will transform value of Date is Server's Default TimeZone for storing in Table Column. At times, we try to offset value of Date, so that when JDBC Driver creates String representation using Server's Default TimeZone, it looks like GMT for example. This is clever, but not a good idea.

This approach can cause issues with Queries. It will also not represent values correctly on screen components. You can workaround these issues, but that's extra work that can be avoided, by accepting the fact that Date will be stored in Server's Default TimeZone.

2. Do not specify Date Format on Control Hints for Entity or View Object attributes


ADF does a good job of providing Control Hints that can be set on Business Components, but in this case I would recommend not setting any Format for Date on Entity and View Object. I have seen issues with Control Hints related to Date Format and more importantly it makes sense to control this based on User's Preferences / Locale.


3. Create Session Scope variables for TimeZone & Date Format


Using Phase Listener, create Session Scope values for TimeZone and various Date & Time formats. You can read this values from User's Preference or derive it using any other data store.

These can be used in UI pages with af:convertDateTime as shown below.

 

4. Specify TimeZone in trinidad-config.xml

If you set value of time-zone in trinidad-config.xml, it will apply to all Date components for display and input processing.


5. Specify Pattern on af:date Specify different TimeZone if necessary on af:date

If you want to display particular Date value in a different TimeZone, you can indicate that on af:convertDateTime. For example, Delivery Date would make sense to be displayed in TimeZone of Delivery Location.


Saturday, June 22, 2013

af:poll not working

ADF Faces provides poll component, it's description & sample use cases are documented on Tag Documentation as shown below.
The poll component delivers PollEvents to the server at fixed intervals. This can be used either for steady updates, or to deliver a heartbeat to keep a user logged in, or to warn a user about to be logged out (for some examples).
One classic use of Poll component would be to keep User Session active as long as browser window is open. In this case, you will set Poll Interval (interval) and dummy pollListener. Poll Listener can be empty method, it does not have to do anything. Poll Interval should be less than HTTP Session Timeout. HTTP Session Timeout is setup in web.xml.

Such use of Poll component fails to keep User Session active, after upgrading from 11.1.1.3. This is due to new attribute timeout for af:poll, value for which defaults to 10 minutes (This property is added with 11.1.1.4). So if user does not perform any activity on Keyboard or Mouse for 10 minutes, Poll component will stop delivering any Poll Events. If you are using af:poll to keep User Session (by sending regular heartbeat) active, add timeout property to af:poll with very high value to avoid stopping Poll Events.

Sunday, June 16, 2013

How to define List of Values for View Object attribute

This is very powerful feature of ADF and it often goes unnoticed. You can define a List of Values for View Object attribute including component types that you want to use by default. Once this setup is done, when you Drop View Object on your page, it will create List components instead of simple text box.

Let's define Department List of Values for "DepartmentId" attribute of EmployeeVO. We have "EmployeeVO" (Default VO for Employee table) and "DeparmentsLOVVO" (has Id & Name for all Deparments).

First open EmployeeVO and Select DepartmentId attribute.

Expand List of Values:DepartmentId and click Green Plus icon. You will see "Create List of Values" dialog like one shown below. 


This is not very straightforward User Interface. Now you can select where your List Data is coming from in "List Data Source:", if you don't have one, click Green Plus icon to create one, see screen shot below.

Make sure that you name your view accessor appropriately. See i am using "VA" suffix.


Select "List Attribute" now. This is the value from your List Data Source that will be stored in your View Object attribute when User performs selection on UI.


You can use different value to display on your List component than what is being stored in your Attribute. This is done from UI Hints tab.


You are almost done. Go to EmployeeVO's View Accessor tab. Select your View Accessor and examine "Row Level Bind Values" property. If Rows in your EmployeeVO can use different Department List than this value should be true. (blank also means true). Easiest way to figure this out is if you have Bind Parameters on your List View Object (DepartmentLOVVO) and that is controlled by another attribute in your View Object (EmployeeVO). For example, if your View Object attribute is State and it's list changes based on Country attribute in that same View Object.

You must set this value to "false", if list is static for all Rows in your View Object, Otherwise you will see Memory Leak and Performance issues.

"Row Level Bind Values" is sometimes cleared by JDeveloper, which can lead to issues. This is something you want to create Audit Rules to make sure that your Build Process catches it. 

Define Primary Keys for all View and Entity Objects

When working with ADF, it is best to AVOID ISSUES by doing the right thing. Now that is broad statement, but i will try to post my learning's on this Blog.
Each ADF View & Entity Objects must have Primary Key.
ADF Business Components will generally have Primary Key defined, when they are generated using "Business Components from Tables" wizard. But in other cases when you have Read Only or Transient View Objects, they will not have Primary Key by default.

For example, see following steps to create List of Values (SQL based) View Object.



Note that DepartmentId is not selected as Primary Key. Select "Key Attribute" check box for all attributes that are part of Primary Key for this particular View Object.


Now you can see DepartmentId is selected as Primary Key.


ADF uses Primary Key for selection process, so if you did not have proper primary key, you will see weird behavior in Table Selection.

Tuesday, June 11, 2013

Use Non Schema User for ADF Business Components

ADF Model project is configured with Database Connection to generate Business Components from Tables and/or Views. Generated objects are Not Qualified with Schema name if you use Schema User for Connection Configuration. This can cause failures like "Table or View does not exist.", when application executes with a Different User. You can always resolve such errors by creating Synonyms. 

You have two options:
  1. Use Non Schema User for JDeveloper Connection Configuration & no additional work needed when Sharing Code with other Applications.
  2. Use Schema User for JDeveloper Connection Configuration. You will have to create Public Synonyms.
I recommend Option #1 as it is very simple and use of Option #2 can lead to confusion due to use of Synonyms. And this only applies to Code Generation, if you write SQL, you should implement similar option. 

Option 1 : Using Non Schema User for Database Connection



Option 2 : Using Schema User for Database Connection