Wednesday 25 December 2019

Performance issues in oracle ADF. How to detect performance issues in ADF Applications?

Oracle ADF is a very exhaustive framework that provides so many inbuilt functionalities to ease the work of the developer and help the developer in building applications quickly. ADF was built to support large Enterprise level Applications. But with so many functionalities sometimes due to large data or improper implementation of certain business functions, comes the issues related to the performance of the Applications.

ADF is fast!! If your ADF Application is slow, that eventually is due to development mistakes.

This blog post is related to ADF Performance issues that we face in applications. The most important challenge is to identify the exact issue and resolve that issue. Here are a few issues which I have found out during development as ADF Developer.

Reasons for performance issues in Oracle ADF applications

1. Long-running view object Query.


This can be the main reason for the slow performance of the ADF application. First, the Query needs to be identified which is causing the problem. How to identify the query?? I have posted a very detailed answer in this post. The performance-related issue in oracle ADF? How to Identify long-running queries of View Object?

2. ViewObject loading a huge number of records in the memory. 

This happening mostly due to the unintentional loading of huge no. of rows in the memory. How to identify the root cause. In this post, I have looked into this issue in detail. ADF ViewObject loading a huge number of records in the memory? Why? How this can be stopped?

3. Repeated execution of view accessors.

View accessors are the source for a Lov in a view object. There is a property that defines if the view accessor will be executed for all the rows in the view object or not. If the LOV values will remain the same for all the rows of the view object then this needs to set false. In the other case, this needs to be set to false.

view accessor row level bind variable in adf

4. Repeated execution of database functions in attribute getters in rowImpl classes.

The getters are called every time a value is called. The getters are called each and every time a values is called and if some calculating logic is written then it will be called many times which will eventually reduce the performance of the application.

5. Slow running database call, like database function or procedure, etc.

A database function or procedure that is being called is not optimized and taking much time to execute. If this is the case then optimization needs to be done at database level.

6. Unintentional use of "ignore case" clause in view criteria.

Ignore case is used to ignore the case of values in where clause. When we use the upper clause the sql query is like 

 ( (UPPER(Employees.FIRST_NAME) = UPPER(:bindFirstNm) ) ) 

 as we know that the upper clause is slower than normal where clause. Sometimes if this is used unintentionally this can be a cause for the slow query.

ignore clause in view object

7. Improper use of LOV type.

There are so many different types of LOV's in ADF and each has a different purpose. If the LOV is used properly for the business scenario for which it is applicable, then it can lead to different issues which can be problematic. For Example, if we use single selection LOV for a Larg no. of records then it can cause the Application to load slow. I have a detailed post where I have explained this in detail. What happens when we use the wrong type of a LOV??
 

8. Improper view object tuning.

View Objects are used to fetch records from the database. View objects by default tuned for optimal usage. But in some business cases if we are required to play with a large no. of rows of a view object. So the rows need to be loaded in the memory intentionally. In this case, we can use view object tuning to fetch the rows into memory in minimum time. This is not one fit for all solutions. But this will work well. We have some tuning parameters of view object defined in view object tuning section of a view object. 

view object tuning parameters image

I have discussed these parameters in detail in an old post of mine. https://adfjavacodes.blogspot.com/2014/04/adf-scrolling-in-table-with-large-data.html

9. Improper implementation of a use case.

This is the obvious reason in most for the performance-related issues in ADF. This case is best explained in the blog of Andrej https://andrejusb.blogspot.com/2017/11/adf-performance-story-this-time.html



If you have any queries related to the above blog post, please feel free to ask. :)

Tuesday 17 December 2019

ADF ViewObject loading a huge number of records in the memory? Why? How this can be stopped?

View object loading an unnecessary no. of rows in the memory can be a strong reason for causing performance-related issues in oracle ADF applications. There are many scenarios where the rows are being loaded in the memory unintentionally. As too many rows are loaded into the memory this will lead to slow application performance.

There can be many reasons due to which this is happing.

1. The wrong List of Values used.

        a. There are several types of LOV's that are defined in ADF.
        b. Each has different usage depending on the use case.
        c. To explain the point above I will only talk about two, i.e. af:InputListofValues (Lens Lov) and af:selectOneChoice (Dropdown LOV).
        d. af:InputListofValues(Lens LOV): These LOV's are used where the user has to select a value from a very large no. of options. Users can narrow down the list by search and filter and then select the record. This type of LOV loads a small no. of rows (Max 10 Default Query Limit) in the system List of Values Properties in the ViewObject.

ADF af:InputListOfValues

       
        e. af:selectOneChoice (Dropdown LOV): These LOV's are used where the user has to select the value from a small no. of Options lets say 5 to 10. In this case, all the records are displayed on the page and there is not Query Limit by Default.

ADF Single Selection LOV

        f. So if during the implementation if in case if no. of values is large and single selection Lov is used then a large no. of rows will be loaded in the memory and will lead to slow application loading.

        

2. Range of Table set to -1 which means all the rows that are loaded from view object query.


The default range of a view object if dropped on the Page is 25 that means 25 rows will be loaded into memory if that view Object is page is rendered. If the range size is changed to  -1 than all the rows in the view object will be loaded in the memory on the first request and if there are large no. of rows returned from the view object Query then it will take time to load. As per my experience, it is never advised to set the range size of a table to -1.    


oracle ADF Table


3. Use of getFilteredRows or RowQualifier for in-memory filtration in the Application.

        a. getFilteredRows or RowQualifier are used for filtering the rows of the view object programmatically.
        b. These are in-memory filtration, i.e. first all the rows will be loaded in the memory and then filtration will be done.
        c. But this filtration is done in the memory, and if the is being done on a view object which has a large no. of rows then all the rows will be first loaded into the memory which will lead to slow application processing.


How to identify the view object which is loading huge no. of Rows.

ADF shows all the model layer activities using oracle.jbo logger and by setting it to finest we can see minute details of the processes that are being executed when the application is running.
How to enable the logger? I have mentioned the steps to enable the logger in this post ->
Performance-related issues in oracle ADF? How to Identify long-running queries of View Object?

Now run the application and open the logger window and while application is loading see the log. It will show the queries which are being executed. If the log is stuck at some query and the log shows something like this.


The line "$$added root$$ id=-2" means that the Application is loading all the rows of the view object of the above query. 


Solution.

1. First identify the view object or Lov which is loading large no. of rows.
2. Check the references of the view object, where they are used and how they are used.
3. Check if the view object is used for in-memory filtration or not. If yes, then check how many rows are being loaded into memory and why they are being loaded in the memory. Maybe there is any issue in implementation logic due to which this is happening.

 
If you have any questions or queries related to the above blog, please feel free to ask. :)

Saturday 14 December 2019

Performance-related issues in oracle ADF? How to Identify long-running queries of View Object?

The long-running query can be an important reason for the poor performance of the oracle ADF Application. The main point is how to identify that query in an ADF Application.

My ADF application was working fine earlier, but now it is slow. What's the reason??

My view object query is working fine in the database but when I am running in the ADF Application it is running slow? Why??

The above are the common question? Right?

The best way to identify a slow query is through the ADF logs. ADF shows all the model layer activities using oracle.jbo logger and by setting it to finest we can see minute details of the processes that are being executed when the application is running.

ADF logger is a very important tool that can be used in development for debugging. It provides mynute details that can be used to identifying the issues in the ADF applications. I provides you the runtime queries along with the parameters which are used to call the queries.

Here is how you can use the logger.
1. Open the Weblogic log and click on Configure Oracle Diagnostic Logging

oracle adf Weblogic log console

2. After that, the logger screen will open. Go to oracle.jbo logger and set the level to "Finest". The finest level log shows each and every activity which is being performed by the framework.


3. Finest log generates a large no. of rows, so for viewing the whole log we need to increase the log lines in preferences. Initially, it's 3000. Increase the limit to 300000.

Log prefefences in JDeveloper

4. Now when we run the Application (I have taken a sample app with Departments ViewObjects with a view criteria).

how to run an adf application

 5. After the application is started just check the log. Here you can see the query which is executed by the framework to fetch the data along with bind Variables.



How can this be used to identify the queries which are running slow??

Using log we can identify the long-running queries.
1. Run the application and when the application is loading or performing some action which is slow check the log.
2. If the log is stuck at some query for a longer time as shown above in the screenshot, then make a note and thats the query you need to work upon.


Thanks

If you have any queries related to the above blog, feel free to ask. :)


Thursday 12 December 2019

oracle.jbo.DeadEntityAccessException: JBO-27101. Resolved! Attempt to access a dead Entity in EntityObject.


Error : oracle.jbo.DeadEntityAccessException: JBO-27101

