html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Oracle ADF. Business Components

Доброе время суток хабравчане. Моя предыдущая статья была небольшим интро в ADF. И так как по результатам опроса я вижу, что тема оказалась интересна, то я продолжаю писать об ADF.

Теперь после небольшого рассказа о данном фреймворке, можно «ринуться в бой» и рассмотреть фичи ADF более конкретно. Данная статья будет об ADF Business Components. О том как работать с ними декларативно и программно.


Общие понятия


ADF Business Components (далее BC) – это часть фреймворка для работы с БД, предоставляющая визуальную и декларативную разработку. Конфигурация BC хранится в XML файлах, но при желании можно сгенерировать Java классы и добавить и/или переопределить логику.
BC делятся на 5 основных частей:
  • Entity Objects (EO)
  • View Objects (VO)
  • Associations
  • View Links
  • Application Module

EO представляет собой таблицу из БД, и, соответственно, экземпляр EO – это строка из таблицы.
Данный компонент инкапсулирует в себе данные, правила валидации и логику персистентности.

EO associations определяют связи между двумя сущностями (таблицами)

VO – компонент, ответственный за чтение данных из data source, а также включает в себя операции по их обновлению.

View Links – определяют связи между VO (по аналогии с associations)

Application Module – это уровень сервиса, предоставляющий работу с бизнес компонентами (а именно с VO и View Links). Также в него можно добавить дополнительные методы и вкладывать другие Application Modules. В конечном счете Application Module используется, как Data Control.

IDE time


Для тестовых БД данных я буду использовать employees таблицу из oracle HR схемы.

После прохождения визарда «Business Components from tables», в результате получим следующий набор файлов.


Здесь Employees – EO, EmployeesView – VO, EmployeesAppModule – Application Module, EmpManagerFkAssoc – ассоциация между работниками и их менеджерами, EmpManagerFkLink – View link для аналогичной связи, но для VO, Business Components Diagram — диаграмма компонентов.

А на панели Data Controls создастся соответствующий data control.


Взглянем на диаграмму.

Можно увидеть, что EmployeesView создан на основе Employees EO. А в ApplicationModule попали два инстанса EmployeesView. Один отвечает за менеджера, а второй за его работников.

Краткий обзор сгенерированных файлов.

Employees

В сгенерированном EO можно посмотреть какие атрибуты в него входят, отредактировать, добавить свои или удалить.


Также можно управлять правилами валидации данных.


EmployeesView

Из атрибутов VO видно, что они берутся из Employees EO.


Можно посмотреть запрос VO, его переменные и критерии (named where clauses)


EmployeesAppModule

Application Module, как мы видели раньше, содержит два экземпляра EmployeesView


EmpManagerFkAssoc

Связь между сущностями.


EmpManagerFkLink

Одинаковые Source и Destination, говорят о том, что View Link построена на базе Associations.


CRUD




Да-да. CRUD будет реализован полностью декларативным путем, мною не будет написано ни одной строчки кода.

Посмотрим какой будет результат.
Вначале будет показана таблица с сотрудниками.


При нажатии на Create employee, произойдет переход на создание нового сотрудника.


При нажатии на Save новый сотрудник добавится в БД, и мы вернемся к таблице.


При нажатии на Update employee, произойдет переход на редактирование информации сотрудника.


После сохранения изменений, снова возврат к таблице.


Ну и наконец при нажатии на Delete employee, сотрудник испарится.


Ходом операций управляет bounded task flow. О том, как работать с task flows, будет отдельная статья. Пока просто посмотрим на диаграмму.


ViewEmployees, createEmployee и updateEmployee это view activities с JSFF, отвечающие за отображение таблицы и форм.
Для отображения сотрудников в таблице, нужно перенести EmployeeView из Data Control на страницу и выбрать в опциях создания – нужный вид таблицы (в моем случае – это read only)


Для вывода форм на страницах createEmployee и updateEmployee нужно сделать аналогичную операцию, но выбрать из категории Form (в моем случае – это ADF Form)


Все остальные activities – это операции над DataControl’ом. Перенесены эти операции также с Data Controls панели.


CreateInsert создает в итераторе новую строку и переводит курсор итератора на нее.
Delete удаляет строку в итераторе, на которой в данный момент находится курсор.
Чтобы действия CreateInsert и Delete вступили в силу, необходимо вызвать операцию Commit, а для того, чтобы откатить изменения – Rollback.
На этом реализация CRUD’а завершена.

CRUD v2


Теперь рассмотрим случай, когда мы не отказываемся полностью от декларативного пути, но операции хотим вызывать в каком-либо managed bean’e.

Для простоты рассмотрим только реализацию вставки, так как остальные выполняются аналогично.
Первым шагом необходимо создать managed bean.


Код bean’a рассмотрим в самом конце.

Я создам новую страницу и перенесу на нее таблицу, чтобы можно было увидеть новые данные, и форму для добавления нового сотрудника.
В input компонентах проставлю связи value на managed bean. И в конце добавлю кнопку, используя в качестве action listener’a метод managed bean'а.

В итоге разметка jspx выглядит следующим образом:
<af:form id="f1">
        <af:table value="#{bindings.EmployeesView1.collectionModel}" var="row"
                  rows="#{bindings.EmployeesView1.rangeSize}"
                  emptyText="#{bindings.EmployeesView1.viewable ? 'No data to display.' : 'Access Denied.'}"
                  fetchSize="#{bindings.EmployeesView1.rangeSize}" rowBandingInterval="0" id="t1">
            <af:column sortProperty="#{bindings.EmployeesView1.hints.FirstName.name}" sortable="false"
                       headerText="#{bindings.EmployeesView1.hints.FirstName.label}" id="c1">
                <af:outputText value="#{row.FirstName}" id="ot1"/>
            </af:column>
            <af:column sortProperty="#{bindings.EmployeesView1.hints.LastName.name}" sortable="false"
                       headerText="#{bindings.EmployeesView1.hints.LastName.label}" id="c2">
                <af:outputText value="#{row.LastName}" id="ot2"/>
             </af:column>
             <af:column sortProperty="#{bindings.EmployeesView1.hints.Email.name}" sortable="false"
                       headerText="#{bindings.EmployeesView1.hints.Email.label}" id="c3">
                <af:outputText value="#{row.Email}" id="ot3"/>
            </af:column>
            <af:column sortProperty="#{bindings.EmployeesView1.hints.PhoneNumber.name}" sortable="false"
                       headerText="#{bindings.EmployeesView1.hints.PhoneNumber.label}" id="c4">
                <af:outputText value="#{row.PhoneNumber}" id="ot4"/>
            </af:column>
            <af:column sortProperty="#{bindings.EmployeesView1.hints.JobId.name}" sortable="false"
                        headerText="#{bindings.EmployeesView1.hints.JobId.label}" id="c5">
                <af:outputText value="#{row.JobId}" id="ot5"/>
            </af:column>
        </af:table>
        <af:panelFormLayout id="pfl1">
            <af:inputText value="#{backingBeanScope.employeeBean.employeeId}" label="#{bindings.EmployeeId.hints.label}"
                          required="#{bindings.EmployeeId.hints.mandatory}"
                          columns="#{bindings.EmployeeId.hints.displayWidth}"
                          maximumLength="#{bindings.EmployeeId.hints.precision}"
                          shortDesc="#{bindings.EmployeeId.hints.tooltip}" id="it1">
                <f:validator binding="#{bindings.EmployeeId.validator}"/>
                <af:convertNumber groupingUsed="false" pattern="#{bindings.EmployeeId.format}"/>
            </af:inputText>
            <af:inputText value="#{backingBeanScope.employeeBean.firstName}" label="#{bindings.FirstName.hints.label}"
                          required="#{bindings.FirstName.hints.mandatory}"
                          columns="#{bindings.FirstName.hints.displayWidth}"
                          maximumLength="#{bindings.FirstName.hints.precision}"
                          shortDesc="#{bindings.FirstName.hints.tooltip}" id="it2">
                <f:validator binding="#{bindings.FirstName.validator}"/>
            </af:inputText>
            <af:inputText value="#{backingBeanScope.employeeBean.lastName}" label="#{bindings.LastName.hints.label}"
                          required="#{bindings.LastName.hints.mandatory}"
                          columns="#{bindings.LastName.hints.displayWidth}"
                          maximumLength="#{bindings.LastName.hints.precision}"
                          shortDesc="#{bindings.LastName.hints.tooltip}" id="it3">
                 <f:validator binding="#{bindings.LastName.validator}"/>
              </af:inputText>
              <af:inputText value="#{backingBeanScope.employeeBean.email}" label="#{bindings.Email.hints.label}"
                          required="#{bindings.Email.hints.mandatory}"
                          columns="#{bindings.Email.hints.displayWidth}"
                          maximumLength="#{bindings.Email.hints.precision}"
                          shortDesc="#{bindings.Email.hints.tooltip}" id="it4">
                <f:validator binding="#{bindings.Email.validator}"/>
              </af:inputText>
              <af:inputText value="#{backingBeanScope.employeeBean.phoneNumber}" label="#{bindings.PhoneNumber.hints.label}"
                          required="#{bindings.PhoneNumber.hints.mandatory}"
                          columns="#{bindings.PhoneNumber.hints.displayWidth}"
                          maximumLength="#{bindings.PhoneNumber.hints.precision}"
                          shortDesc="#{bindings.PhoneNumber.hints.tooltip}" id="it5">
                  <f:validator binding="#{bindings.PhoneNumber.validator}"/>
              </af:inputText>
              <af:inputDate value="#{backingBeanScope.employeeBean.hireDate}" label="#{bindings.HireDate.hints.label}"
                            required="#{bindings.HireDate.hints.mandatory}"
                            columns="#{bindings.HireDate.hints.displayWidth}"
                            shortDesc="#{bindings.HireDate.hints.tooltip}" id="id1">
                  <f:validator binding="#{bindings.HireDate.validator}"/>
                  <af:convertDateTime pattern="#{bindings.HireDate.format}"/>
              </af:inputDate>
              <af:inputText value="#{backingBeanScope.employeeBean.jobId}" label="#{bindings.JobId.hints.label}"
                            required="#{bindings.JobId.hints.mandatory}"
                            columns="#{bindings.JobId.hints.displayWidth}"
                            maximumLength="#{bindings.JobId.hints.precision}"
                            shortDesc="#{bindings.JobId.hints.tooltip}" id="it6">
                  <f:validator binding="#{bindings.JobId.validator}"/>
               </af:inputText>
               <af:commandButton text="Create Employee" id="cb1"
                                actionListener="#{backingBeanScope.employeeBean.createEmployee}"/>
           </af:panelFormLayout>
