Tuesday, October 30, 2012

ADF Mobile - Login Functionality

This post will be about new Oracle product - ADF Mobile. While ADF Mobile is deployed as native application, ADF Mobile Browser option is available as well - it allows to build lightweight ADF UI pages and host them on central server (check my previous post from 2011 about ADF Mobile Browser - iPhone Web Application Development With ADF Mobile Browser). New ADF Mobile approach with native deployment is cool when you want to access phone functionality (camera, email, sms and etc.), also when you want to build mobile applications with advanced UI. Same time ADF Mobile Browser remains very important for enterprise customers, because it simplifies development, deployment and maintenance procedure. If you want to expose simple worklist with approval/rejection to mobile interface, it would work just fine with ADF Mobile Browser approach (as per blog post above).

Today I will talk about new ADF Mobile and about Login functionality implementation (read more about it from ADF Mobile developer guide - 17.3 Introduction to Authentication). I will go step by step and describe how sample application is implemented - adfmobilelogin.zip. This archive contains two applications:

1. ADFBasicAuthApp - typical ADF application with basic ADF security authentication enabled. This application will be used as authentication server

2. ADFMobileSecuredApp - ADF Mobile application, with deployment profile for iOS simulator. Implemented secured home page and contains configuration for login page

Firstly I will describe ADFBasicAuthApp, this application contains single ADF page and is enabled with standard ADF Security - ADF Authentication option:

jazn-data.xml contains one registered user (we will test ADF Mobile login with this user) - redsam:

Page - index.jsf, is granted with authenticated access:

Application is deployed on the server and is accessible through URL:

You can see that URL is pointing to our index page. We will use the same URL for ADF Mobile Login functionality configuration. ADF Mobile is authenticating against remote authentication server (our ADF application with basic ADF Authentication) - username/password is passed from ADF Mobile Login page to access protected URL. If access is successful - user is allowed to access ADF Mobile application as well.

We move now to the second part - ADFMobileSecuredApp application. This one is quite basic ADF Mobile application, it contains single ADF Task Flow and page:

There is one feature defined, it is mapped with the ADF Task Flow (it renders home.amx page):

This feature is configured with remote credential authentication (authentication is done with remote secured application - ADFBasicAuthApp application enabled with basic ADF Authentication):

Login page behavior is configured in adfmf-application.xml file. ADF Mobile offers default login page, there is no need to build it (although you can build custom login page also, if you need it) - keep Default option:

We have only one feature, it is listed in Authentication and Access Control section - com.redsamurai.home. We should define Login Server Connection for this feature and point to our remote authentication application:

As you can see - Login URL points towards index.jsf, this is ADF Security protected page from ADFBasicAuthApp. If mobile user will be able to login into this application, user will be granted access to the mobile application also. You should specify JSESSIONID cookie, if authenticating against WebLogic server.

These are main steps in configuring Login for ADF Mobile application.

Here you can see how default Login page looks in iPhone simulator:

Try to login with un-existing user - sking:

It reports error about invalid username/password, as it was expected:

Provide now valid user - redsam/welcome1:

Authentication with remote ADF application is successful, home page is loaded:

Sunday, October 28, 2012

ADF Project Development Time Distribution

Here you can see a video from my OOW'12 session, where I'm describing how development time splits for ADF projects. This should give you good idea for planning and estimating ADF project development time:

One of the key things - ADF BC development time always takes less comparing to ADF UI development time. This is not obvious when you are about to start your first ADF project, but is always good to know in advance for proper planning:

Saturday, October 27, 2012

LOV Validation and Programmatic Row Insert Performance

When I work, I think - is not enough just to implement use case, final solution must have good performance and run without side effects. I will give you today one more example and technical hint, to prove such thinking is important. This time I will use example of programmatic insert, when newly inserted row contains attribute with LOV mapping.

LocationId attribute from sample application - CreateRowLOVExecApp.zip, is mapped with LOV:

There is custom method created in AM Implementation class. This method is responsible to insert two new rows, it sets new value for LocationId attribute (attribute with LOV mapping):

So far so good - nothing special here. Use case of programmatic row insert seems to be implemented. But wait a bit, lets test it how it works - press Add Rows button on the UI, it will call our custom method and add two new rows:

It works - no errors. Well - thats true, but look what we can see in the log. We are inserting two new records, but there are 2 SQL (why 2 of them, at least we should be happy only 2 - but not 3. for me only 1 would be enough :) statements executed in addition per each new row. If you look more closely, you can notice these SQL statements are coming from LOV definition. Basically, because we are setting value for LocationId attribute (mapped with LOV) - ADF calls LOV SQL and executes it to validate new value we are setting (to check if it exists in LOV):