Description: Attempt to access a dead entity in the Entity Object.

Root cause: This issue comes up when the application is trying to access a row that is already removed from the entity object cache. Suppose a row is being deleted in a method and then at the end, the same row is being referenced for doing some kind of operation.
 
The error normally comes up due to wrong implementation logic written in

public void doDML(int operation, TransactionEvent e)

method of EntityImpl class. This method runs after every DML operation in the row.
On removing the row also, this method will be called and if some logic is written there such as updating some attribute values of that row without checking for the transaction type, then this error may come up.

Here is an example of the wrong implementation:

    protected void doDML(int operation, TransactionEvent e) {
        super.doDML(operation, e);
        setModifiedOnDt(new Date());   
    }

Right Implementation:

    protected void doDML(int operation, TransactionEvent e) {
        super.doDML(operation, e);
        if(operation == DML_UPDATE){
            setModifiedOnDt(new Date());   
        }
    }

If the above is not your use case, then here is another example

Another example just to simulate this error:

    public void updateRecord(){
        Row currentRow = getEmployeeVO1().getCurrentRow();
        currentRow.remove();
        // oracle.jbo.DeadEntityAccessException: JBO-27101 Error will be shown in the code below
        Object empId = currentRow.getAttribute("EmployeeId");
    }
 
Solution:
The solution is to ensure that if any row is deleted then it should not be referenced after the deletion.

Next: What is the use of EntityImpl in ADF??

Wednesday 11 December 2019

What is EntityImpl class in ADF?

EntityImpl is the implementation class of EntityObject which represents a row which currently there in EntityObject Cache. The row may be a row from a database table or a new Row which is created from the Application.
EntityImpl in oracle ADF

There are a few methods which there in EntityImpl and they are quite useful in the development.

1. public void create (): This method is called whenever a new row is created from the Application. Here we can implement logic to set default values that are needed when a row is created.

Example Logic which can be implemented: 

Suppose you need to store the information about when and by which user a row is being Created. You can implement the logic here. Here in this method, you can write the code to set UserId and CreateDate, the values will be set at the creation of the Row itself.

2. public void doDML(int operation, TransactionEvent e):   This method is called whenever there is any kind of DML operation is going on in the Row. It contains a parameter operation that represents which kind of operation is being done. The operations can be
    DML_INSERT: Insert operation is being done.
    DML_UPDATE: Update on the Entity Row is being done
    DML_DELETE: Delete operation is being done.

Example Logic which can be implemented:

On any update of the Row, we can implement the logic to set the Modified Username and Modified date of the row
  
3. public void remove():  This method is called whenever a row is deleted for removed from the EntityObject.

Example Logic which can be implemented:

Supposed you need to check if there are any child records for the existing current records or not. This logic can be written here.

Tuesday 10 December 2019

What is partial commit in adf? getDbTransaction().postChanges()

postChanges() is a method of DbTransaction that is used to sync the cache layer and database. It basically means when you call postChanges() method is will send all the data that is in the cache to the database and synchronizes both layers.

Example 

Let's take an example of EmployeeVO which is based on an Entity Object.
We will create a row by calling createInsert() method of view object and fill the values. The row will be available in the cache memory. 

Suppose there is a database function that needs the data currently created for performing some operation based on the row which is created.
If you call the database function, the function will not get the data as the row is not available in the database.

The row with the value is currently is in the Model cache, if you want to send that data to the database then you will call the method postChanges(). The method pushes the data into the database with an insert statement in this case.
If a value of a row is updated, then an update statement will be fired when postChanges() is called.

Now the row is posted in the database in the current session. As the row is in the database it will be available for any database function or procedure to perform any operation.

Let's take a use case.

1. The user will create a row of Employee.
2. Entry employee details and then click a button "Update Commission Details".
3. On click of "Update Commission Details" a database function will be called and will do some calculation based on data entered by the user. Then update the Commission of the employee which was created by the user.
4. After that the user will see the commission on the screen.
5. Save the record.

postchanges-in-applicationmodule

Sunday 8 December 2019

Ways to Filter rows from View Object in oracle ADF. When and Which method to use?

During development, we always encounter a situation where we have to programmatically filter rows from a ViewObject. In this blog, I will talk about the different ways through which this can be done. However, there no one fit for all.

I will also try to explain the condition or scenario in which one should be used and also their Pros and Cons.

1. View Criteria 

View Criteria is used to filter the rows by running the Criteria in the database. It runs a WHERE CLAUSE over the query for your View Object. Let us take an example.

Suppose we have a View Object EmployeeVO with Query SELECT * FROM EMPLOYEES

Suppose we want to see the Employees of some particular department, to do so we create a View Criteria on this view object to fetch the employees of a particular department, let us say department no. 102. 

We create a view criteria EmployeeVOViewCriteria1 and apply on the view object with condition 
[DepartmentId = :DeptIdBind], where :DeptIdBind is bind variable for Department Id.

When we will filter the rows then, the framework runs query

 SELECT * FROM (SELECT * FROM EMPLOYEES) WHERE DEPARTMENT_ID = 100

and return the result.

When view criteria should be used.

1. In the case where the query in the view object is simple runs fast and has less no. of records.
2. If the query in the view object is complex with many computations and takes time to execute, then view criteria should not be used to fetch records.
3. View criteria should is not used for a repeated task in a transaction. As whenever you will fetch records from view criteria, a query will run it will add a database hit. Again this is just a suggestion

Pros:

1. Queries run directly in the database and fetch the records.
2. Only the records which are needed will be loaded and displayed.

Cons:

1. It runs the clause over the query of the view object, so this makes the overall query a little slower than the query with direct bind variables.
2. It has to go to the database to fetch records each time it's called.


2. Direct Bind variables in the Query.

We can also use direct bind variables in the view object to filter records.
For the above case if we have to use direct bind variables then we will create the view object query like 

SELECT * FROM EMPLOYEES WHERE DEPARTMENT_ID = NVL(:DeptIdBind);

Here if we have to filter the rows for a particular department, then we will execute the query with the bind variable :DeptIdBind.
On executing the query passing bind variable as null will give all the records.

When direct bind variables should be used.

1. If the query in the view object is complex with many computations and takes time to execute, then direct filtering through bind variables should be used.
2. Loads only the required rows into the memory.
3. Direct bind variables should is not used for a repeated task in a transaction. As whenever you will fetch records, a query will run it will add a database hit.

Pros:

1. Queries run directly in the database and fetch the records.
2. Only the records which are needed will be loaded and displayed.
3. The query runs faster than the query in case of view criteria.

Cons:

1. It has to go to the database to fetch records each time it's called.
2. So every time if the filtering needs to be done, the query will be fired and a hit to the database will be made.

3. Using RowQualifier or ViewObject.getFilteredRows().

RowQualifier is used for in-memory filtering of the data in the ADF Application. 

In the case of filtering the rows with RowQualifier or getFilteredRows, the query of the view object is executed once and fetches all the data in the view object in the application memory and does the filtering of the records.

If we take the above example and filter the rows through row qualifier.

At first all the rows from the query of the view object i.e. 

SELECT * FROM EMPLOYEES

will be loaded in the memory and then the filtering will be done in the memory by comparing the attributes of the query.


When direct bind variables should be used.

1. In the case where repeated filtering is needed many filtering is needed.
2. It loads all the rows in the memory, so it should not be used in case if there are hugs no. of records in the view object.

Pros:

1. The rows are loaded once in the memory and filtering is done.
2. Query execution is needed for the first time only, on the first filter, it loads all the rows into the memory and does the filtration on the basis of that.
3. Good for filtering rows to fetch certain data repeatedly in a transaction.

Cons:

1. It loads all the data into the memory on the first hit, thus increasing memory use of the Application.
2. If the view object contains a huge number of rows, then it takes quite a time to load into memory.






Tuesday 3 December 2019

What is Application Module Pool and how it works??

Application Module is the transaction controller of the ADF Application.
  1. Any database related activity of Business Components in ADF Application is performed through the Application Module. 
  2. Changes made by the Application Module can be Committed and Rollback at any instance of the transaction. 
  3. Application Module can perform a series of database changes in a single session. 
  4. Each Application Module creates a single database connection.

Application Module pooling is done by WebLogic to reuse the free Application Module Instances. This helps in making the Application Scalable.

That means though Application Module pooling, the application can handle transactions even if the no. of users session is greater than the no. of database connections.

The Application Module instance can be shared between users or browser clients. This helps in maintaining low memory usage and improves the performance of the Application.

When the Application Module is shared then the current transaction is saved in the PS_TXN table in the database. And after that, the Application Module instance is available for other uses.

Application Module Pooling works through Passivation and Activation.

Passivation: This is the process in which the state of an Application Module is saved in Database tables in serialized form.

Activation: This is the process in which the Application Module state is reviewed from the database tables.

Let's take an example of a User creating Sales Order and SalesOrderAM is the application Module that is being used.
  1. User login in the system to make some kind of transaction.e.g. to book Sales Order.
  2. When the request comes then Weblogic will check for free Application Module Instance.
  3. If there is no free instance in the application Module pool, then a new Application Module Instance will be created and allocated to the transaction.
  4. If there is a free instance then that instance will be allocated to that transaction.
  5. The user continues with the transaction and then when the user session is idle and some other request comes up and there is no free instance.
  6. In this case, the current Application Module state will saved in the database in PS_TXN tables. And the Application Module instance will be made available for the new request. This is called Passivation.
  7. When the second user completes its transaction and the first user resumes, in this case, the Application Module state will be reviewed from the saved state in the database. This is called Activation.
  8. Application Module instance increases until the max pool size. Max Pool Size is the maximum no. of Application Modules that can be created.

There may be cases where you will not see any entry in PS_TXN tables, this is possible if the Application Module pool size is large enough and Application Module instance sharing is not required.

What is RowQualifier in ADF?

Rowqualifier is used in ADF to programmatically filter rows. This can be used to filter the ViewObject based on one or more where clauses.

For example: If you have an employeeViewObject containing information of the employees and you want to fetch the record of the employees for some particular department. In this case, RowQualifier can be used.

RowQualifier filters the rows from the Memory. i.e. first it loads all the records of the ViewObject in the memory and then filtered the row.

RowQualifier in ADF




Tip: Never user RowQualifier on a table with large no. of records as it will take time to load all the rows into the memory and then run the filter. The application may take some time to process the request.


I have created a method in ApplicationModuleImpl to filter the rows of EmployeeVO on the basis of the RowQualifier.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    public void getEmployeeOfDepartment(Integer DepartmentId) {
        // Employee ViewObject Instance
        ViewObjectImpl employeeVO = getEmployeeVO1();
        System.out.println("Employee Count :" + employeeVO.getRowCount());
        // Creating rowQualifier for EmployeeVO
        RowQualifier rQlfr = new RowQualifier(employeeVO);
        rQlfr.setWhereClause("DepartmentId =" + DepartmentId);
        Row[] filteredRows = employeeVO.getFilteredRows(rQlfr);
        System.out.println("Employees in Department 10 :" + filteredRows.length);
    }

On executing the method below result is printed.



We can also filter the rows using ViewCriteria in ADF Application.
What is ViewCriteria in ADF??

Monday 2 December 2019

What is a View Criteria in ADF?

ADF ViewCritera is basically used to create where clause in ViewObjects.

Suppose you have created a ViewObject with a selected statement and you want that data to be filtered by where clause, in this case, ViewCritera comes into the picture.


Let us see how we can create a ViewCriteria.


Click on Add Button to create a ViewCriteria.


Now click on Add Item button to add a clause to View Criteria.


Here I want a filter the Department table with the DepartmentVO with DepartmentId as 10. So I have selected value 10.  So the ViewCriteria is created now.


I have added an instance DepartmentVO2 to apply the above viewCritera and check.


Now click on the Edit Button. and select the ViewCritera.




Now click on the Ok button. So the ViewCriteria is applied now.
Run the application module to see the results.
As you can see the buttons are grayed out, which means there is only one record in the view. The records are filtered on the basis of given criteria.


RowQualifier can also be used for in-memory filtering of the rows.
Filtering rows through RowQualifier in ADF

How to create Query Based ViewObject in oracle ADF?

Query based ViewObject is used only to view data in ADF Application. This cannot be used to make any kind of data updations.

Let us take an example of a Query Based ViewObject to view the data of the Departments table.

Select ViewObect in the Menu. 


Here I have given the name "DepartmentDisplayVO". In the Data Source section select "Customer SQL Query" and click next.


Write the SQL query which will be used to show the records.


Here you can see the columns which were selected in the Query. You can select specific columns also in the query.





The Query-based ViewObject is created.


Now add an instance of ViewOject in Application Module.


Run the Application Module to see the results.


Below is the tester window showing records.


You will notice that the attributes of the data are grayed out, that means they cannot be modified. If you need to modify the column values then you need to create Entity based View Object.

What is a View Object in Oracle ADF??

View Object is used to view and update data in ADF Applications.

We need a database query to perform CRUD operation in the database, that query is represented by ViewObject in oracle ADF Application.

Analogy: In database if what has to perform CRUD operation, then what would you do? You will write a Query. Right?? That query is represented by ViewObject in ADF.

It basically contains database query to fetch or update the records.

View Object are basically of 4 types.

1. Entity based ViewObject

Entity based ViewObject is based on EntityObject of ADF application and can be used to create, read, update and delete or in short perform CRUD operation a database.

how to create an Entity based ViewObject??

2.  Query based ViewObject.

Query-based ViewObject is based on Query and can be used to view the record. 

3.  Static ViewObject.

Static ViewObject is based on the static Values defined in the ViewObject. This can be used to show static content.

4. Programmatic ViewObject.

Programmatic ViewObject is used where data is populated in the ViewObject programmatically. This data is populated by using the POJO class or some database Cursor or Procedure.

how to create a Programmatic ViewObject??




Creating first oracle ADF Application

In this post, I will show how to create an oracle ADF application and create Entity Object and ViewObject and test the Business Component.

We will create the following in the blog below.
  1. Create an oracle ADF Application.
  2. Create an Entity Object.
  3. Create a View Object.
  4. Create an Application Module.

Let's start.

1. Creating an ADF Application.

 

Open JDeveloper and create a new Application.


Then from the dialogue select Applications->ADF Fusion Web Application. JDeveloper IDE can be used to make many types of Applications. Oracle ADF Applications are made under this head.


Creating an Application involves 6 Steps.
In first you have to write Application Name and Application Package Name. In this case, I have used the name "EmployeeDetailsAPP". I have also given the package name as "employeedetailsapp"
.

ADF Application support MVC and an Application is divided into 3 parts
  • Model (Business Layer)
  • View (View layer)
  • Controller. (Control Flow)
An ADF application is divided into two Projects, one is Model and other is ViewController.
The windows below show the first project i.e. Model and its constituents.



The windows below show the second project i.e. ViewController and its constituents.



This is the last step, here leave the selection to default.


Now application structure is made. In the middle section you can see the steps for developing the application which is shown by default.


After that you have to create database connection which will be used in the Application.



As we have created the Database Connection, the next step is to create an Entity Object.


Select the database connection which will be used for creating the Entity Object.


Now we have to select the Database Table i.e. DEPARTMENTS for which Entity Object will be created.


Click on next. Now you can see the Attributes of the Table DEPARTMENTS


In this dialog you can see the attribute properties. All the properties are inherited from Database Table. e.g. you can see the Attribute "DepartmentId" is Primary key and a mandatory column. From here the properties can be changes as per the need, but it is advised not to change these.



In this window from will see the summary. Now click on Finish.


Here is DepartmentEO which we have created.


Here are the business rules of the table which are inherited by Entity Object.


As we have created the Entity Object, now we will create a View Object based on Entity Object. This is also called updateable ViewObject.



Here we have to specify the name of the ViewObject. In the Data Source selection select Entity.


In the Entity Object section select the Entity Object for which you want to create View Object.



Then in the next dialog you will have option to select the attributes of Entity Object which will be considered while creating ViewObject.


Select the select all icon to select all the attributes.


Here you can see the attributes properties.


In this dialog you can select order by clause for your ViewObject.


This is the summary.


Now as you can see we have created DepartmentsEO and DepartmentVO.


Now to run the ViewObject we need to create an Application Module. Application Module is the Transaction Controller of the ADF Application. All the database activity are performed by Application Module.


As the name of the Application is EmployeeDetailsApp, I have names Application Module as EmployeeDetailsAM. Its good practice to give name to Application name.



Now as we have created the ApplicationModule. Go to the Data Model Section and add a instance of ViewObject from the Left panel.


Now as we have created all the needed Business components we need to run and test the Application Module.


When you run the application a tester window will appear as you can see the image below. As you can see that the fields such as DepartmentName,DepartmentId,etc. are editable. As this ViewObject is based on EntityObject, this can be used for performing CRUD operations.


In this blog i have demonstrated till the Model Layer. In the Next blog i will show you how we can perform CRUD operation on a Web page.

Followup post coming soon.... ☺️


Next Post : https://adfjavacodes.blogspot.com/2020/01/crud-operation-on-webpage-in-adf.html