Wednesday, December 24, 2014

Configuring MDS Customisation Layer and Layer Value Combination in ADF

With this post I would like to dive a bit deeper into MDS customisation and layer combination handling. By default, there is defined customisation layer - site. Typically we set our own customisation values for this layer, as a result - all customisations usually are stored under site layer. There could be situations, when more advanced setup would be required - to be able to control layer and layer value combination in a custom way. In other words - to be able to define your own custom layer and then provide customisation values for this layer (MDS customisations will be stored under custom_layer/custom_layer_value, instead of default site/custom_layer_value). Oracle docs would not describe how to handle on runtime layer name to be dynamic and retrieve it from some sort of configuration file. I'm going to describe a technique for this, allowing to combine and group MDS customisations under custom layer and layer values folders.

Sample application - MDSCustomizationsApp_v3.zip is implemented with a separate JDEV project for MDS customisation files. There is no site layer, it starts with profile1/profile2 and then goes with MDS layer values group1/group2. Layer profile1/profile2 switch is dynamic and handled by custom MDS customisation class implemented in the project. This is how it looks like in JDEV (Customisation Context is set with profile2 name) - MDS layer name is retrieved from a custom JAR file stored under JDEV structure (I will describe it below):


In Oracle docs you would find an example of custom class with MDS layer, where layer name will be set as static. In my sample app, I have implemented it as dynamic - layer name is retrieved from configuration file. Layer name is retrieved and assigned during first application load, it is not reset until the next restart. Here is the example of layer name variable initialisation:


Method getValue is overriden as well, to return different MDS layer customisation values, based on ADF Security.

Method getName is overriden to return MDS layer name on application initialisation. Custom method retrieveDynamicLayerName is implemented to retrieve MDS layer name from configuration file. This method works on design and runtime, this means it can be used for MDS design time seeded customisations:


In order to use custom SiteProfileCC class on runtime, we need to package it into separate JAR file and include this JAR into EAR. In my example, configuration file is packaged together with the class (this would allow to use it for design time MDS seeded customizations):


You must copy JAR file with MDS seeded customisation class SiteProfileCC into JDEV directory - jdeveloper/jdev/lib/patches, this would make it visible for design time MDS seeded customisations:


I have defined multiple MDS layers with layer values. Two layers are used for the test - profile1 and profile2. Each of these layers is assigned with group1 and group2 MDS layer values:


Application must be configured to use custom class SiteProfileCC, this is done in add-config.xml file:


Customisations are implemented in the separate JDEV application, all customisations are deployed to MAR file (we can export them directly and apply to the running instance of ADF application):


MAR file is included into main application deployment profile, under EAR level. You should notice - MDS customisation class JAR file is included to be packaged under lib folder on EAR level (this is important, otherwise application will not be started, because it will fail to load custom SiteProfileCC class):


Let's see how it works. I have provided profile1 for MDS layer in configuration file and redeployed application:


Login with user redsam1, the one granted with Group One role:


Application screen is loaded with customisations based on MDS layer and layer value - read-only table is rendered on the right side:


Login with user redsam2, the one granted with Group Two role:


Customisations for profile1 and group two are applied. Instead of Submit button, Save button is implemented:


Let's change MDS layer to be profile2 and test again with the same users:


User redsam1 gets customisation applied with Jobs block rendered below Employees:


User redsam2 gets customisations with Save and Cancel buttons included:

Saturday, December 13, 2014

How To Set EAR Upload Size for Oracle Enterprise Manager

By default, there is a limit for EAR upload size (~40 MB) in Enterprise Manager. If your ADF application is fairly big, you may face this limitation and will not be able to deploy through Enterprise Manager. Deployment for large EAR would work through WebLogic console, WLST script or directly from JDEV, however sometimes you may need to deploy through Enterprise Manager. I will describe in this post, how you could increase the limit - we are going to extract Enterprise Manager application EAR and change maximum file upload size specified in web.xml.

In my case, the requirement was to be able to deploy ~47 MB EAR file:


When trying to deploy this EAR through Enterprise Manager, I would get the error about maximum file upload size exceeded:


You must navigate to the folder, where applications are deployed for your domain (alternatively, double check in WLS for EM application, where EAR file is stored). There must be one called em.ear, this is the deployment for Enterprise Manager application:


Extract this EAR (make sure to create backup), you will find em.war file inside - we need this file:


Extract em.war file now. Navigate to WEB-INF folder, you will find web.xml file there. Open web.xml file for editing:


Search for org.apache.myfaces.trinidad.UPLOAD_MAX_DISK_SPACE parameter in web.xml and change its value to be large enough to accept the size of EAR file you want to deploy. I have set it to 50 MB = 52428800 bytes:


Make sure to pack everything back, and keep original em.war and em.ear files structure:


After all the are changes applied, large EAR file is accepted in Enterprise Manager and we can proceed with the deployment:

Monday, December 8, 2014

ADF Mythbusters UKOUG'14