</af:form>


А описание страницы будет выглядеть так.


Код managed bean’a (get’ры и set’ры опустим).
Поля:
    private int employeeId;
    private String firstName;
    private String lastName;
    private String email;
    private String phoneNumber;
    private Timestamp hireDate;
    private String jobId;
    private BindingContainer bindings;


Метод вставки, использующийся кнопкой на странице:
public void createEmployee(ActionEvent actionEvent) {
        // Получаем binding контейнер
        BindingContainer bindings = getBindings();
        // Выполняем операцию создания новой строки
        OperationBinding createOperation = 
            bindings.getOperationBinding("CreateInsert");
        createOperation.execute();
        // Забиваем атрибуты данными
        AttributeBinding employeeId = 
            (AttributeBinding)bindings.getControlBinding("EmployeeId");
        employeeId.setInputValue(this.employeeId);
        AttributeBinding firstName = 
            (AttributeBinding)bindings.getControlBinding("FirstName");
        firstName.setInputValue(this.firstName);
        AttributeBinding lastName = 
            (AttributeBinding)bindings.getControlBinding("LastName");
        lastName.setInputValue(this.lastName);
        AttributeBinding phoneNumber = 
            (AttributeBinding)bindings.getControlBinding("PhoneNumber");
        phoneNumber.setInputValue(this.phoneNumber);
        AttributeBinding email = 
            (AttributeBinding)bindings.getControlBinding("Email");
        email.setInputValue(this.email);
        AttributeBinding hireDate = 
            (AttributeBinding)bindings.getControlBinding("HireDate");
        hireDate.setInputValue(this.hireDate);
        AttributeBinding jobId = 
            (AttributeBinding)bindings.getControlBinding("JobId");
        jobId.setInputValue(this.jobId);
        // Коммитим и тем самым сохраняем новую строку
        OperationBinding commitOperation = 
            bindings.getOperationBinding("Commit");
        commitOperation.execute();
    }


Проверим работу managed bean’a, убедившись, что в таблицу попала новая запись.


CRUD v3


И последний пример, в котором будет только использование кода.
Для начала нужно подготовить классы у Business Components.
Для этого откроем EmployeeView перейдем на вкладку Java и сгенерируем следующие классы.


EmployeesViewImpl необходим для работы с запросами, а EmployeesViewRowImpl будет представлять из себя строку с атрибутами.

Таким же путем сгенерируем класс для Application Module.


Осталось написать новый метод для добавления строки в БД в EmployeesAppModuleImpl, создать TO класс для передачи данных в этот метод, и вызвать данный метод в managed bean’e.

Метод в Application Module:
    public void createEmployee(EmployeeInfo employeeInfo) {
        // Получаем ViewObject
        EmployeesViewImpl employeeView = getEmployeesView1();
        // Готовим новую строку.
        EmployeesViewRowImpl employee = (EmployeesViewRowImpl)employeeView.createRow();
        employee.setEmployeeId(employeeInfo.getEmployeeId());
        employee.setEmail(employeeInfo.getEmail());
        employee.setPhoneNumber(employeeInfo.getPhoneNumber());
        employee.setFirstName(employeeInfo.getFirstName());
        employee.setLastName(employeeInfo.getLastName());
        employee.setHireDate(new Timestamp(employeeInfo.getHireDate()));
        employee.setJobId(employeeInfo.getJobId());
        // Производим операцию вставки.
        employeeView.insertRow(employee);
        // Коммитим
        getDBTransaction().commit();
    }


Новый метод bean’a:
    public void createEmployee2(ActionEvent actionEvent) {
        // Получаем application module
        String applicationModuleClass = "com.matim.forhabr.model.EmplyeesAppModuleImpl";
        String config = "EmplyeesAppModuleLocal";
        EmplyeesAppModuleImpl appModule = (EmplyeesAppModuleImpl)
            Configuration.createRootApplicationModule(applicationModuleClass, config);
        // Забиваем данными TO
        EmployeeInfo employeeInfo = new EmployeeInfo();
        employeeInfo.setEmail(this.email);
        employeeInfo.setEmployeeId(this.employeeId);
        employeeInfo.setFirstName(this.firstName);
        employeeInfo.setHireDate(this.hireDate);
        employeeInfo.setJobId(this.jobId);
        employeeInfo.setLastName(this.lastName);
        employeeInfo.setPhoneNumber(this.phoneNumber);
        // Вызываем метод по созданию нового сотрудника
        appModule.createEmployee(employeeInfo);
        // Освобождаем ресурсы
        Configuration.releaseRootApplicationModule(appModule, false);
        // Так как вставка идет на стороне AppModule, 
        // то только для целей, обновления таблицы
        // выполним операцию Execute
        BindingContainer bindings = getBindings();
        OperationBinding executeIterator = 
            bindings.getOperationBinding("Execute");
        executeIterator.execute();
    }


Проверяем работу:


На этом сегодня все. Много всего еще осталось за бортом по этой теме, поэтому оставлю ссылку на дополнительную информацию здесь.

P.S. Следующая статья будет о task flows.
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

0

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции