вторник, 29 октября 2013 г.

Запись изменений VO в базу без commit

Для автоматической записи в БД всех изменений происходящих на уровне WLS
можно выставить  this.setAutoPostChanges(true); в объекте VOImpl.

ВАЖНО:
1. запись будет происходить только  в момент выполнения ExecuteQuery()
2. на измененных записях таблицы выставляется блокировка




What you may need to know about DBTransaction::postChanges()


// Get VewRowImpl someVewRowImpl from VO  
    someVewRowImpl.setAttribute( "SomeAttrib","New Value");  
    EntityImpl someEOImpl = someVewRowImpl.getEntity(0);  
    DBTransaction txn = getDBTransaction();  
    txn.validate();  
    txn.postChanges();  
    txn.removeTransactionPostListener(someEOImpl); 
 
    //The below two lines may cause your EO to skip 
    // beforeCommit() and afterCommit() call backs.
    //Normally you can skip the below two lines, 
    // use it if you need to clear the EO cache once data is posted to DB
    // This makes sense if you have millions of rows in an update and
    // and you want to get rid of the cached rows without any delay
    txn.removeTransactionListener(someEOImpl); 
    txn.clearEntityCache(null);



Как получить текст запроса для поисковой формы


Хотим получить запрос выполняющийся в поисковой форме (Query) элементе
для этого переопределяем метод executeQueryForCollection объекта ViewObjectImpl

    protected void executeQueryForCollection(Object qc, Object[] params,
        int numUserParams) {
            System.out.println("--- numUserParams "+numUserParams);
            System.out.println("--- getQuery "+getQuery());
            for(int i=0;i<numUserParams;i++) {
                Object[] o = (Object[])params[i];
            System.err.println(o[0] + " " + o[1]);
        }
        super.executeQueryForCollection(qc, params, numUserParams);
    }

Получаем что-то такое:


SELECT * FROM
(SELECT /*+ FIRST_ROWS */ IQ.*, ROWNUM AS Z_R_N FROM
(SELECT TrInOperationsEO.ID,         TrInOperationsEO.INOUT_DATA_LOG_ID,
...
TrInOperationsEO.CLIENT_CODE
FROM TR_IN_OPERATIONS TrInOperationsEO
WHERE (ROWNUM <= :bndMaxRows)
AND ( ( ( (TrInOperationsEO.ID = :vc_temp_1 )
AND (TrInOperationsEO.INOUT_DATA_LOG_ID = :vc_temp_2 ) ) ) ) ORDER BY id DESC
) IQ  WHERE ROWNUM < :Bind_RangePage_High
) WHERE Z_R_N > :Bind_RangePage_Low

Надо заметить, что параметры Bind_RangePage_High, Bind_RangePage_Low возникают из постраничного вывода VO, остальные имеют имена vc_temp_1, vc_temp_2, и т.д. в соответствии с тем, какие параметры отмечены в форме.

Список параметров выглядит примерно так:


bndMaxRows 100
vc_temp_1 15613
vc_temp_2 23
vc_temp_3 R

Первая переменная bndMaxRows добавлена в запрос VO вручную, остальные формируются по полям автоматически. 




  

четверг, 24 октября 2013 г.

Таблицы с постраничный выводом


Настраиваем VO для работы с многостраничными запросами



В свойствах итератора выставляем то же  количество записей:





Для таблицы с постраничным выводом количество записей получается через функцию
getEstimatedRowCount()  объекта ViewObjectImpl