I would like to post the slides from our recent session on UKOUG'14 conference - ADF Mythbusters. This session was presented by my colleague from Red Samurai Consulting - Florin Marcus. The goal was to break popular ADF myths. We have logged Oracle Support SR's, each myth in the slide is assigned with SR number.

Slides are available on SlideShare:


The following topics are covered in the presentation:
  • ADF BC Batches Of Functionality
  • AM Pools and DB Connection Pools
  • Activation-Safe Application Modules
  • Maximum Number of Regions Per Page
  • JSP vs Facelets
More detailed description and analysis data are available in the slides.

Thursday, December 4, 2014

Adaptive Case Management 12c and ADF Human Tasks

I'm diving into the new topic - Adaptive Case Management 12c and ADF integration. Today will be the first post in the category and there are more posts planned for the future. I strongly believe that ACM (Adaptive Case Management) makes a great extension for standard BPM. Mainly because it allows to define a loose process, without strict order steps. Process steps can be executed in different order, depending on the situation requirements, at given time. I will be explaining how to implement ADF Human Task for ACM activity and will share several tips, how to make it run in BPM Workspace application.

This is how sample application (HotelBookingProcessing_v1.zip) is constructed, there are two Human Tasks (AddHotelBooking and ValidateHoteBooking) and HotelBookingProcessing Case control:


HotelBookinfProcessing case is defined with Hotel Booking Details data type (this type is based on XSD schema and is defined as Business Component variable - don't mix up with ADF Business Components) - you can think about it as about main data structure type for the case, this can be transferred into every case activity:


There are two stakeholders defined, this could help to control who could have access to human task and case activity. Customer Service Representative is supposed to add new hotel booking, while Financial Accountant can approve or reject it:


I have created Human Task activity directly through composite, it is not necessary to have BPM process to define human tasks. Important to set Application Context property for Human Task to be OracleBPMProcessRolesApp, this will help later with security roles configuration in BPM workspace:


In order to register human task with Case management, we are given option to promote human task as a case activity. This will allow to initiate human task from the case management:


We can define input and output for the case activity, based on the same data type defined in the case. This will allow to transfer data from the case to the activity, and to the underlying human task in our situation:


You could generate ADF form case data, this form will be rendered in BPM workspace case UI. I'm going to look into customisation options of this kind of form in my future posts (checkbox is set to generate editable form):


This is how case data form is rendered, out of the box is given option to save and reset data for the case - Hotel Booking Details:


Human task form is generated in the same way as it was in 11g - no change here for 12c. You could auto generate this form, it generates a lot of code and I would prefer to build custom light form instead:


Important hint - auto generated human task form will not render in BPM workspace window. You need to change FRAME_BUSTING parameter generated in web.xml from differentDomain to never. With differentDomain option it doesn't render human task form, in 11g it was generating with option set to never, for some reason this was changed in 12c - not for good:


With FRAME_BUSTING set to never, human task form renders well:


Human task is started directly from the case activity - Add Hotel Booking from the available list of activities:


We can track in the case activity log - when activity was started, completed or modified. This is quite helpful info to track activity history:


One of the main advantages - user could decide the order of activities, on contrary to strict BPM process. Start Validate Hotel Booking activity, this will create new task for Financial Accountant:


Activity was started, we can see this from the audit log:


This is readonly human task, rendered in BPM workspace - Financial Accountant could approve or reject it:


Case can be closed and hotel booking approved:

Saturday, November 29, 2014

Adaptive Form with Dynamic ADF LOV Value Binding

Previously I had a post about dynamic ADF attribute binding creation and dynamic ADF form generation - Adaptive Form with Dynamic ADF Attribute Value Binding. Blog reader was asking how to generate dynamic ADF LOV binding using similar approach. This is possible and actually documented in Eugene Fedorenko post here - Dynamic LOV binding. I will use the same piece of code to extend my sample application with dynamic ADF LOV binding support.

Here you can download updated sample application - DynamicAttributeBindingApp_v2.zip. This application is updated with LOV definition for JobId attribute in ADF BC:


Once you are generating dynamic components on the UI and getting VO attributes to render, you should not be surprised there will be more attribute entries returned than you can see defined in VO. Additional attributes are for View Accessors, and we don't need them while generating dynamic ADF UI. This can be controlled by checking attribute kind property for attribute definition. If attribute kind is not of rowset kind, we can display it:


There is another method in the sample app, it checks for attribute type. This helps to decide what kind of UI component to render - input text, input date, LOV, etc.:


Dynamic ADF LOV binding is constructed from helper method below, this method is invoked from ADF UI LOV component:


Here is the essential part of the updated sample app - LOV binding creation method. LOV binding is constructed, similar as ADF attribute binding, by pointing to the iterator, LOV server binding name, attribute name and ID:


Dynamic ADF UI components are stamped through ADF UI iterator:


There is a special Facet to support ADF LOV UI component creation. UI component is created by pointing to the helper method, where ADF LOV binding is constructed:


LOV generated dynamically works well on runtime, user can open a list and select a value:


LOV validation also works, try to enter invalid value (not available in the list), user will be prompted to enter existing value instead: