Disclaimer

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle.
Showing posts with label ADF. Show all posts
Showing posts with label ADF. Show all posts

Thursday, November 8, 2012

Mass Refactoring ADF Application

There are occasions when you may need to refactor the entire adf application including model and view projects to align to certain standards based on your organizational requirements or as a developmental decision.

Dev guide already covers on how to refactor different BC4J and UI artifacts like entity objects, task flows etc. You may refer the fusion applications developer guide for the individual refactoring requirements at http://docs.oracle.com/cd/E15051_01/web.1111/b31974/refactoring.htm

However, doing this object based refactoring could be just too painful depending upon the size of your application and yes of course time consuming as well. So, to make a change everywhere like converting the package name com.mycompany.app.blawblaw  to com.mycompany.newapp.blawblaw it will be required to change all the references of app to newapp in all the application files and also to rename the physical directory structure of the directory app to newapp. Here, are the steps you may find useful:

Assumptions
1. Used jdeveloper 11g version 11.1.1.6.2
2. Used on windows 7
3. Your JDeveloper is closed (not essentially harmful to keep it open but not recommended)

1. Take a good backup of your application before you start. Source control is a good way. However, I will still recommend to take a physical backup by just copy paste the app folder to somewhere else. Sometimes, source control might get crazy to figure out mass changes from outside the jdeveloper.
2. Download a good search and replace tool like I used http://www.divlocsoft.com/index.htm
3. Browse the tool to the root of your adf workspace and do a search with a filter mask *.jpr; *.jpx; *.java; *.xcfg; *.xlf; *.xml; *.cpx; *.adfc_diagram;  *.dcx
4. Above will make sure to capture all the relevant files from workspace from model and view controller project. Then search and replace the following:

  • .app. to .newapp.   for fixing all the packages
  • _app_ to _newapp_ to fix databindings.cpx with correct usageIds 
  • /app/ to /newapp/ to fix taskflow path references etc
5. Once file content refactoring is done there comes a bit manual work. Now, you need to rename all the directories with name app to newapp

Now, start your jdeveloper and you should be all set. 
A point to not forget is to use jdeveloper based refactoring if there are very less number of artifacts and not really a need of moving jpx, jpr files etc.

Tuesday, July 17, 2012

ADF Anti Patterns

I was looking into some of the anti patterns followed by developers while build applications for the enterprise World. I came across one of the useful doc in this direction by ADF-EMG group at https://sites.google.com/site/oracleemg/adf/files

I would still like to summarize the covered anti-patterns here for a quick review:

1. Do not use Composite Primary Keys. Better to use sequences as single attribute primary keys.
2. Do not set Read Permissions on Entity Object. Better to prevent the view access to such pages.
3. Do not mark associations as Composite better to handle it by marking foreign key as not null.
4. Do no call Application Module from inside Entity Object code.
5. Do not call Application Module from inside View Object code that can be found using View Accessors.
6. Do not call setter method of an attribute from the getter method of another attribute.
7. Do not use FacesContext or any other View Layer code in the model layer.

Some, of these might sound quite obvious but developers do ignore these quite often. Most of these anti-patterns usually hints for avoiding either due to performance reasons or due to breaking the standard Object Oriented design principles one of those guides as "Do not invoke anything from the outer layer in any of the inner layers". Another supporting theory is called as 'Onion Architecture'

Tuesday, March 20, 2012

ADF Library to ViewController or to Model ?

Very recently, I got into the conversation when a friend got an external ADF library which had BC4J components and he wanted to use it to create a UI page.

As the library contained BC4J components or you can say an ApplicationModule so the first thought came was  to add the library to the model project and expecting the AM bundled in the library to show up in Data Controls. And when it was tried this way the AM did not show up in the Data controls. Refreshing, rebuilding the project or even restart did not help.

So, trying to dig further when we opened the model project properties and went to the business components import we could see the EOs,VOs and AM from the ADF library.