Пройти по всем записям можно через два цикла, первый - цикл по страницам, второй по записям на каждой странице, примерно так:


    public void onLoop(ActionEvent actionEvent) {
        long row_count = getVoImpl().getEstimatedRowCount();
        long rows_per_page = getVoImpl().getRangeSize();
        long page_count = row_count / rows_per_page + 1;
        System.out.println("total rows:" + row_count + "  rows at page:" +    rows_per_page + "  numb of pages:" + page_count);
        int m = 1;
        for(int i=1;i<=page_count;i++) {
            System.out.println("--- Page: " + i);
            getVoImpl().scrollToRangePage(i);
                for(int j=0; j<rows_per_page && m<=row_count; m++, j++) {
                    Row row = getVoImpl().getRowAtRangeIndex(j);
                    System.out.println(m +"  "+ row.getAttribute(0)+ "  " + row.getAttribute(2) );
                }
        }
    }



Тестовое приложение TestHr1.rar






вторник, 22 октября 2013 г.

Стандартные иконки


Иконки находится в jar файле oicons.jar

У меня они в двух местах:

C:\Oracle\Middleware123\jdeveloper\ide\lib\
C:\Oracle\Middleware123\oracle_common\modules\oracle.adf.model_11.1.1\oicons.jar

Oracle ADF Useful Links and Resources Resource Links

понедельник, 21 октября 2013 г.

Pagination in ADF 11.1..2....


Оракл убрал привычный постраничный вывод таблиц в ADF 11.1..2.... Изумлению пользователей, судя по отзывам в блогах, нет предела, тем не менее факт свершившийся.)


Будем искать обходные маневры:
Custom Table Pagination Using EJB Native Query


В принципе, постраничная организация вывода в новом ADF работает, только это осуществляется "прозрачным" для пользователя способом. Хорошо или плохо это, не знаю.


Ограничения, связанные с постраничным выводом:

Нельзя открыть итератор по записям, возникнет ошибка: "JBO-25083: Cannot create a secondary iterator on row set {0} because the access mode is forward-only or range-paging"

"In order to be able to iterate a view object rowset using a secondary iterator, the view object
access mode in the General | Tuning section must set to Scrollable. Any other access
mode setting will result in a JBO-25083: Cannot create a secondary iterator on row set {0}
because the access mode is forward-only or range-paging error when attempting to create a
secondary iterator. To iterate view objects configured with range paging, use the range paging
view object API methods. Specifically, call getEstimatedRangePageCount() to determine
the number of pages and for each page call scrollToRangePage(). Then determine
the range page size by calling getRangeSize() and iterate through the page calling
getRowAtRangeIndex()."
                                                  Oracle JDeveloper 11gR2 Cookbook



"Падучая" болезнь Weblogic-а при деплойменте


Weblogic оказался подвержен "падучей" при деплойменте приложений. Каждая третья попытка кладет его по OutOfMemory, превышен Permgen.

Нашел статью с рекомендацией "Java. Сборщики мусора" .с рекомендацией включить очистку  Permgen-а. Для этого в опциях java машины нужно добавить два параметра
+CMSPermGenSweepingEnabled +CMSClassUnloadingEnabled

(редактируем startWebLogic.cmd)
@REM МОИ ДОПОЛНИТЕЛЬНЫЕ НАСТРОЙКИ для очистки Permgen
set EXTRA_JAVA_PROPERTIES= -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled
set MEM_ARGS=%MEM_ARGS% %EXTRA_JAVA_PROPERTIES%


Не знаю поможет или нет.
UPD:
Отчасти помогло, WLS стал работать устойчивее, но всё-же не до конца, его по-прежнему . можно завалить "деплоями".


Полезные ссылки:

Java. Сборщики мусора. Часть первая.
Java. Сборщики мусора. Часть вторая.

пятница, 18 октября 2013 г.

Напоролся на JBO-25200


Оказывается если использовать ViewCriteria с виндинг-переменной в WHERE конструкции например WHERE ROWNUM <= :bndMaxRows) , то при выполнении можно поиметь исключение JBO-25200. Выглядит так, словно модуль потерял коннекцию к базе. Причем, это происходит только в том случае, если переменная отображается в списке критериев поиска, если же у неё своиство display hint сделать Hide то ошибка исчезает.


Полезная ссылка:
oracle.jbo.NotConnectedException: JBO-25200 While using View Criteria

