Creating Custom Business Methods Using ADF Business Components
Creating Custom Business Methods using ADF Business Components
Purpose
This
tutorial describes how to add a custom method to a business model using Oracle
ADF Business Components. The purpose of a custom method is to provide easy client
application access to specific application data. This data is usually calculated
or derived from multiple business objects. Custom methods provide an easy and
encapsulated way of publishing this type of data.
Move your mouse over this icon to show all screenshots. You can also move your
mouse over each individual icon to see only the screenshot associated with it.
Overview
The
tutorial steps you through creating a custom method in an ADF Business Components
project. When a client application calls this method, it will pass a department
number to the method and get the total salary for that department back from the
method. The purpose of a custom method is to provide an easy way for client applications
to get calculated or derived data from the ADF business model without having to
instantiate a specific view object or multiple view objects.
You
have been working on the data model for a Human Resource Information System. You
have now discovered that a number of client applications need to determine the
total salary for a given department. You could leave it to the client applications
to calculate the total, but that would lead to redundant work and quite possibly
introduce erroneous data. You have decided to create a custom method in your
application that accepts a Department Id as a parameter, calculates that total
salary for that department, and returns the value to the calling client application.
By building the code within the Business Model, your provide access to any client
application that can use the Business Model. You therefore help ensure consistency
and reduce redundant code.
In this step you will create a
new application workspace and project to help organize your application. All of
the work you do in JDeveloper is organized into projects within an application
workspace. After you have created a workspace and project, you will create a default
Business Components Model for your business.
Create a new Application workspace
to hold the business model components. Select File | New, then select
the Application workspace node. Click OK.
This will open a dialog
where you can define location, templates, and application package prefix
2.
Change the name of the application
to HRApplication. Accept the other defaults for the application and click OK.
3.
On completion you should have an application
named HRApplication and two projects named Model and ViewController.
You will only use the Model project for this exercise.
It is generally
easier and more effective to start with a set of default business components than
to create each one individually. Whichever technique you use will result in a
set of components that you can customize to fit your specific business needs.
To
create a set of default business components, right-click the Model project
node in the System Navigator and select New.
2.
This opens the New Gallery wizard.
From this gallery, select the Business Components category and Business
Components from Tables and click OK. You can also double-click Business
Components from Tables.
3.
Selecting Business Components from
Tables opens the Business Components wizard. The first step of this wizard
is to establish a connection to your database. Select the connection name that
connects to the HR schema. If the welcome page is displayed, click Next to go
the step 1 of the wizard.
Note: If you have not established this connection to the HR schema,
please see the prerequisites section.
4.
In step 1 of the Business Component wizard, select the tables for which you
want to create entity objects. Select the Departments, and Employees
tables.
5.
In step 2 of the wizard, select which
view objects you want to create from the default entity objects These view objects
will be updateable. In the next step, you can create view objects that are read-only
and that are based on tables, not on entity objects. Select all of the available
entity objects and click the shuttle button.
6.
In step 3 of the wizard, you can
create view objects that are based on tables, not on entity objects. These view
objects are useful for any view that will not be updateable.
7.
In step 4 of the wizard, change the
name of the Application Module to HRAppModule. If the Application Module
checkbox is checked, the wizard will create a default application module for you.
If
it is not checked, check it.
8.
The last step of the wizard confirms
what Business Component objects you are about to create. Click Finish to accept
your choices.
9.
Your project should now include an
application module with entity and view objects.
JDeveloper
includes a built-in Business Components Browser that tests business components.
The browser works without requiring you to build any client code.
To
invoke the tester, right-click the Application Module you just created in the
System Navigator and select Test from the context menu.
2.
The first step of the Tester is to
select a database connection to use for this test. Select the database connection
you used to create the default objects and click Connect.
3.
The Business Components Browser shows
all of the View objects defined in your Application Module.
4.
Double-click a view object instance
to display a single-record data viewer.
You can scroll through the rows in this View object using the controls
on the top of the window. You can double-click other View objects to run multiple
data viewers.
The Business Components Browser gives you a view of the application
module that you have just created.
When you are finished testing your application,
close the Business Components Browser.
Before you add a custom method, you
must decide where to put it. In general, it depends on how and from where, the
method will be called. If the method will be called while a client is using a
View Object, then the method could go in the View Object. However, if the method
may be called outside the context of a specific View Object, the method should
go in the Application Module. Putting the method in the Application Module makes
it easier for client applications to access the method. They won't have to instantiate
a View Object to access the method. In our example, we will create a method in
the Application Module.
In this step, you will add a simple method
stub that you will complete in the later steps. Adding this stub takes you through
steps you will repeat every time you add or modify code using JDeveloper's code
editor.
In the System
Navigator, click HRAppModule. This will show the contents of the Application
Module in the Structure pane. Notice the two source files: HRAppModule.xml and
HRAppModuleImpl.java
2.
Double click the source file HRAppModuleImpl.java
to open the code editor.
3.
Now that we have a code editor open,
we can start adding the custom code. The first step is to create the method signature.
Enter the following code after the end of the default constructor.
public Number getDeptSalaryTotal(String dept_id){ return
new Number(0);}
Since we will be using the Oracle implementation
of Number, add an import statement to the top of the class as follows:
import oracle.jbo.domain.Number;
4.
You should compile your class periodically
to make sure that you have not introduced errors in your code that the compiler
will catch. To compile the class, right-click anywhere in the code editor window
and select Make from the context menu.
5.
Check the message window for any compile errors. If there were no errors, the
compilation was successful.
Getting
the Department and Employees View Objects
In this step,
add code to your method that will:
Instantiate
a Departments View Object
Set the where clause
Execute
the query
Set the current row to the first row in the
View Object
Get the related Employees View Object
Loop
through the rows, summarizing the Salary attribute
Before you can use data from the Departments
View Object, you must instantiate it. JDeveloper ADF provides methods that make
this a simple task. To instantiate the view object call getDepartmentsView1()
to your method.
// get a department view object DepartmentsViewImpl
dept = getDepartmentsView1();
2.
Once you have access to the Departments
View object, you can manipulate it by calling standard methods on the object.
In our case, we need to modify the where clause to include the department
ID. Add the following code to your method which:
Sets the where clause
Executes
the query
Sets the current row to the first row of the rowset
public
HRAppModuleImpl() { }
public Number getDeptSalaryTotal (String dept_id)
{ // get a department view object DepartmentsViewImpl dept = this.getDepartmentsView1();
dept.setWhereClause("DEPARTMENT_ID = " + dept_id); dept.executeQuery();
dept.first(); return new Number(0); }
3.
Make sure to compile your code periodically
to find any coding errors you may have introduced.
Next you will use another
method that is part of ADF Business Components to get all of the Employees that
are related to the Department you just retrieved. To get the Employee rows, add
a call to the getEmployeesView3() method.
EmployeesViewImpl
emps = getEmployeesView3();
4.
The ADF Business Components framework
automatically coordinates the master detail relationship between Departments and
Employees. This means the Employee rowset you just created will contain only Employees
that belong to the department you queried in the previous step. Now all you have
to do is loop through the Employee rows and summarize the salary attribute.
Before you can loop through the Rows, you need to import oracle.jbo.Row. JDeveloper
provides automatic advice on import statements. When you enter the following code,
you will notice that JDeveloper underlines the Row object and prompts you to import
oracle.jbo.Row. If you hit Alt + Enter, JDeveloper will add the import
for you. You need to create a temporary RowSetIterator. You will use this
iterator to loop through the employee rows.When you are through with the iterator,
make sure to close it.
Your completed method should look
like the following:
public Number getDeptSalaryTotal(String
dept_id) { // get a department view object DepartmentsViewImpl dept
= getDepartmentsView1(); dept.setWhereClause("DEPARTMENT_ID = "
+ dept_id); dept.executeQuery(); dept.first();
So far, you have created and tested a couple
of default business components. You have also added code to the Application Module
that any client can call to easily get the total salary of a given department.
The next step in this scenario is to create a client application that uses this
method and test it. There are several types of clients we could create; a JSP,
a Java rich-client interface, a UIX client, or a Java command line client. For
the purposes of this exercise, the easiest and quickest is the Java command line
client. JDeveloper provides design-time tools that make this approach fairly easy.
This will also help familiarize you with the JDeveloper IDE.
In the System
Navigator, right-click the Model project and select New from the context
menu.
2.
In the New Gallery, select Simple Files
and Java Class. This will open the Create Java Class Wizard.
3.
In the Java Class Wizard, rename the
class to TestClient. Make sure to check the box that has the wizard create
a Main method for you. Click OK to accept all the other default values.
4.
JDeveloper has now created a simple
Java class named TestClient and has opened it in the editor window. The
next step will be to add the code to test your custom method.
Adding Code to
Instantiate the Application Module
Now that you
have the shell of a simple Java program, you will add the code to instantiate
the Application Module. This will give you access to the objects within that Application
Module. Remember that in ADF Business Components, the application module provides
and controls access to all of its objects. In our case those objects include the
Departments and Employees view objects along with the application module itself.
First, let's create a couple of String
variables to hold the name of the application module and the name of the configuration.
The application module name is whatever you named it when you created the Business
Components. It should be HRAppModule. The default configuration name is
the application module name appended with Local (HRAppModuleLocal). You
also need to include the package name as part of the application module. Add the
following code the your TestClient. The code will go within the Main()
method and replaces the default code "TestClient testClient = new TestClient();"
Next we'll call a method the instantiate
the application module. The method we call accepts two arguments: the application
module name, including the package name, and the configuration name. For the next
few steps, you will import the classes that are required by letting JDeveloper
remind you which ones are needed and hitting Alt+Enter to include the import.
Add the following code:
ApplicationModule am = Configuration.createRootApplicationModule(amDef,
config);
3.
Now that we have an generic application
module, we will need to cast it to our specific application module. This will
allow us access to any application specific code you have added, like your custom
method. Add the following line of code to cast the application module.
HRAppModuleImpl myAm = (HRAppModuleImpl)am;
4.
At this point, you should be able
to compile and run your class. It won't do anything interesting but it will prove
that your code can successfully find and instantiate the application module.
To run the application, right-click anywhere in the code editor window and select
run. Your program should run successfully. Your code should look like the following:
Now that we have an instance of our
application module, we can simply call the method. Remember that the method returns
an oracle.jbo.domain.Number object. The following code calls the method. Notice
that we have hardcoded the department Id. We could have passed an argument to
the program but this is a little easier for now. When you create a more robust
client application, you will call the method with a department number probably
derived from a form field or the like.
Number salaryTotal
= myAm.getDeptSalaryTotal("10");
2.
That last line of code set your salaryTotal
variable to the results of the call. All we have left to do is display the results.
You can display the results by calling System.out.println() with some text concatenated
with salaryTotal variable. The code should look like:
System.out.println("Total
salary for Department 10: " + salaryTotal);
3.
Now we need to do a little housekeeping.
Whenever you create an instance of an application module, you should remove it
when you are done. The last step in creating this test client is to release the
application module. The code for that is:
/** * * @param args */ public static void main(String[] args) {
String amDef = "model.HRAppModule"; String config = "HRAppModuleLocal";
ApplicationModule am = Configuration.createRootApplicationModule(amDef, config);
HRAppModuleImpl myAm = (HRAppModuleImpl)am; Number salaryTotal = myAm.getDeptSalaryTotal("10");
System.out.println ("Total salary for Department 10: " + salaryTotal);
Configuration.releaseRootApplicationModule(am,true); } }
5.
Of course the last step is to run
the TestClient to see the results. Remember, to run an application, right-click
anywhere in the code editor and select Run from the context menu. You will
see the results in the message window at the bottom of the JDeveloper window.
Summary
In
this tutorial you learned how to create a custom method that makes it easier for
client applications to access calculated or derived data. Using custom methods
to provide that specialized data reduces the amount of client coding and therefore
reduces the risk of client applications introducing bugs into the application.
You
have also learned how to test your custom method by creating a Java program that
instantiates your application module and calls the method.