After a while, when the library was added to the ViewController project and the ApplicationModule immediately showed up in the data controls. So, what was actually happening here?


Well, that's actually how it should have been done. As a thumb rule, if you want to build UI based on the ADF library jar provided by third party then it should be a dependency of UI project not the model project. However, if you want to extend your BC4J components based on the provided components in the adf library then you should add it to the model project.

Tuesday, May 3, 2011

Continuous Integration for ADF applications using Hudson

This post is to show how to create a new job in hudson to setup continuous integration for an ADF application source controlled using svn and hosted on a standalone weblogic server.

Installation of hudson is very simple. Just download the latest version war file from http://hudson-ci.org/ and drop this war in your favorite server container. I am using Tomcat 7 currently.

For this blog post I am assuming following things:

  • You already have a standalone weblogic server setup and capable to run a ADF application.
  • You have the source code of your application version controlled using svn.
  • You have a running hudson with administrator privileges
So, here are the detailed steps to create and configure a job in hudson which will pull the source code from the svn repository when there are any changes committed to it and build n deploy the same code to the running standalone wls.

From the hudson dashboard click on New Job link



On next screen choose the first option free style software project for our job  and give a suitable name the job as shown below

On pressing ok will take you to detailed configuration of the job. This is a big page with a lot of options. So, I am giving a walk-through section via section. In the first part, fill job description and click on 'Discard old builds' checkbox. Here, you can specify how many old builds you want to keep to save the server space as shown below:

You can leave rest of the options and can explore on your own as they are self explanatory. Move down to the 'Source Code Management' section where we will configure the adf source code to pull and build it to deploy.

On choosing subversion, section will expand and ask for repository url which it will check for the validity. Rest of the options can be left default as they are good to go. In the next section, you need to configure at what frequency the builds should happen. Two typical options are polling svn and building periodically. You can choose both for the same job and it totally depends on individual's need. I have below used scm poll which will check for changes in the repository every 5 min.

Other schedules can be configured similarly and well explained in the question mark on the top right corner of the schedule box. So till here, your job is ready to pull the code from svn repo as soon as new changes are there. After this, next steps is to write a small script to build a ear from this code and then deploy it to the running standalone server.  For this click on the list in the build section and choose 'Execute Shell' option. This will provide a text box to write a shell script. You can either write the script here itself or write on the machine where hudson is running and just provide the path here like: /home/username/buildScript.sh as shown below:


I am providing the complete script which can be used to build the ear and deploy it to the running standalone wls with just replacing repo, server urls etc here. Just copy paste it to above text box or store it as a script in your machine and provide the path. Finally there are some post build steps which are like sending email notifications, publishing results etc. Hudson provides a large array of plugins to use for this purpose.







Friday, March 11, 2011

ADF 11g: String comparison in EL expressions

Few days ago I got a situation where i had to compare a part of a string type vo attribute to decide on rendering a component. The value in the vo attribute was a url like http:://facebook.com/user/id=2454555 . So, the requirement was to render a component only if the url is of facebook.  By default you cannot write an EL expression on render property to achieve this. So here is what you can do:

1. On the jspx or jsff add xmlns:fn="http://java.sun.com/jsp/jstl/functions" Make sure to add the library as well in the project properties

2. Now you can right as:  <af:outputtext id="o1" rendered="#{fn:contains(row.link, 'facebook') ? true :false}">

Monday, January 17, 2011

Oracle JDeveloper and Oracle ADF 11g (11.1.1.4.0) (Build 5923) Release 1 Patch Set 3 is released!!!

Monday morning came with a surprise a new Jdev 11g build which is Release 1 PS3...

Grab it from otn site at: http://www.oracle.com/technetwork/developer-tools/jdev/downloads/index.html
Check out the release notes at: http://www.oracle.com/technetwork/developer-tools/jdev/relnotes-14-jan-11-261400.html which is a long list of fixes and features...
For highlights checkout the What's New section at: http://www.oracle.com/technetwork/developer-tools/jdev/index-088099.html#NewInThisRelease