From LOV validation point of view this is logical and correct. But if we are performing bulk inserts and we know that attribute value always will be correct - there is no need to call LOV validation for each row. In such case I would recommend to use another VO, without LOV's defined - use it to do bulk insert and then re-execute VO with LOV's to display latest data on the UI.

Thursday, October 25, 2012

Primary Key Importance for LOV View Object

Keep in mind, if you want to enable ADF Faces LOV component for autocompletion - you must have primary key defined for LOV View Object (even this View Object is readonly). Otherwise, ADF Faces LOV component may not function properly - new value will not be accepted and reverted back to original one.

I will demonstrate such behavior in this sample app - LOVPrimaryKeyApp.zip.

Originally, LOV VO didn't had any primary key defined - we will test how it works:

LOV VO is defined for JobId attribute:

ADF UI is set with AutoSubmit=True property for LOV component:

LOV field originally is loaded with AD_VP value:

We change it to be IT_PROG and tab out:

From the log we can see ADF executes two SQL statements - first it filters by IT_PROG and then suddenly it executes same SQL but without bind variable - its where new value is lost and LOV is reset back to original value AD_VP:

This happens because ADF tries to validate new value and execute findByKey method for that reason. However, if there are no key defined on LOV VO - it fails to execute findByKey and performs blind SQL execution without any bind variables at all. Value is reset back to original - AD_VP:

Let's set primary key for LOV VO - JobId:

 Finally now findByKey is executed correctly, because LOV VO contains key attribute. New value was validated correctly and accepted - see second SQL:

There is still a big mystery why ADF executes two SQL statements to validate new value for LOV. We would need to dig into ADF source code to understand that.

Monday, October 22, 2012

Transaction Level ADF BC Entity Validation

Is not so well known, but we can defer validation execution to transaction level for ADF BC entity validators. This can be applied only to Key Exist and Method validators on Entity level and is available in both ADF 11g R1 and ADF 11g R2. It is useful, because it instructs framework to invoke such validation rule only if other validation rules were passed successfully. If validation rule invokes complex code, it may affect performance - each time to invoke it together with other validations. You could defer it for later execution, only if all other validations passed - sounds good.

Download sample application - EOValidationApp.zip. This sample implements two validation rules - one is marked to be deferred to transaction level and second is using default setting of entity level execution. You can configure validation rule execution option in Validation Execution section:

I have set both validators to return false, this will ensure both validators to fail. Let's test if validator with deferred execution will be invoked together with default one:

In order to distinguish executed validation visually, I have set different message for deferred validation - Employees validation on transaction level:

Only one validation rule is executed - it fails and framework prevents executing additionally second rule (one which is deferred):

If we test both validation rules set with default execution setting:

Both rules are executed and reported at the same time:

Sunday, October 21, 2012

Why Oracle ADF Developers are Sensitive People

Here you can hear a story I told during my OOW session (OOW'12: Oracle ADF Implementations Around the Globe: Best Practices). This is a true (may be a bit funny, if not sad :) story about ADF developer life and his fight with the deadline for ADF form implementation:

Enjoy and stay calm, even if the deadline is coming to you :)

Wednesday, October 17, 2012

ADF Essentials Security Implementation for Glassfish Deployment

ADF Essentials includes all the key ADF technologies, only one is missing - ADF Security. This is related to ADF Security technical implementation dependency on WebLogic security. However, lack of ADF Security support is not a show stopper - we can enable JAAS security model. This would protect page resources from ADF application, but not ADF Task Flows with Fragments. One of the most common ADF architectures nowadays - use of ADF Task Flows with Fragments through dynamic regions based on single page. This means security implementation to protect ADF Task Flows with Fragments, when rendered through dynamic region is very important.

In this post I will provide solutions, implemented in the sample application - MultiTaskFlowApp_gfsec.zip for:

1. Configuring JAAS security for ADF application
2. Configuring ADF application for Glassfish security
3. Restricting access to ADF Task Flows with Fragments

Sample application contains SecurityController class - custom class, responsible to check if task flow can be accessed. Logic is pretty simple - we check current dynamic region task flow address, compare it along with a security check (globalaccess role). This is simplified example, in real life most likely you would retrieve mapping between task flow and security role from the database:

Now the key part - from where this logic is invoked. It is invoked from task flow activation property (conditional activation). This means, dynamic region will be activated only if task flow will be viewable (security access is granted) based on the custom security logic from our method above:

This is how we can control ADF Task Flow with Fragments access.

Now let's take a look how security infrastructure is configured for deployment. Firstly you need to define JAAS security constraint in web.xml:

As you can see here, all pages (/faces/*) are restricted to be accessed only for authorized roles. These roles are mapped with groups. Groups are defined on Glassfish server. This is the same concept as with WebLogic, only that we need to use glassfish-web.xml (create it manually) configuration file in WEB-INF where roles are mapped with groups:

We can test it now - login as redsam (GlobalUser):

Open task flow for Departments:

Login now as sking (RegionalUser):

This user doesn't have access to the Departments task flow, task flow will not be activated as per our security check implementation:

You can create local user in Glassfish, just in the same way as you do in WebLogic - go to file realm and press Manage Users:

You can manage users from here:

Sunday, October 14, 2012

PanelGridLayout (JDev ) to Simplify Oracle Forms Modernization to ADF

I'm usually bored to death to work with UI layout or CSS. But not today, when we have new af:panelGridLayout ADF Faces component available with JDev (it was already available with Read more about it from Duncan Mills blog - PanelGridLayout - A Layout Revolution. This will change how we build layout in ADF, but also it will change how we build form blocks layout. I believe it will substitute af:panelFormLayout component, in more complex use cases. This is especially true for Oracle Forms modernization - usually Forms screens are pretty complex and stuffed with af:inputText boxes. Up till now it was hard to adapt af:panelFormLayout to create proper grid UI - this will change with af:panelGridLayout component.

Here is simplified example of such layout, typical to Oracle Forms systems (download sample application - PanelGridLayoutSampleApp.zip). This layout is stretchable:

Input text boxes are rendered using grid structure and spread across different areas of the page. We could achieve similar layout structure with af:panelFormLayout, but this would mean to add lots of af:spacer components into empty areas - not a real grid.

One more reason to move to JDev - Panel Grid Layout available directly from Component Palette:

When you drag and drop it to the page - JDev offers configuration wizard, this is very helpful - is much easier to understand different layout properties and apply them correctly:

Here you can see how it looks from the source structure - rows and cells:

Saturday, October 13, 2012

ADF 11g R2 WebLogic 10.3.5 vs ADF Essentials Glassfish 3.1 Performance Test

With ADF Essentials certified on Glassfish server, we can run performance test and compare ADF runtime performance on both servers - Glassfish and WebLogic. You can read about ADF Essentials (free distribution of ADF framework) from my previous post - ADF Essentials - Quick Technical Review. Based on performance test results - ADF runs faster on Glassfish server. This can be explained logically, because Glassfish server is much lighter comparing to WebLogic - it allows to execute ADF runtime faster.

Performance test was completed on regular ADF developer environment, there was no special tuning applied for both servers - just all default settings. My goal was to test with default settings, without special tuning - because at the end we can tune both servers and get even better results in production.

For the test case, in order to make it more realistic - I was using free sample Chinook Database data loaded into Oracle XE. I have generated ADF BC for this database, with Master-Detail relationships. Some of the tables contains around 10 K rows. I was using these tables for LOV and Master-Detail implementations.

The best thing - I was able to record single JMeter script and run it without changes (well, just server port change) for both deployments (Glassfish and WebLogic). Exactly same JMeter script execution against two servers allows to produce as much as possible accurate results for the same application deployed on both servers.

Here you can download sample ADF 11g ( application I have developed for performance test - SamplePerformanceApp.zip. JMeter performance test script is included into archive.

Performance test was performed for two types of user load: 25 and 50. Each test was repeated 3 times to get average results.

1. 25 concurrent users. Response times (obviously lower is better):

a. Glassfish: 0.8 seconds in average
b. WebLogic: 1.4 seconds in average

2. 50 concurrent users. Response times:

a. Glassfish: 8.7 seconds in average
b. WebLogic: 17.2 seconds in average

These results show WebLogic to be 2 times slower (twice as slow) in average comparing to Glassfish when running the same ADF application.

Sample application contains two tabs. First tab brings region with single record block. Stress test is recorded for each user to navigate through records, to go to last/first record, open long list LOV for Album Id:

Second region renders 6 blocks, there are 3 Master-Detail relationships. Stress test is recorded for each user to navigate through Master-Detail records, open LOV's and return values:

Sample application implements ADF BC structure based on sample free Chinook DB (see above):

There are two regions, rendered in tabs from main page:

Master-Detail structure implemented in details region:

Below I provide JMeter stress test summaries:

1. Glassfish 25 users

2. WebLogic 25 users

3. Glassfish 50 users

4. WebLogic 50 users

Summary: ADF performance depends on the server type. ADF is not slow, but it might be just server is slow. It seems to run faster on Glassfish with free ADF Essentials distribution, at least today. I will not go into deeper conclusions at this point, because my goal was to compare ADF runtime performance on WebLogic and Glassfish from technical point of view.