tutorial_medialibrary _ prototype version _ august 2007

Upload: german-sarmiento-diaz

Post on 07-Apr-2018

224 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    1/34

    Media Library Tutorial

    By Fabre Tristan

    Prototype version, the 17th of August 2007

    Abstract:This tutorial introduces how to use Jdeveloper 10g, the ADF BC framework and the

    Oracle 9i RDBMS in order to build a little web application enabling to upload and download

    files. These files will be kept into the database as BLOB and the interfaces of the app will let

    to organize these records depending on their extension and a type chosen by the user. An

    administrator will be able to manage the content of this type list and too the extension and

    their associated mime-type.

    Prior to follow these instructions, assume to have successfully installed Jdeveloper

    (Jdev) 10g and Oracle 9i, and to have created a database (DB) instance.

    Content:

    I. Building the model layer .................................................................................................... 2

    a. Generating the application skeleton ............................................................................... 2

    b. Making the DB schema.................................................................................................. 3

    i. Connecting the DB ..................................................................................................... 3

    ii. Building the DB schema ............................................................................................ 4

    c. Organizing and configuring the app module.................................................................. 8

    i. Generating the Business Components........................................................................8

    ii. Organizing the Business Components........................................................................ 9

    iii. Configuring the Business Components................................................................10

    II. Building the controller layer ............................................................................................ 13

    a. Generating the interface skeleton................................................................................. 13

    i. Configuring the UserInterface project ..................................................................13

    ii. Building and using the faces-config.xml.............................................................. 13

    iii. Adding the source files......................................................................................... 15

    b. Coding the needed methods and functions................................................................... 16i. Controlling the application administrator tasks ....................................................... 16

    ii. Controlling the library tasks..................................................................................... 18

    III. Designing the interfaces ............................................................................................... 24

    a. Generating the administration page.............................................................................. 24

    i. Management of the type list ..................................................................................... 24

    ii. Management of the extensions and the mime-types ................................................ 27

    b. Generating the library page .......................................................................................... 28

    i. Displaying the files................................................................................................... 28

    ii. Enabling to upload new files .................................................................................... 29

    c. Binding the controllers and refining the display .......................................................... 30

    i. On the administration.jspx page ........................................................................... 30ii. On the Library.jspx page ......................................................................................32

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    2/34

    I.Building the model layera.Generating the application skeleton

    The first step to perform is to make the schema of the DB and then to save it underOracle 9I. And before doing that, the future application needs a container to the different

    files.

    Building the application skeleton is quite an easy task under Jdev. Open the

    Application Navigator in the Jdev menu > View, right click on Applications and select

    New Application. Fill the form to correspond to the following screen:

    The creation wizard launches the form enabling the creation of a new project into the

    app; Enter DataModel and accept the default directory. A simple setting to add is the

    default package name. For that right click on the new created project and select Project

    Properties. Select the Project Content facet and change the text field at the bottom of the

    form: Default package which should be medlib has to be change for medlib.datamodel.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    3/34

    b.Making the DB schemai. Connecting the DB

    In Jdev, open the Connection Navigator window in the Jdev menu > View; rightclick on the Database folder and then choose New Database Connection. The wizard

    which is launched includes 4 steps to fill like the followings:

    Step 1: Choose a name for the new connection and select JDBC. This

    name will be referenced in this tutorial by the tag .,

    and to help in the understanding of this tutorial, the

    will be MediaLibraryConnection in all the examples

    Step 2: Use sys, the sys-password defined during the instance creation and

    sysdba to fill the username, the password (DEMLIB here) and the role

    (sysdba). Check the box for Deploy password

    Step 3: Use Thin for the driver. Depending on the Oracle 9i installation,use localhost, 1521 and the SID name for the Oracle DB instance

    created. In the examples, SID will be DEMLIB.

    Step 4: Test the connection. If the test doesnt return Success, go back on

    the preceding steps on try to find what mistake has been done.

    NOTE: In a first time, the connection is created for the sys in order to access the

    SQL*PLUS executable. After creating an empty schema for a specific user, the connection

    will be modified for allowing access only to this user and this schema.

    Select the new connection and in the Jdev menus, open Tools > SQL*PLUS. A

    browser function should be launched to help to find the SQL*PLUS executable. Find it in theOracle9i_Home\ora92\bin\sqlplusw.exe. When prompting for a password, enter MEDLIB,

    and then On the SQL*PLUS page, enter:

    CREATE USER TIF IDENTIFIED BY TIF

    DEFAULT TABLESPACE users

    TEMPORARY TABLESPACE temp

    QUOTA UNLIMITED ON users;

    GRANT connect, resource TO TIF; then press Enter to execute it.

    Now close this window, and right click on the new created connection. Select

    properties, go on authentication and replace the username and its password by TIF and

    TIF. Delete the role, go to the Test facet and check if the new connection parameters are

    correct by testing the connection.

    NOTE: The browse function enabling to select the SQL*PLUS executable is launched at the

    first use of Tools > SQL*PLUS, but you can change this location going to Tools >

    Preferences > Database connections

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    4/34

    ii. Building the DB schemaNow, create the database diagram, by right clicking on the new project and selecting

    New, the database diagram creation wizard is in General > Diagrams. Use

    MedLibDiagram and medlib.datamodel.diagram as name and package for the newdiagram.

    The proposed schema is simple; a table will contain all the files in a Blob field, it will

    be associated to a central table which will support the details about each file uploaded. To

    identify easily the extension and the mime-type to associate, they will be stored in a separate

    table, and finally by adding a last one which contains a type, the application will allow user to

    class the uploaded files in different types like Rock music, Administrative documents,

    Charm pictures, etc.

    => Creating tables

    To make this document shorter, only two table creation processes are entirely

    described here: the DOCS and the DETAILS table.

    NOTE: If the Component palette is not yet displayed when the MedLibDiagram is

    opened, go into the Jdev menus at Views > Component palette or click Ctrl+Maj+P.

    Start by dropping a table from the Component palette and then rename it DOCS

    by double clicking on the title. Now double click on the table to open the wizard enabling to

    add fields, constraints, primary and foreign keys on the table.

    In the Table Information, enter TIF in the Schema. Its important to

    not forget this step during the creation of all the tables and the sequences.

    Select Column Information and add two columns by clicking on the green

    cross. Name the first one DOC_ID and the second DOC_BLOB. With

    the first one selected choose Number, and choose Blob for the second.

    Check the box Cannot be null for the two.

    Now Select the Primary Key Information, and make DOC_ID switching

    from the left panel to the right one

    There is neither constraints nor foreign key on this table, also choose OK

    Drop a new table and rename it DETAILS. Open the wizard:

    Add six columns with names DETAIL_ID, DETAIL_NAME,

    DETAIL_EXTENSION, DETAIL_TYPE, DETAIL_DOC and

    DETAIL_DATE

    Select Date for DETAIL_DATE, Varchar2 (4000) for

    DETAIL_NAME and Number for the other columns.

    Now Select the Primary Key Information, and make DETAIL_ID

    switching from the left panel to the right one

    Add a Unique Constraints Information by making DETAIL_NAME

    switching from the left panel to the right one. That will let to forbidden thesave of two files having the same name.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    5/34

    Now add a Foreign Key: Referenced DOCS on constraint DOC_PKand make matching DETAIL_DOC in the local column to DOC_ID in

    the referenced column on DOCS. Finally choose OK.

    Add still two tables EXTENSIONS and TYPES, and then edit DETAILS to add

    their ID in the foreign keys.

    => Creating sequences

    On each table, create a sequence:

    Dont forget to enter TIF in the Schema text field.

    Drop a sequence on the diagram per table and name it with the name of the

    table without the S it refers, plus _SEQ.

    Double click on the sequence to open a new wizard.

    Use 1 for the Increment and 200 for the Start with.Enter 1 and 999999999 for the Min and the Max value

    Finally check the box Cache and enter 20 in the associated text field

    These sequences will enable to generate automatically different ID for each new entry

    in the different tables. But to use these sequences, some triggers are needed.

    => Conciliating the complete schema to the DB

    The complete schema is the following:

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    6/34

    When schema is complete, it has to be reconciled to the DB. Automatically, Jdev has

    built the Offline Database Sources which are an offline copy of the elements contained in

    the schema. The folder containing these sources should have name MYSCHEMA. Right

    click on it and choose Generate or Reconcile Objects:

    Step 1: Switch the 4 table elements except DETAILS (to assume the othertables will exist before trying to create the foreign keys) to the Selected

    panel. The tables have to be created before trying to generate the sequence.

    Step 2: Choose CREATE Objects. Functions REPLACE and ALTER

    can be used when objects already exists in the DB.

    Step 3: Uncheck Generate SQL Scripts. Checking this option has no

    consequences on this tutorial and can be done for having a look on the way

    of SQL generates the DB objects.

    Step 4: Check Perform Operations Against Database. Choose for

    Connection the MediaLibraryConnection and for Schema the name

    given to the DB user which is TIF.

    Step 5: Check the summary before to accept it. Until clicking on End, theOracle DB schema TIF is still empty and that action will populate it. Now,

    complete the table creation by clicking on End and check the pop up

    message. This message confirms the table creation.

    Step 6: Now, reconcile the last table DETAILS by repeating step 1 to 5

    with switching only this table.

    Step 7: Finally, reconcile the sequences by repeating the step 1 to 5 with

    switching only the sequences.

    NOTE: Its possible to reconcile offline objects to the DB by right clicking on the schema and

    selecting Generate > Data Definition Language For Database.

    => Creating triggers

    On each sequence, the DB needs a trigger to know when use it:

    Open the Connection Navigator window in the Jdev menu > View, and

    drilldown the MediaLibraryConnection > TIF > Triggers. Then right click

    and choose New Trigger

    Enter ASSIGN_DOC_ID in the Name textfield, select DOC table and

    check the Insert box before clicking on OK.The new trigger is created on the DOC table. Double click on it in the

    Triggers folder. That opens it in the principal window.

    Finally cut and paste the part of the code corresponding to the

    ASSIGN_DOC_ID trigger from the following:

    TRIGGER ASSIGN_DOC_ID BEFORE INSERT ON DOC

    FOR EACH ROW

    BEGINIF :NEW.DOC_ID IS NULL OR :NEW.DOC_ID < 0 THEN

    SELECT DOC_SEQ.NEXTVAL

    INTO :NEW.DOC_ID

    FROM DUAL;END IF;

    END;

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    7/34

    TRIGGER ASSIGN_DETAIL_ID BEFORE INSERT ON DETAILS

    FOR EACH ROW

    BEGIN

    IF :NEW.DETAIL_ID IS NULL OR :NEW.DETAIL_ID < 0 THEN

    SELECT DETAIL_SEQ.NEXTVAL

    INTO :NEW.DETAIL_ID

    FROM DUAL;END IF;

    END;

    TRIGGER ASSIGN_EXTENSION_ID BEFORE INSERT ON EXTENSION

    FOR EACH ROW

    BEGIN

    IF :NEW.EXTENSION_ID IS NULL OR :NEW.EXTENSION_ID < 0 THEN

    SELECT EXTENSION_SEQ.NEXTVAL

    INTO :NEW.EXTENSION_ID

    FROM DUAL;

    END IF;

    END;

    TRIGGER ASSIGN_TYPE_ID BEFORE INSERT ON TYPE

    FOR EACH ROW

    BEGIN

    IF :NEW.TYPE_ID IS NULL OR :NEW.TYPE_ID < 0 THEN

    SELECT TYPE_SEQ.NEXTVAL

    INTO :NEW.TYPE_ID

    FROM DUAL;

    END IF;

    END;

    Build the three others triggers by adapting the preceding steps. In the Connection

    Navigator window, the existing objects should match the following screen:

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    8/34

    c.Organizing and configuring the app moduleThe Db is ready to use and the Offline Database Sources should reflect it. These

    sources will be very useful to make the app evolving by adding tables and columns in the

    existing schema.

    The next step is to produce the Entity Objects (EO), the View Objects (VO) and the

    View Link (VL) which will provide the model layer, and then to organize them to build the

    Application Module (AM).

    i. Generating the Business ComponentsThe objective is to obtain the following architecture:

    Jdev enables, thanks to the Application Development Framework Business

    Components (ADF BC), to build very quickly and easily the model layer. Right click on the

    datamodel package and select new Business Components from Tables:

    Step 1 creating the EO: Click on the Query button, and switch all the 4

    tables into the Selected panel.

    Step 2 creating the Updatable VO: Switch all the 4 tables into the

    Selected panel.

    Step 3 creating the Read-only VO: No read-only VO has to be created.

    Step 4 creating the AM: Check the box Application Module and enter

    MedLibModule in the field Name.

    Step 5 creating the Business Component Diagram: uncheck the box, and

    click on Next.

    Step 6 summary: The displayed summary should match the following, ifnot, cancel the creation and start again the creation at step 1:

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    9/34

    ii. Organizing the Business ComponentsTo understand the circulation of the information through the model layer and facilitate

    future maintenance, a good way is to reorganize the business components.

    => Organizing EO and their corresponding Associations

    Select the 4 EO (Details, Docs, Extensions and Types). Right click and

    choose Refactor > Move. Enter the path medlib.datamodel.entities, click on Ok and

    accept the creation of the new folder.

    Select the 3 Associations (DetailsDocFk1Assoc, DetailsExtensionFk1Assoc and

    DetailsTypeFk1Assoc). Right click and choose Refactor > Move. Enter the path

    medlib.datamodel.entities.associations, click on Ok and accept the creation of the newfolder.

    => Organizing VO and their corresponding VL

    Select the 4 VO (DetailsView, DocsView, ExtensionsView and TypesView).

    Right click and choose Refactor > Move. Enter the path medlib.datamodel.viewobjects,

    click on Ok and accept the creation of the new folder.

    Select the 3 VL (DetailsDocFk1Link, DetailsExtensionFk1Link and

    DetailsTypeFk1Link). Right click and choose Refactor > Move. Enter the pathmedlib.datamodel.viewobjects.links, click on Ok and accept the creation of the new

    folder.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    10/34

    The result of this reorganization matches the following screen:

    iii. Configuring the Business ComponentsThe Business Components provide a quite easy and fast way to perform a lot of

    complex tasks like handling the transactions between the database and the model layer or

    managing the way of displaying the data through the interface.

    => Configuring the EO:

    Different tasks can be performed on the EO; the following is a short sample list:

    Customizing the EO attributes, like fixing the ID of each table to a

    DBsequence type, adding default values if needed, fixing the labels to

    display at run time.

    Adding validation rules to force values to match some regular expressions or

    to belong to a fixed list

    Generating associated Java files to add custom code functionalities.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    11/34

    The first task to perform is to fix the ID of each EO on the DBSequence type:

    Double click on the EO, expand the attribute node and select the ID attribute.

    Use the Type drop down list to find DBSequence.

    Keep the other default values, click on Apply then on Ok.

    Repeat these simple operations for each one of the EO.

    Now, change the labels to customize the future interface displays:

    For the Extensions and the Types EO, double click on the EO, expand

    the attribute node and select one of the non ID attribute.

    Click on the Control Hints tab.

    In the Label Text field, enter Extension Name, Type Name, Mime-

    type or Type Definition depending on the selected attribute.

    In the Display width field, type 25 (except for the Type Definition where

    this value has to be fixed to 50)

    Repeat these simple operations until have fixed Label Text and Displaywidth for each one of the four attributes.

    Now repeat these steps for the Details EO. DetailName should have

    label File Name and width = 50. DetailDate take 10 and Upload Date

    for values.

    => Configuring the VO:

    In complex app, many VOs are built on each EO depending on the different operations

    to carry out. That explain why its possible to refine again the future interface displays;

    default behaviour for each VO is to take values from the EO but if any value has been set in a

    VO, it will display it:

    In the MediaLibrary app, there is no need for specific customization of the VO, but a

    not yet existing VO is needed. To create it right click on the viewobjects package, and then

    choose New View Object:

    Step 1: Just change Name empty field to AllFilesAndDetails and go to

    the next step

    Step 2: In the medlib.datamodel.entities package displayed in the left

    window, find Details and switch it to the right window. Verify the

    Updatable is checked when the Details in the right panel is selected.Switch the three other EO assuming the Association list is correctly

    populated and only the Reference box is checked for each of them (default

    behaviour).

    Step 3: Switch all the attributes from left to right

    Step 5: (Just keep default on step 4) Add Types.TYPE_NAME ASC ,

    Extensions.EXTENSION_NAME ASC , Details.DETAIL_NAME ASC in

    the Order By text field and keep other default values. Click on Finish to

    create the VO.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    12/34

    => Building the AM:

    The Application Module let the interface interacts via the controllers to the model. The

    way the VO will be available in the AM has to be configured:

    Double click on the AM to editing itGet the right panel empty of the nested VO by selecting them one by one and

    using the blue arrow. The AM is populated by default, but there is no need

    for these complex relationships (search for master - detail) in the app.

    Expand the medlib.datamodel.viewobjects package (central panel) to find

    the AllFilesAndDetails VO, and switch it to the right panel

    Click on Apply and on Ok.

    The complete AM looks like the following screen:

    NOTE: Its important to save regularly the current progress. The use of Make and

    Rebuild is another think to keep in mind; java has to be compiled to work.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    13/34

    II.Building the controller layera.Generating the interface skeleton

    Like in the first part of the tutorial, the application has to be structured in a newproject which will contain the files for the interface and the controllers.

    i. Configuring the UserInterface projectRight click on the MediaLibrary application and select New Project. In the left

    panel, choose General > Projects, and select Empty Project in the right panel. Fill the

    Project Name text field with UserInterface and keep the default value for the directory.

    Right click on the new created project and choose Project Properties. In the left panel select

    the Project Content node and at the bottom of the right panel find the Default Package

    and type medlib.userinterface. Now choose Dependancies in the left panel and check thebox DataModel.jpr to assume the two layers are connected together.

    ii. Building and using the faces-config.xmlRight click on the UserInterface project and choose New. Drill down the Web

    Tier node, select the JSF and choose JSP Page Flow in the right panel. After clicking

    on OK, keep the default values for File Name and Directory Name. The new file is

    opened in the principal window on the Diagram facet; just open the Component Palette

    by clicking on Ctrl+Maj+P or by getting in the Jdev menus > View > Component Palette.

    => Imagining the workflow:

    By using drag and drop, Jdev enables to build very quickly the complete application

    navigation and skeleton.

    Drop two JSF Page onto the diagram. Then drop two JSF Navigation Case going

    from one page to the second. Finally change the names of the page and the navigation arrows

    in way to match the following screen shot:

    NOTE: The yellow warning signals mean these pages dont yet exist. Have a look on the tab

    Source, the underlining lines have the same signification.

    => Building a template for the pages:

    Building a template is very useful to generate quickly similar pages and so giving anapplication a unified look and feel.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    14/34

    Right click on the WEB-INF project and choose New. Drill down the Web

    Tier node, select the JSF and choose JSF JSP:

    Step 1: Enter template.jspx in the File Name field and add \template to

    the default entry in Directory Name. Assume to have checked the JSP

    Document box

    Step 2: Check Do Not AutomaticallyStep 3: Assume you have selected (in the right panel), the ADF Faces

    Components, ADF Faces HTML, JSF Core 1.0 and JSF HTML

    1.0 libraries.

    Step 4: Here, you could add a personal touch, but just click on Finish.

    The new template appears in the principal window. Drop on it the PanelPage

    component from the ADF Faces Core elements (from Component Palette). Then Drop a

    MenuBar and two PanelGroup components. These different containers will be use in the

    pages.

    => Generate the pages and apply the template:

    Reopen the faces-config.xml if it was closed. Double click on one of the two pages.

    That will launch the Cerate JSF JSP wizard with all the correct settings, so just click on

    next if you want to check the steps, or directly click on Finish. Repeat this action for the

    second page.

    NOTE: The yellow warning signals have disappeared.

    In the Application Navigator, select the template.jspx file. The Structure

    window shows the content of the file. Find the afh:html node, right click on it and choose

    Copy. Next find one of the two pages, find the node html, delete it and paste on the

    f:view the node you have copied. Do the same on the second page.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    15/34

    iii. Adding the source filesThe source files will contain all the classes, functions and methods enabling to control

    the information flow coming from the interface.

    => Using some utility files:

    In a first time, its interesting to add some utility files which will provide the future

    beans some common functions and methods.

    In the Application Navigator, right click on the Application Sources folder. Then

    choose in the left panel, the tab General, then in the right panel the Java Class option. Fill

    the form to match this one:

    Repeat these steps two times with using JSFUtils and FileOperations for the class

    names. Copy the content from appendix to the corresponding Java class.

    => Completing the web.xml:

    Add the following tags to the web.xml:

    javax.faces.STATE_SAVING_METHOD

    client

    CpxFileName

    dfly.userinterface.DataBindings

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    16/34

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    17/34

    The new class is created but has to be declared into the faces-config.xml to be used:

    Step 1: Open the faces-config.xml in the principal window by a double

    click on it in the Application Navigator window.

    Step 2: With the Overview tab selected, choose the Managed beans and

    click on the button New.Step 3: Enter LibraryBean in the Name field and

    userinterface.view.backing.LibraryBean in the field Class. This second

    text can be obtained by using the Browse button and selecting the class

    LibraryBean. Finally keep the Request scope and the box Generate

    checked, then press Ok.

    This bean will have to be bound to the interface context. To enable this, more

    declarations are needed:

    With the LibraryBean selected into the Managed Beans panel, expand

    the Managed Properties panel with the black array and add a new property

    with the New button.Insert bindings in the Name field and accept the form.

    Now, with the new Managed properties selected, change the Value in the

    Managed property panel from null to #{bindings}.

    => Written the needed code:

    In order to edit it, open the LibraryBean.java file if it is not already opened:

    Copy the lines below in the Public Class LibraryBean between the braces:

    Right click on the word bindings, then choose Generate Accessors.

    Check all the boxes in order to generate the getters and the setters for the

    three new attributes.

    The code editor automatically imports the corresponding libraries, also the

    following lines have been created:

    Now write the function enabling to switch the display:

    public String administrationSwitchDisplay() {

    if (this.getAdministrationTypesPanelGroup().isRendered()) {

    // If the page displays the types management form// Don't display it any more

    this.getAdministrationTypesPanelGroup().setRendered(false);

    // And display the extension management form

    this.getAdministrationExtensionsPanelGroup().setRendered(true);

    } else {

    // Else display itthis.getAdministrationTypesPanelGroup().setRendered(true);

    // And don't display the extension management form

    this.getAdministrationExtensionsPanelGroup().setRendered(false);}

    return null; // To stay on the same page

    import oracle.adf.view.faces.component.core.layout.CorePanelGroup;

    import oracle.binding.BindingContainer;

    private BindingContainer bindings;

    private CorePanelGroup administrationTypesPanelGroup;

    private CorePanelGroup administrationExtensionsPanelGroup;

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    18/34

    ii. Controlling the library tasksThe library has to enable to download the selected file and to upload new ones. The

    upload process is composed by a selection in a drop down list for the type to associate to the

    file and then by the selection of the file itself.

    => Adding the functions for switching the display:

    In order to edit it, open the LibraryBean.java file if it is not already opened:

    Build the following attributes in the LibraryBean class:

    Generate all the corresponding accessors.

    The code editor has imported the following class:

    Finally, add the three following functions:

    public String libraryDownloadSwitchDisplay() {

    if (this.getLibraryDownloadSelectionPanelHeader().isRendered()) {

    this.getLibraryDownloadSelectionPanelHeader().setRendered(false);

    this.getLibraryDownloadConfirmationPanelHeader().setRendered(true);

    } else {

    this.getLibraryDownloadSelectionPanelHeader().setRendered(true);

    this.getLibraryDownloadConfirmationPanelHeader().setRendered(false);

    }

    return null;

    }

    public String librarySwitchDisplay() {

    if (this.getLibraryDownloadPanelGroup().isRendered()) {this.getLibraryDownloadPanelGroup().setRendered(false);

    this.getLibraryUploadPanelGroup().setRendered(true);

    this.getLibraryUploadTypeSelectionPanelbox().setRendered(true);

    this.getLibraryUploadFileSelectionPanelbox().setRendered(false);

    } else {this.getLibraryDownloadPanelGroup().setRendered(true);

    this.getLibraryUploadPanelGroup().setRendered(false);

    this.getLibraryDownloadSelectionPanelHeader().setRendered(true);

    this.getLibraryDownloadConfirmationPanelHeader().setRendered(false);

    }return null;

    import oracle.adf.view.faces.component.core.layout.CorePanelHeader;

    import oracle.adf.view.faces.component.core.layout.CorePanelBox;

    private CorePanelGroup LibraryDownloadPanelGroup;

    private CorePanelHeader LibraryDownloadSelectionPanelHeader;

    private CorePanelHeader LibraryDownloadConfirmationPanelHeader;

    private CorePanelGroup LibraryUploadPanelGroup;

    private CorePanelBox LibraryUploadTypeSelectionPanelheader;

    private CorePanelBox LibraryUploadFileSelectionPanelHeader;

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    19/34

    => Adding controllers for uploading files:

    The first step, in order to upload a new file into the library, is to choose in a list the

    type which will be associated to this file

    In order to get the selected type, copy the following function:

    To confirm the choice and going to the page enabling to select the file to

    upload, the simplest solution is to use the preceding

    libraryUploadSwitchDisplay function.

    Now add two functions to extract the name and the extension of the selected

    file:

    public Integer findTheSelectedTypeFromList4UploadingNewFile() {DCIteratorBinding typeIter = ADFUtils.getIterator("TypesView1");

    Row r = typeIter.getCurrentRow();

    Integer typeID =

    new Integer(0).valueOf((String)r.getAttribute("TypeId").toString());

    return typeID;

    }

    /**

    * Enable to read the name a document by cuting its extension

    * @param filename The complete name of a document

    * @return String Return the name of the document without its extension

    */

    public static String findExactName(String filename) {String[] tests = filename.toLowerCase().split("\\.");

    Integer i = null;

    for (i = 1; i < tests.length - 1; i++) {

    tests[i] = tests[i - 1].concat("." + tests[i]);}

    return tests[tests.length - 2];

    }

    /**

    * Enable to read the extension of a document by cuting its name

    * @param fileName The complete extension of a document with the initial dot

    * @return String Return the extension of the document without its name

    */

    public static String getExtensionFromFileName(String fileName) {

    String[] tests = fileName.toLowerCase().split("\\.");

    return "." + tests[tests.length - 1];

    }

    public String libraryUploadSwtichDisplay() {

    if (this.getLibraryUploadTypeSelectionPanelheader().isRendered()) {

    this.getLibraryUploadTypeSelectionPanelheader().setRendered(false);

    this.getLibraryUploadFileSelectionPanelHeader().setRendered(true);

    } else {

    this.getLibraryUploadTypeSelectionPanelheader().setRendered(true);

    this.getLibraryUploadFileSelectionPanelHeader().setRendered(false);}

    return null;

    }

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    20/34

    To simplify the use of the library, its very useful to control the extensions of

    the uploaded files and to create them if they are not yet existing:

    /**

    * Test if an extension name exists in an iterator based on the extension Db table

    * @param extensionName, the extension name to look for* @return Boolean, True if the extension name is already existing in the database

    */

    public Boolean extensionExist(String extensionName) {

    Boolean result = false;

    String testExtension = null;

    DCBindingContainer dcBindings =

    (DCBindingContainer)ADFUtils.findBindingContainer(getBindings(),

    "app_administrationPageDef");

    DCIteratorBinding docExtensionIter =dcBindings.findIteratorBinding("ExtensionsView1Iterator");

    ViewObject docExtensionVO = docExtensionIter.getViewObject();

    docExtensionVO.clearCache();

    docExtensionVO.executeQuery();if (docExtensionVO.getEstimatedRowCount() != 0) {

    testExtension =docExtensionVO.first().getAttribute("ExtensionName").toString();

    if (testExtension.matches(extensionName)) {

    result = true;

    }

    if (docExtensionVO.getEstimatedRowCount() > 1) {

    for (Integer i = 1; i < docExtensionVO.getEstimatedRowCount();i++) {

    testExtension =

    docExtensionVO.next().getAttribute("ExtensionName").toString();

    if (testExtension.matches(extensionName)) {

    result = true; }}}}return result;

    }

    /**

    * Add an extension to the existing one in the database

    * @param fileExtension* @return the new extension Id

    */

    public Integer createAnExtension(String fileExtension) {DBSequence newExtensionId =

    new DBSequence("EXTENSION_SEQ",

    ADFUtils.getApplicationModule("MedLibModule"));

    DCBindingContainer dcBindings =

    (DCBindingContainer)ADFUtils.findBindingContainer(getBindings(),

    "app_administrationPageDef");

    DCIteratorBinding docExtensionIter =

    dcBindings.findIteratorBinding("ExtensionsView1Iterator");

    docExtensionIter.getViewObject().clearCache();

    docExtensionIter.getViewObject().executeQuery();Row newRow = docExtensionIter.getViewObject().createRow();

    newRow.setAttribute("ExtensionId", newExtensionId);

    newRow.setAttribute("ExtensionName", fileExtension);

    docExtensionIter.getViewObject().insertRow(newRow);

    OperationBinding operationBinding =

    dcBindings.getOperationBinding("Commit");

    Object result = operationBinding.execute();

    return new Integer(newExtensionId.toString());

    }

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    21/34

    Finally it misses only the functions creating the BLOB with its details and

    the function which will be called from the interface:

    /**

    * Find the extension ID corresponding to the given extension name

    * @param extensionName, the extension name to look for

    * @return Integer, the extension ID of interest

    */

    public Integer findAnExtensionFromName(String extensionName) {

    Integer resultingExtensionId = 0;String testExtension = null;

    DCBindingContainer dcBindings =

    (DCBindingContainer)ADFUtils.findBindingContainer(getBindings(),

    "app_administrationPageDef");DCIteratorBinding docExtensionIter =

    dcBindings.findIteratorBinding("ExtensionsView1Iterator");

    ViewObject docExtensionVO = docExtensionIter.getViewObject();

    docExtensionVO.clearCache();

    docExtensionVO.executeQuery();

    if (extensionExist(extensionName.toLowerCase())) {if (docExtensionVO.getEstimatedRowCount() != 0) {

    testExtension =

    docExtensionVO.first().getAttribute("ExtensionName").toString().toLowerCase();

    if (testExtension.matches(extensionName)) {

    resultingExtensionId =new

    Integer(0).valueOf(docExtensionVO.getCurrentRow().getAttribute("ExtensionId").toString

    ().toLowerCase());

    }

    }

    if (docExtensionVO.getEstimatedRowCount() > 1) {for (Integer i = 1; i < docExtensionVO.getEstimatedRowCount();

    i++) {

    testExtension =

    docExtensionVO.next().getAttribute("ExtensionName").toString().toLowerCase();

    if (testExtension.matches(extensionName)) {

    resultingExtensionId =

    new

    Integer(0).valueOf(docExtensionVO.getCurrentRow().getAttribute("ExtensionId").toString

    ().toLowerCase());

    }

    }

    }

    }

    return resultingExtensionId;

    }

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    22/34

    public void createTheDocumentDetails(Integer docBlob) {

    DCIteratorBinding docDetailsIter =

    ((DCBindingContainer)getBindings()).findIteratorBinding("AllFilesAndDetails1Iterator");

    ViewObject allFilesAndDetails = docDetailsIter.getViewObject();

    Row newRow = allFilesAndDetails.createRow();newRow.setAttribute("DetailId", -1);

    newRow.setAttribute("DetailName", findExactName(uploadedFile.getFilename()));

    Integer docExtension = 0;

    if (extensionExist(this.getExtensionFromFileName(uploadedFile.getFilename()))) {

    docExtension =

    this.findAnExtensionFromName(this.getExtensionFromFileName(uploadedFile.getFilena

    me()));

    } else {

    docExtension =

    this.createAnExtension(this.getExtensionFromFileName(uploadedFile.getFilename()));

    }

    newRow.setAttribute("DetailExtension", docExtension);

    newRow.setAttribute("DetailType",

    findTheSelectedTypeFromList4UploadingNewFile());

    newRow.setAttribute("DetailDoc", docBlob);

    java.sql.Date docDate = new java.sql.Date(new Date().getTime());

    newRow.setAttribute("DetailDate", new oracle.jbo.domain.Date(docDate));

    allFilesAndDetails.insertRow(newRow);

    OperationBinding operationBinding =

    getBindings().getOperationBinding("Commit");

    Object result = operationBinding.execute();}

    public Integer createTheDocumentBlob(BlobDomain file) {

    DBSequence newBlobId =

    new DBSequence("DOC_SEQ",

    ADFUtils.getApplicationModule("MedLibModule"));

    DCIteratorBinding docBlobIter =

    ((DCBindingContainer)getBindings()).findIteratorBinding("DocsView1Iterator");

    ViewObject docBlob = docBlobIter.getViewObject();Row newRow = docBlob.createRow();

    newRow.setAttribute("DocId", newBlobId);

    newRow.setAttribute("DocBlob", file);

    docBlob.insertRow(newRow);OperationBinding operationBinding =

    getBindings().getOperationBinding("Commit");

    Object result = operationBinding.execute();

    return new Integer(newBlobId.toString());

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    23/34

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    24/34

    III.Designing the interfacesa.Generating the administration page

    The administrator of the application will use this page to manage the content of the

    type list proposed to the user. Actually each user will have to select a type in this list to

    classify the file he is uploading. This page will enable too to add or remove some of the

    allowed extensions and to change if needed the mime-type associated to the existing

    extensions.

    i. Management of the type list=> Building the table:

    Open the Adiministration.jspx page from the Application Navigator, and the

    Structure Navigator, the Component Palette and the Data Control Palette from the Jdev

    menu.

    From the Data Control Palette:

    Find the TypesView1, drag and drop it on the first panel group

    Select Table and ADF Table.

    In the wizard, delete the field TypeId and check the Enable sorting and

    the Enable selection boxes.

    => Adding the specific functionalities:

    The table will display the possible document types. The administrator will need to be

    able to save the changes brought to these types, but too to add and to delete them if needed.

    From the Data Control Palette:

    Expand the TypesView1 collection to find the proposed actions.

    From the Operations folder, drag and drop the Execute action on the

    Submit button located in the table. Choose Bind existing

    CommandButton.

    Now, repeat this step with the Delete action and with choosing ADF

    Command Button.

    public String downloadAction() {

    DCIteratorBinding blobIter = ADFUtils.getIterator("AllFilesAndDetails1");

    Row r = blobIter.getCurrentRow();

    BlobDomain file = (BlobDomain)r.getAttribute("DocBlob");

    String fileName = (String)r.getAttribute("DetailName");

    String fileExtension = (String)r.getAttribute("ExtensionName");

    String fileMimeType = (String)r.getAttribute("ExtensionMimetype");FileOperations.downloadFile(fileName, fileExtension, fileMimeType,

    file);

    //ADFUtils.executeOperation("app_LibraryPageDef", "Execute");

    return libraryDownloadSwitchDisplay();

    }

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    25/34

    The Structure window should look like the following:

    Under the Table facets are present different facets. The Selection facet, into which

    have been dropped the two buttons,

    From the Data Control Palette:From the Operations folder, drag and drop the Create action on the

    actions facet. Choose ADF Command Button.

    Right click on the new command button and choose Edit Command

    Button.

    In the Select an action drop down list, select Create insert.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    26/34

    => Running the page:

    The Administration.jspx page should look like the following:

    Its possible to run the page by a right click on the page then select Run. The actions

    delete and create can be used, but there is no way for saving the data until now. Actually these

    actions enable to modify the collection build from the content of the database and the

    Execute action will submit the changes to the database, but the transactions have to be

    committed to the database to be saved permanently.

    => Adding the common functionalities:

    From the Data Control Palette:

    Collapse the TypesView1 collection and find the Operations folder

    located under the node MedLibModuleDataControl.

    Drag and drop the Commit and the Rollback actions on the MenuBarinto the page with choosing ADF Command Button.

    From the Component Palette:

    Drag and drop the Command Button component on the MenuBar into

    the page

    This button will enable to switch the administration panels between the tables for the

    type and for the extension management

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    27/34

    ii. Management of the extensions and the mime-types=> Building the table:

    From the Data Control Palette:

    Find the ExtensionsView1, drag and drop it on the second panel group

    Select Table and ADF Table.

    In the wizard, delete the field ExtensionId and check the Enable sorting

    and the Enable selection boxes.

    => Adding the specific functionalities:

    The table will display the possible document extensions and their associated mime-

    types. The administrator will need to be able to save the changes brought to these details, but

    too to add and to delete them if needed.

    NOTE: More information about MIME: http://en.wikipedia.org/wiki/MIME

    From the Data Control Palette:

    Expand the ExtensionsView1 collection to find the proposed actions.

    From the Operations folder, drag and drop the Execute action on the

    Submit button located in the table. Choose Bind existing

    CommandButton.

    Now, repeat this step with the Delete action and with choosing ADF

    Command Button.

    From the Operations folder, drag and drop the Create action on theactions facet. Choose ADF Command Button.

    Right click on the new command button and choose Edit Command

    Button.

    In the Select an action drop down list, select Create insert.

    => Running the page:

    The Administration.jspx page should now look like the following:

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    28/34

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    29/34

    => Adding the specific functionalities:

    The table will display all the files and users will need to be able to download the

    selected one and to upload new one.

    From the Data Control Palette:

    Expand the AllFilesAndDetails1 collection to find the proposed actions.

    From the Operations folder, drag and drop the Delete action on the

    Submit button located in the table. Choose Bind existing

    CommandButton.

    From the Component Palette:

    Drag and drop a Command Button component on the new Delete button

    with choosing ADF Command Button. It will be used for downloading the

    selected entry.

    Drag and drop a second Command Button component on the MenuBarinto the page. It will enable user to switch to the upload panel.

    ii. Enabling to upload new files=> Building the global layout:

    From the Component Palette:

    Drag and drop two PanelBox components into the second panel group,

    then drop one PanelHorizontal in the first box and two in the second.

    Into the first PanelHorizontal, drop an OutputText component, and in theProperty inspector window, type Select a type into which classify your

    file in the Value property.

    Into the first PanelHorizontal of the second panel box, drop an InputFile

    component and change its Label property into Select the file to upload.

    Finally, in the second PanelHorizontal of this panel box, drop a

    PanelButtonBar, then add into it two Command Button components

    From the Data Control Palette:

    Drag and drop the TypesView1 collection into the first PanelBox in the

    second PanelGroup of the page.

    Select Table and ADF Table.Make the wizard matching the following screen shot:

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    30/34

    In the Structure window, the page should now look like the following:

    c.Binding the controllers and refining the displayIts now time for binding the interfaces with their controllers and to associate the

    corresponding labels in order to finalize the application

    i. On the administration.jspx page=> Binding the actions:

    Only one action is needed on this page, the one which will enable to switch from the

    types management form and the extension management form

    Using the Structure and the Property Inspector windows:

    Find and select the first PanelGroup

    In the Property inspector, enter AdministrationTypePanel in the Id

    field

    Click in the Binding field then on the little button with the three dots. A

    wizard appears which enables to associate the panel group component with a

    bean.Select LibraryBean in the first list and administrationTypesPanelGroup

    in the second. The field should take the value:

    #{LibraryBean.administrationTypesPanelGroup}.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    31/34

    Repeat these operations for the second panel group:

    Find and select the second PanelGroup

    In the Property inspector, enter AdministrationExtensionPanel in the

    Id field

    Click in the Binding field then on the little button with the three dots. Awizard, enabling to associate the panel group component with a bean,

    appears.

    Select LibraryBean in the first list and

    administrationExtensionsPanelGroup in the second. The field should take

    the value: #{LibraryBean.administrationExtensionsPanelGroup}.

    Now add the function under the command button:

    Expand the menuBar and select the commandButton 1

    In the Property inspector, click on the Action property then on the little

    button with the three dots. A wizard appears to associate a button to an action

    declared in a bean.Select LibraryBean in the first list and administrationSwitchDisplay in

    the second. The field should take the value:

    #{LibraryBean.administrationSwitchDisplay}.

    => Refining the display:

    Some labels have been built automatically and also need to be changed in order to be

    more understandable. The only label which really needs to be changed on this page is the one

    displayed on the command button commandButton 1. This button has to display Go to

    Extension Management or Go to Types Management depending on which table is

    displayed in the page. To carry out this complex display the best way is to use the

    Expression Language.

    NOTE: More information about the Unified Expression Language:

    http://en.wikipedia.org/wiki/Unified_Expression_Language

    Using the Structure and the Property Inspector windows:

    Find and select the command button commandButton 1

    In the Property inspector, click on the Text property then on the little

    button with the three dots. A wizard appears to build the button label.Expand JSF Managed Beans > LibraryBean >

    administrationTypesPanelGroup and double click on the rendered

    attribute.

    Finally modify the proposed expression to obtain the following:

    Do the same for the three buttons on the extension table:

    Find and select the command button Create1and rename it in the property

    inspector with Create.

    Find Execute1 and Delete1, then change them for Execute andDelete.

    #{LibraryBean.administrationTypesPanelGroup.rendered? 'Go to Extensions Management':'Go to

    Types Management'}

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    32/34

    Finally, make the document extensions management panel disappearing:

    Select the second PanelGroup.

    From the Properties Inspector, find the attribute Rendered and set it to

    false.

    ii. On the Library.jspx page=> Adding some needed binding:

    To enable the upload of new file, the page needs to be associated to the VO controlling

    the access to the table Docs which contains the BLOBs:

    Right click on the Library.jspx page and select Go to Page Definition.

    In the Structure Inspector, find the executables folder, right click on it

    and select Insert inside executables > iterator.From the wizard, select the DocsView1 and accept.

    Now, in the Structure Inspector, find the bindings folder, right click on it

    and select Insert inside executables > table.

    In the Select an Iterator drop down list, find DocsView1 then assume the

    two attributes are in the right panel called Display Attributes.

    To confirm the changes made into the database, its needed to commit them. This

    action will be called from the bean but need to exist in the bindings:

    Now, in the Structure Inspector, find the bindings folder, right click on it

    and select Insert inside executables > action.

    In the Data Collection panel, click on the MedLibDataControl item andin the Select an action list choose Commit (with a French version the

    label is Valider, in this case accept in then in the action id change it for

    Commit)

    => Binding the actions:

    To be able to upload files from the Library page, the Form which contains all the

    component has to be change from the current which is a JSF one to an ADF one.

    Open the Library page if needed, and click on the Sources tab.

    Find the tags and and change them for and .

    Return on the Design facet and select the af:form in the Structure

    window.

    Find the attribute UsesUpload in the Properties Inspector and set it to

    true.

    Five different actions are needed on this page: uploading and downloading files, and

    the three actions enabling to switch the display between the two panel groups and between the

    two panel boxes and the two panel headers inside of each pane l group.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    33/34

    Using the Structure and the Property Inspector windows:

    Find and select the first PanelGroup

    In the Property inspector, enter LibraryDownloadPanelGroup in the Id

    field

    Click in the Binding field then on the little button with the three dots. Awizard, enabling to associate the panel group component with a bean,

    appears.

    Select LibraryBean in the first list and libraryDownloadPanelGroup in

    the second. The field should take the value:

    #{LibraryBean.libraryDownloadPanelGroup}.

    Repeat these steps with the second PanelGroup. Use

    LibraryUploadPanelGroup in the Id field and complete the Binding to

    obtain #{LibraryBean.libraryUploadPanelGroup}.

    Expand the first PanelGroup, and select the first PanelHeader. Set the

    properties Id and Binding to LibraryDownloadSelectionPanelHeader

    and #{LibraryBean.libraryDownloadSelectionPanelHeader}.Select the second PanelHeader and set Id and Binding to

    LibraryDownloadConfirmationPanelHeader and

    #{LibraryBean.libraryDownloadConfirmationPanelHeader}.

    Expand the second PanelGroup, and select the first PanelBox. Set the

    properties Id and Binding to LibraryUploadTypeSelectionPanelbox

    and #{LibraryBean.LibraryUploadTypeSelectionPanelbox}.

    Select the second PanelBox and set Id and Binding to

    LibraryUploadFileSelectionPanelbox and

    #{LibraryBean.LibraryUploadFileSelectionPanelbox}.

    Now add the functions under the command buttons:

    Expand the menuBar and select the commandButton 2

    In the Property inspector, click on the Action property then on the little

    button with the three dots. A wizard appears to associate a button to an action

    declared in a bean.

    Select LibraryBean in the first list and librarySwitchDisplay in the

    second. The field should take the value: #{LibraryBean.

    librarySwitchDisplay}.

    Repeat these steps to trigger the actions libraryDownloadSwitchDisplay

    and libraryUploadSwtichDisplay with respectively the command buttons

    commandButton 5 and commandButton 3Do it again for have the actions #{LibraryBean.downloadAction},

    #{LibraryBean.uploadAction}, #{LibraryBean.selectFileToDownload}

    and #{LibraryBean.libraryUploadSwtichDisplay} respectively on the

    buttons commandButton 6, commandButton 4, commandButton 1 and

    Submit.

  • 8/6/2019 Tutorial_MediaLibrary _ Prototype Version _ August 2007

    34/34

    The outputText component which will display the name of the selected file to

    download needs to be linked to the bean:

    Find the outputText1 from the Structure window.

    In the Property inspector, enter NameOfSelectedFile4Download in the

    attribute id.In the binding attribute select LibraryBean and

    nameOfSelectedFile4Download to obtain the value

    #{LibraryBean.nameOfSelectedFile4Download}.

    The last action to bind is the one which enables to automatically keeping up-to-date

    the UploadedFile attribute in the bean with the selected file:

    Find the af:InputFile from the Structure window.

    In the Properties Inspector, find the ValueChangeListener attribute and

    set its value to #{LibraryBean.onUploading}.

    => Refining the display:

    Now its time for changing the label of the different buttons. Using the Structure and

    the Property Inspector windows, change the Text attribute of the buttons according to

    those proposed in the following table:

    Button current label Button wanted labelcommandButton 1 Download this file

    commandButton 2 #{LibraryBean.libraryDownloadPanelGroup.rendered?

    'Upload new File':'Download a File'}commandButton 3 Cancel upload

    commandButton 4 Confirm upload

    commandButton 5 Cancel download

    commandButton 6 Confirm download

    Submit Select this type

    Finally, your application is almost ready to use. The last step is to avoid the display of

    some panels at the first use of the application. The Rendered attribute has to bet set to

    false for the second PanelBox of the second PanelGroup, the second PanelGroup and

    the second panelHeader of the first PanelGroup.

    You can now run your application. To access from one page to the other change in the

    internet browser address field Library.jspx by administration.jspx or

    administration.jspx by Library.jspx depending on the current displayed page.

    Lot of improvements can be added but that will be the subject for next tutorials.