Don't forget to add your comment on what you like and what you didn't? What met expectations and what you were expecting...

Wednesday, February 10, 2010

What not to do while editing a AM method exposed to client

In a typical ADF application you would be having some AM methods exposed to client side. Whenever you expose a AM method to client side you need to go to AM and in the java you need to shuttle the method to the right.

As a result your AM.xml and AMClient.java will be modified (it will actually add the entry for the exposed method). This is fine and works good.

However, if a need arises to modify this method's signature then you should not directly go to your AM.java and modify it straight forward. Doing this may corrupt your AMClient.java file and leading to issues.

The right way is:
1. Open you AM and go to java tab.
2. Shuttle the method whose signature is to be modified towards left.
3. Now modify your method signature. save all.
4. Open you AM again and shuttle back the method.

You will also need to delete the method from the pageDefinition file where it is used and refresh the data control to add it again.

Ninja ADF Developer

Found an interesting video on oracle ADF




Thursday, December 31, 2009

Deploying ADF 11g application in weblogic 10.3

Today, I was trying to deploy my ADF 11g web application to a weblogic server. So the first step was to right click on View Controller project and go to deploy option. This created a war file for me as npe.war . I went to weblogic console and in the deployments choose install option and provided the path of npe.war. After few next next and finish I saw an error saying:

java.lang.ClassNotFoundException: oracle.adf.library.webapp.ResourceServlet

So, on hunting for a solution finally found that I used the wrong way of deployment. Instead of deploying View-Controller project as a war file I should have deployed the whole application as an ear file. So to do so there is an application menu in the jdeveloper. Select deploy option from there and choose deploy to ear file. So far so good I went again to the weblogic console deleted the old npe.war web app and this time installed npe.ear. After reaching the finish step on hitting finish I saw a new set of errors saying:

java.security.PrivilegedActionException: wenlogic.common.ResourceException:
java.security.PrivilegedActionException: wenlogic.common.ResourceException:
No credential mapper entry found for password indirection user=system for data source NPE

So, another hunt on web resulted into another change I need to do before deploying the app as an ear. To avoid this error you need to go to Application --> Application properties and in the new window uncheck Auto Generate and synchronize weblogic-jdbc.xml Descriptors during deployment.

That's it.. now deploying the ear this time should successful. Please comment if you found any other issues while deploying your ADF application to weblogic.

Tuesday, October 13, 2009

Getting handle to HttpSession in ADF

However, in general you should not need to get HttpSession programmatically in ADF.

But sometimes you need and here is how:

FacesContext context = FacesContext.getCurrentInstance();

HttpSession session  = (HttpSession)context.getExternalContext().getSession()



Monday, September 7, 2009

Performance tuning : Fault-in behavior in ADF

Well these days I got some interest in performance improvements in ADF applications.
So, here is an interesting term 'fault-in'. Before, I tell what it is the thumb rule is "Try to avoid it.".

Normally, when you build your Model or business components you start with building entity objects. On an entity object you build one or more view depending upon the UI requirements.

If you go with default options of creating an updatable view object based on an entity object you get a sql query which is selecting all the entity attributes with no where clause which is called 'Deafult VO query'. So, say you have an entity object EmpEO based on an employee table with selected attributes empId, empName, empSalary and mgrId then you will get something like

SELECT EmpEO.empId, EmpEO.empName, EmpEO.emoSalary, EmpEO.mgrId
FROM employee

However, in real life we create VOs depending upon the UI page requirements. So, say we create VO choosing only empId, empName and empSalary. While creating UI say it is just required to show empId and empSalary from the VO instance. On running the page, which has a VO instance of this VO as a table, ADF framework queries all the rows from the employee table and create entity instances one per row having information about empId, and empSalary. It will not populate empName and mgrId from DB. The VO instance will have pointer for each vo instance row to the actual EO instance having data.

This is pretty smart as most of the times you might be only viewing data and in that case it saves time and memory by not populating entity instances with data you don't need. Now, imagine there is a update page based on this vo instance where you try to update the emp record with id 486. In the entity object you define a validation rule that empSalary of the employee being updated should not be higher than the salary of any of the employee under his manager. So, here fault-in comes to the picture. As mgrId is mentioned in the validation rule which is missing from VO definition so while checking for this validation on record commit, framework will fire the default VO query and hence will populate all the missing EO attribute information from DB for that row . That could cause performance overhead at run time. It may be fine for a case where there is just one missing attribute and your entity is based on a few attribute based table. But in a scenario where say your entity has 100 or more attributes in that case default VO query may be big performance overhead. Situation could be worse when some of the attributes may be of type CLOBs or BLOBs.

To avoid fault-in you can look up for such cases and add such attributes to your VO. This way, while executing the VO query for the first time it will automatically populate such attributes as well in the entity instances.

Another way is slicing your entity object into multiple entity objects and creating composite VOs. For example say you have a Emp table with 30 columns some of being CLOB and BLOB types or very less used. So, you can create two Entity Objects one with mostly used columns and another with rest of the attributes. Depending upon your business requirements you can create VOs either on just one of the two EOs or a composite VO based on both the EOs.


Friday, September 4, 2009

Fine tuning your Application Module in ADF

A lot of performance problems occurs because we leave the stuff as soon as it starts working as per the requirement.

We simply do not care at the performance issues it might create later in system testing or in production environment with real life load. I am not a guru of performance tuning but here is a little I learned from my experience:

1. Carefully investigate each and every instance you added in the Application module of your view objects. Go to the tunning tab and there set the batch size equals to 1 more than the expected number of rows the VO is expected to get from DB in most of the cases. This will save un-necessary db trips. So, say a VO instance is supposed to retrieve 20 rows from db then change the batch size to 21. By default it is 1.

2. Iterating over View objects is fairly easy and we easily get into the habit of copy paste the code to iterate over the View object to look for some particular row. Avoid that. Where ever possible have a view criteria with bind variables and use it in your code to fetch the desired row.

3. One of the most neglected area is executables sometimes left in pageDefinition files and un-used. During development we try various options when something does not work and forget to remove the dead code. So, those executables run at the page load time automatically and slow down the page load time even it does not have any other side-effects on the functionality of your app. So, remember to analyze bindings and executable in your pageDef and cleanup if needed.


Wednesday, September 2, 2009

Difference between getRowCount and getEstimatedRowCount in ADFount

In ADF applications where a VO is working on large amount of data it is could be a bad impact on using getRowCount to find the number of rows in the VO. The reason is it query the database table every time it is used. So, it incurs you a DB trip.

However, getEstimatedRowCount is a bit different. For the first time it queries to DB table using a select * from table query and store the count in the Middle-tier. After that it keeps on adjusting the count within the middle tier whenever row insertion or deletion are performed on the view object.

This way it prevents the db trip and is much faster.

The downside of this method is it may not be accurate sometimes. Specially, in the scenarios where there are possibilities of data insertion or deletion from backend by some other application at the same time.

Wednesday, August 19, 2009

Using Parent Action in ADF 11g

What is parent action and why do we need it?

Imagine a situation where you are on a page and you have dropped a bounded task flow A as a region on this page. Now, from inside TF A you call another bounded task flow TF B which in turns calling a third bounded TF C. So, finally you are in task flow TF C.

Here, there are situations when you may need to navigate directly to TF-A rather to TF-B. So, in this case a task flow return activity will not help as it will only navigate you to the taskflow TF-B.

So, to go to TF-A you can drop a parent Action activity from component pallet on the task flow diagram of TF-C. In the properties define the parent outcome as some string value.