воскресенье, 13 октября 2013 г.

Динамическое отображение колонок в таблице


Задача: изменять видимость колонок таблицы в в коде программы, в зависимости от некоторых условий.


  • создаем HashMap отвечающий за отображение колонок в бине InOperationsB (область ViewScope). Инициализируем  его в конструкторе, либо в момент первого использования


    private HashMap viewColumns;

    public InOperationsB() {
        super();
        
        if(viewColumns == null) {
            viewColumns = new HashMap();
            viewColumns.put("Payid",Boolean.TRUE);
        }
        ...
    }


  • вешаем на форму кнопочку Test с обработчиком onTest()  в InOperationsB
    public void onTest(ActionEvent actionEvent) {

       //-- сюда вставляем логику отображения, у меня просто "вкл-выкл"
 
        Boolean b = (Boolean)viewColumns.get("Payid");
        if(b != null) {
            if( b.booleanValue()) {
                viewColumns.put("Payid",Boolean.FALSE);
            } else {
                viewColumns.put("Payid",Boolean.TRUE);
            }
        }
        //-- refresh table  getVoImpl().executeQuery(); 
  }



  • правим свойство Visible у колонки в отображаемой таблице на EL выражение "#{viewScope.InOperationsB.viewColumns['Payid']}" где  'Payid' у меня имя атрибута в колонке(но это не суть важно)
  • тестируем. По нажатию кнопки колонка то появляется, то исчезает



Получение бина области viewScope в коде


Алгоритм примерно такой:



  1. получаем текущий Инстансе из FacesContext
  2. из него получаем контекст EL  и контекст ExpressionFactory
  3. в котором открываем ValueExpression для требуемого бина, через выражение  "#{viewScope.YourBeanName}"
  4. и получаем объект бина функцией getValue()


 Всё офигенно просто.)))

Пример:

private TreeTableStateBean getTreeTableStateObject(){
        TreeTableStateBean stateBean = null;
     
        FacesContext fctx = FacesContext.getCurrentInstance();
        ELContext elctx = fctx.getELContext();
        ExpressionFactory elFactory = fctx.getApplication().getExpressionFactory();
     
        ValueExpression ve = elFactory.createValueExpression(
                                elctx,
                                "#{viewScope.treeTableStateBean}",
                                Object.class);
     
        stateBean = (TreeTableStateBean) ve.getValue(elctx);      
        return stateBean;
      }

Ссылка:
ADF Code Corner 84. Dynamically show or hide af:treeTable columns dependent on the disclosed node

Работа с критериями поиска ViewCriteria


Полезные ссылки:


ViewObject (VO) - Выводимый Объект (ВО)
ViewCriteria(VC) - Критерий Поиска (КП)

Похоже, Критерии Поиска довольно мощный и гибкий механизм. Суть в том, что на один VO можно навесить несколько разных критериев, а затем, использовать один и тот же VO в нужном контексте. 

Примерная последовательность действий:
  • Добавляем несколько КритериевПоиска в интересующий ViewObject
  • Создаем таблицу "t1" в форме на основе VO
  • Добавляем в форму popup элемент в который вставляем query(Запрос с Параметрами) на основе NamedCriteria   для нашего VO.  Можно создать Запрос с Параметрами на основе конкретного Критерия Поиска, но потом всё-равно можно перемещаться выбирая другие КП.
  • Для каждого КП можно декларативно определить выводимые параметры на основе атрибутов VO
----------------------------------------------------------------------------------------------------------

Программное изменение использования атрибута в запросе критерия

В классе ViewObjectImpl определяем метод:


public void setQuerable(String attributeName, Boolean isQuerable) {  
   
     int indx = this.getAttributeIndexOf(attributeName);  
   
     ViewAttributeDefImpl attr = (ViewAttributeDefImpl)this.getAttributeDef(indx);  
   
     attr.setQueriable(isQuerable);  
   
   }