In chapter 2 we have build a data model in the data layer. Now it's time to make the data layer work for us.
This chapter is all about the view layer. We are going to use the data control to build the pages so users can update the reference data like Country and Category. These forms are quite basic so it will be an easy part.
Chapter 4 will be bigger as we will create LOV's for the reference data.
This is an overview of what you will learn in this chapter:
When you build a large application it makes sense to introduce some structure. In the data layer this can be done by building different logical domains. For example you can have an HR domain, finance domain and so on. In the view layer we will do something similar.
Functionality that can stand on its own will be separated. For example a registration form, a master-detail view for employees,... These components all have their own navigation flows and view representations. You may call them components. In ADF these are called taskflows.
The advantage of taskflows is that they can be reused over the entire application. They have their own navigation structure, managed bean and so on. You could also see them as a mini application that needs to be embedded in the application or for people who worked with portals (which might be a few considering you are viewing my blog), taskflows are like portlets but then not standardized.
So enough chit chat let's start building a taskflow and see how it works. This will make things more clear.
We will build a simple taskflow that will allow us to view a table of the available countries and an edit form so we can edit the country.
In chapter 4 we will build the more advanced forms for adding and editing students and teachers.
In order to begin you have to complete the previous chapters. If not, you can also download the application here to start with.
First we need to create the taskflow by right clicking on the VieView project and select New.
Select JSF in the category list and ADF Task Flow in the items list:
Specify countryTF.xml as the filename. The other options can remain unchanged. I will explain these options in later chapters so don't bother to much about them for now.
click OK to create the taskflow.
Now that we have a taskflow we can start adding views on it. A view in a taskflow is a page fragment or an actual page depending on the type of taskflow. In our case it will be a fragment.
Drag and drop the view from the component palette to the taskflow:
Notice that the view has a green circle in the background. This means that this view will be the default activity. When the taskflow will be rendered, this activity will be executed.
Double click on the view. This will open the create page fragment popup.
Specify country.jsff as name and add country as a subdirectory to the folder as shown in the image below:
When we press the OK button the fragment will be loaded in JDeveloper and we can start editing it.
In our case we want to display a table of all the countries in our database. Remember from chapter 2 that we created an application module in the vieModel project. This is exactly where our countries will be exposed.
Open the VieModule from the vieModel project and open the data model tab. You should see something like this:
Now open the data controls section and compare what you see with the Data Model from our application module:
Notice it is the same structure. This is exactly what our Application Module is. It exposed the data model as a data control.
This images above show the generated application module. I don't like it with all those numbers so we are going to remove all the entries in the vieModule and only add those views that we really need. Later on we will add other objects when we need them.
For this case we only need the countryView so when you removed everything from the Data Model, shuttle CountryView to the right and make sure you specify Countries as the new instance name.
Save everything and press the refresh button on the Data Controls section. You should see something like this:
I hope by now the relation between Application Module and Data Controls are clear.
Let's get back to our country.jsff because we still need to display the table. Now's the easy part. Just drag and drop the Countries object from the Data Control on the fragment:
Select Table and ADF Read Only table from the context menu.
In the popup we can configure which columns we want to display in the table. We don't need the ID column so you remove it.
Also make sure you select Single Row in the Row Selection section and Enable Sorting. Press OK to allow JDeveloper to create the table:
So now we have a taskflow that contains a fragment that will display the table of countries. As explained before, a taskflow is a component that needs to be consumed by a page. We cannot simply run the taskflow.
In order to test the TF we need to create a page and add the taskflow to that page so let's do this now.
Press CTRL+N to open the New Gallery.
Select JSF from the Categories and JSF Page from the Items list.
Specify countries.jspx as the filename:
Make sure you select Oracle Three Column Layout. We will use this template for the first few chapters.
Click the OK button to create the page.
Drag and drop the countryTF.xml from the WEB-INF folder into the Center facet of the page:
Select Region from the context menu.
Now the page will consume the taskflow. Right click on the page and select Run:
Depending on what you already created in the database, you should see something similar as this:
Notice that the header of the columns say Country1 and CountryCode. This is because we haven't specified our own value for this.
It might sound strange but we can manage this in the model layer instead of the view layer. This makes sense in a way that all the labels will be managed in the place where the definition of the field is. This also means that everywhere we use that specific field, it will reuse the same label.
Suppose you want to reuse your model in multiple application. Each application has their own view layer. When you specify the labels of the fields in the model layer, you don't have to worry about inconsistency between applications.
So open the Country View from the view package and open the attributes tab.
Select Country1 and select the Edit button:
Open the Control Hints section and specify Country in the Label Text field:
Do the same for CountryCode but specify Country Code as label.
Save everything and press the refresh button in the Data Controls section.
Run the countries.jspx page again:
Notice that the headers are done properly. Also notice we didn't change anything in our actual fragment! Everything was nicely propagated and managed by the framework.
This can be quite overwhelming so now it might be a good time to explain what we just did and what happened behind the scenes.
Let's go back to the country.jsff fragment and examine the code.
One of the most important parts of the code of the table is the value attribute:
The value points to the bindings. In ADF the binding is an additional layer to abstract the access to our model layer. It works with iterators, attribute values, methods and operations to access and manipulate data coming from a data control.
Each page or fragment that is using bindings has a page definition. This is a separate file that contains metadata for the page as well as the binding definitions. At the bottom of your page you should see a few tabs. One of them is the Bindings tab. This will take you to the page definition.
For countries.jsff it looks like this:
Notice that we have a Countries object in the bindings list that points to a CountriesIterator which point the Countries view from the data control.
The iterator is responsible for keeping track of the cursor of the result coming from the database.
The Countries object contains a list of columns you want to expose in the table on the page.
I will explain all of these object in more details later on but for now make sure you understand that they are there and they are created when you drop the Countries view object on a page. It are these objects who are responsible for keeping track of the selected record and which columns are available to your table.
Now that you have basic understanding of taskflows, bindings and so we can focus a little more on building functionality and expand our country taskflow.
We will add an action that will allow us to update a country. As explained before, a taskflow has its own navigation flow and navigation cases. We are going to use those to build a navigation flow from a table view to a fragment that contains the form to edit the country. It know it's a little overkill to crate two separate fragments for such a simple example but it's to explain the concept.
Make sure you have countryTF.xml open. Drag and drop another view next to countryTable and rename the new view to editCountry.
Now we need to create a flow from one view to another. This is done by using the Control Flow Case object. Drag and drop the Control Flow case on the first view. This will be the origin of the flow. Then click on the second view which will be destination. You should see an arrow between them:
Make sure to change the * to edit as shown in the image:
Double click on the editCountry view to create the fragment:
Make sure you add the fragment to the country folder. The application won't brake if you didn't but I just like a nice organized application with a folder for each taskflow.
Now we do the same thing as with our table. Drag and drop the Country object from our data control to the fragment but instead of Table we select ADF Form.
In the next popup we also remove the ID column:
So now we have 2 fragments with a control flow case between them. In order to execute the flow case we need to invoke it and call the edit action.
Open the country.jsff fragment which contains the table and we will add another column that will contains and edit button.
Add following code just before the
The most important part from this code is the commandLink. As you can see, we assign the edit action to it. This matches the control flow case and when we press the button, it will follow the arrow specified by the edit action.
Let's test by running the countries page again.
So now we have an Edit link on each row. When we click it we will navigate to the form:
Also notice that we don't have to write any code to pass the record from one page to another. The reason for this is that the iterator on the first and second fragment are pointing to the same instance which means that they are always pointing to the same record. If you change the cursor in one place, it will also change in the other place.
Notice also that we don't have a save or cancel button. We need those in order to store the changes in the database.
The application module controls the transaction and you have a single transaction per data control. This means that in order to save the changes we have to call the commit operation of our AM. If we want to cancel, we need to call the rollback operation.
You can do this by dropping the commit or rollback operation directly on the edit fragment and it will work but I am going to take a slightly different approach.
Instead of calling the commit or rollback directly, I am going to invoke the methods as a control flow case in the taskflow which will be able to redirect to the table after a cancel or safe.
Drag and drop the Commit and Rollback operation from the data control to the taskflow.
Create a control flow case from editCountry to Commit and call it Save. Do the same to the Rollbaclk and call it Cancel. You should have something like this:
Now we need to create a control flow case from Rollback and Commit back to countryTable:
Now it probably makes more sense why this is called a navigation flow. When we invoke the Save action from the editCountry it will invoke the Commit method. Afterwards it will invoke the Commit action which will show the countryTable view.
The last thing left for us is to create 2 buttons on the form that will invoke the save or cancel action.
Add following code just before the closing
As you can see it will add a panelGroupLayout that will display 2 buttons next to each other. The first one will call the save action and the other one will call the cancel action.
Save everything and rerun the countries page.
When you save, it will automatically reflect the changes in the table as well.
Notice how little code we had to written for all this to work.
By now you should have basic understandings on how taskflows work and how you can create one. You should also be aware on how the data model is exposed from the model to the view layer.
As an exercise you could create a similar taskflow as the countries taskflow but instead of using the countries view, create a taskflow to manage categories.
I will add that taskflow to the downloads for chapter 4 when I release it.
You can also download the application finished in this chapter from here.
If something is not clear or you have additional questions I will happily answer them in the comments section below.