Now in the TF-B drop a task flow return activity and have a control flow navigation from your view activity to the task flow return activity. Give the name to this rule same as the parent outcome name you provided in TF-C.

That's it. Now, when you will will navigate from TF-C the flow will directly navigate to TF-A and skipping the TF-B.

Multiple EO based VOs in ADF 11g

It is very common to have a data model where you have a table jobs with fields jobid, jobname and another table say emp table with empId, empName , jobId where jobid is a ref to job table.

On the UI you usually need to show empName, and the job he is associated rather the job id.
So, to fulfill such requirement you can model you BC4J as following:

Create EmpEO entity over emp table and create JobEO enitity over Jov table. Now, you can create a single VO say EmpJobVO which is based on EmpEO and JobEO. You can shuttle all the attributes from EmpEO and only jobName from the JobEO while creating the VO.

One thing to take care is in the query step is to make sure that the join condition is specified in the where clause. If this will not be specified it will perform a Cartesian join.

Saturday, August 15, 2009

Programmatic error message in ADF 11g

There are situations when you may need to show error messages from your managed bean code to your ADF page.

ADF 11g supports two level of messages as component level messages and page level messages.

To show a component level message write the following code in your managed bean method:

FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "this is component level message");
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(.getClientId(context), msg);

Also note that you need to add component to your page (anywhere).

To show page level message you need to use following code:

FacesContext context = FacesContext.getCurrentInstance();
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "Value entered is invalid");
context.addMessage(null, msg);

Wednesday, August 12, 2009

Using Groovy to populate sequence value in primary key attribute in ADF 11g

In ADF 11g there is a better and much simpler way to populated primary key attribute of your entity using a db sequence.

You can simply to to your entity pk attribute change the default value type to expression and put

(new oracle.jbo.server.SequenceImpl("YOUR_SEQ_NAME",object.getDBTransaction())).getSequenceNumber()

and

Monday, August 10, 2009

What is DataBindings.cpx file in ADF

In ADF web application as soon as you drop a databound component on your page a DataBindigs.cpx file gets created. You may wonder what it contains? So, here it is:

The DataBindings.cpx keeps track of the individual page definitions files used within the project, as well as the DataControls mapping to such things as ADF Business Components Application Modules.

Till Jdeveloper 10.1.3 release there was no way to have multiple DataBindings.cpx files which was very much desirable as the project the size grows and being worked by multiple teams. Jdeveloper 11g added this capability to have multiple DataBindings.cpx files.

There is a new file in 11g called adfm.xml which is used to keep track of all such DataBindings.cpx files in the system. So, when breaking your DataBindings.cpx you need to take care to create an entry in the adfm.xml. You also need to make sure to have unique application id attribute value for each entry.

Usage of PostChanges in ADF

You can override postChanges method of any entity object in your ADF application. postChanges method can be used to push the middle-tier changes to the database. But it does not commit it.

So, a natural question arises like why do we need to push the changes to database from middle-tier and without committing?

Imagine a scenarios where you have a PL/SQL procedure which you need to run after some rows has been inserted/modified in your application. Before you issue a commit everything will remain in the middle-tier. A PL/SQL procedure will run on the database and hence in such scenario your PL/SQL procedure will not be able to get the latest changes which are available in the middle-tier.

So, here comes the postChanges method which you can use to push the middle-tier changes to the database without actually committing.

Friday, July 24, 2009

current date time groovy for ADF

We mostly have created_date or updated_dated column in our data model. The value for these columns is mostly
the currentt date (time truncated) or current date and time. To default such values every time you create a row in VO/EO there
is excellent support for groovy expressions in ADF.

To do so go to your VO/EO .xml file. In overview mode select attributes tab. In that select the attribute you want to default with
current system date-time or date. In the value box type one of the below and choose radio as expression.

Only date: adf. currentDate
Date with Time: adf.currentDateTime