Архив

Архив раздела ‘OA Framework’

OAF-компоненты. Attachments

1. Динамическое создание компонента attachmentTable

import oracle.apps.fnd.framework.webui.beans.layout.OAAttachmentTableBean;
import oracle.apps.fnd.framework.webui.OAWebBeanConstants;
import java.util.Hashtable;
import java.util.Dictionary;
...
OAAttachmentTableBean attTable = (OAAttachmentTableBean)pageContext.getWebBeanFactory().createWebBean(pageContext, OAWebBeanConstants.ATTACHMENT_TABLE_BEAN, null, null);

attTable.setID("xxTestAttachmentId");
attTable.setViewUsageName("ApplicantAssignmentVO");
attTable.setSearchRegionDisplayed(false);
attTable.setDocumentCatalogEnabled(true);

attTable.setText("Сводка дополнений");

Hashtable<String, Object> entity = new Hashtable<String, Object>();
entity.put("entityId", "PER_ASSIGNMENTS_F"); // entity
entity.put("showAll", Boolean.FALSE);
entity.put("insertAllowed", Boolean.TRUE);
entity.put("deleteAllowed", Boolean.TRUE);
entity.put("updateAllowed", Boolean.TRUE);

String[] pkAttrNames = new String[1];
pkAttrNames[0] = "AssignmentId";
entity.put("pkColumns", pkAttrNames);

Dictionary[] entityMaps = new Dictionary[1];
entityMaps[0] = entity;
attTable.setEntityMappings(entityMaps);

webBean.addIndexedChild(attTable);

https://community.oracle.com/thread/2249676
https://community.oracle.com/thread/2404025

2. Не появляются всплывающие popup-ы (Inline Attachments)

В некоторых невыясненных ситуациях, при добавлении компонента attachmentTable на стандартную форму динамически или через персонализацию, не работают popup-ы для просмотра/добавления/редактирования/удаления вложений (Inline Attachments). Было обнаружено, как минимум, 2 условия, которые влияют на эту ситуацию (полный список условий выяснить не удалось):

  • Страница открывается 1-й раз
  • У компонента attachmentTable отключен регион поиска (searchRegionRendered="false")

Для устранения этого неудобства удалось найти workaround. Нужно добавить в контроллер (processRequest) следующий код:

// Тут важен процесс создания компонента, оказывающий положительное влияние на popup-ы, если они не хотят всплывать.
// На форме компонент показывать не нужно.
OAMessageChoiceBean akAttachmentCategory = (OAMessageChoiceBean)createWebBean(pageContext, "MESSAGE_POPLIST", null, "XxTmp");
akAttachmentCategory.setPickListViewObjectDefinitionName("oracle.apps.fnd.server.FndCategoryNameVO");
akAttachmentCategory.setValue(pageContext, "1");

3. Изменения в модели данных
Если форма работает с вложениями (attachmentLink, attachmentTable), то в модели данных происходят следующие динамические изменения:

  • Добавляется дочерний Application Module с именем oracle_apps_fnd_server_OAAttachmentsAM
  • В этом AM, для каждого компонента, работающего с вложениями, создается набор ViewObject-ов. Наиболее интересные — VO, связанные с таблицами fnd_documents и fnd_attached_documents. Именуются они по шаблону Attach_<num>_FndDocumentsDomExtensionVO и Attach_<num>_FndAttachedDocumentsDomExtensionVO. Например, Attach_0_FndAttachedDocumentsDomExtensionVO.

Перед проходом по строкам VO, нужно обязательно проверить, что заданы bind-переменные. Это наиболее вероятная ситуация, но попадались случаи, когда для объекта нет привязанных вложений, и bind-переменные в Attach…VO были не установлены. Попытка сделать проход по строкам VO, в такой ситуации, приведет к тому, что SQL-запрос вернет данные из таблиц без фильтра (например, все записи из fnd_attached_documents). Cтраница зависнет, а потом упадет по timeout-у.
Пример кода.

OAApplicationModule am = pageContext.getApplicationModule(webBean);
// Опорные имена, по которым ищем AM и VO с вложениями
String attachmentsAMName = "oracle_apps_fnd_server_OAAttachmentsAM";
String attachDocsVOFlag = "FndAttachedDocumentsDomExtensionVO";
String docsVOFlag = "FndDocumentsDomExtensionVO";
// Application Module, в котором содержатся ViewObject-ы, имеющие отношения к вложениям (attachemnts)
OAApplicationModule amA = (OAApplicationModule)am.findApplicationModule(attachmentsAMName);
if (amA != null) {
    writeDiag(pageContext, "AM = " + amA.getDefFullName());
    String[] voNames = amA.getViewObjectNames();
    writeDiag(pageContext, "viewobjectNames Length = " + voNames.length);
    for (int j = 0; j < voNames.length; j++) {
        // Обрабатываем ViewObject-ы (их может быть несколько - свой для каждого претендентства), в которых находятся данные по fnd_attached_documents if (voNames[j].lastIndexOf(attachDocsVOFlag) > 0)
        if (voNames[j].lastIndexOf(attachDocsVOFlag) > 0) {
            String voDName = voNames[j].substring(0, voNames[j].indexOf("_", 8) + 1) + docsVOFlag; // "Attach__"
            writeDiag(pageContext, "     AttachedDocuments ViewObject Name = " + voNames[j]);
            writeDiag(pageContext, "     Documents ViewObject Name = " + voDName);
            
            OAViewObject voA = (OAViewObject)amA.findViewObject(voNames[j]);
            // ОБЯЗАТЕЛЬНО!!! Проверяем, чтобы были заданы bind-переменные.
            if (voA.getWhereClauseParams().length > 1) {
                Object[] params = voA.getWhereClauseParams();
                for(int p = 0; p < params.length; p++)
                    writeDiag(pageContext, "params[" + p + "] = " + params[p].toString());
                for (Row rowA = voA.first(); rowA != null; rowA = voA.next()) {
                    writeDiag(pageContext, "DocumentId = " + rowA.getAttribute("DocumentId"));
                    writeDiag(pageContext, "LastUpdateDate = " + rowA.getAttribute("LastUpdateDate"));
                    writeDiag(pageContext, "newRowState = " + ((ViewRowImpl)rowA).getNewRowState());
                }
            }
        }
    }
}

OAF-компоненты. AdvancedTable

1. Использование элементов ввода в области tableActions

Для элементов области tableActions, в которые предполагается ввод данных пользователем (например, MessageChoice или MessageTextInput), была замечена особенность: если ViewObject, связанный c AdvancedTable, не инициализирован, тогда нет доступа к новым значениям элементов, введенных на форме. Признаком того, что ViewObject не инициализирован, является надпись в табличной части «Поиск не выполнен». Если ViewObject инициализирован, но в нем нет строк, то надпись будет «Нет результатов поиска». В контроллере этот факт можно проверить с помощью функции VO isPreparedForExecution. Для кнопок таких проблем не возникает — с точки зрения обработки, важен только сам факт нажатия кнопки, который всегда можно отследить и обработать в контроллере.

Если есть необходимость работать с элементами, допускающими ввод данных пользователем в tableActions, то нужно чтобы VO был в инициализированном состоянии. Например, в контроллере processRequest, можно написать следующий код (чтобы состояние «VO НЕ инициализирован, строк нет» перевести в состояние «VO инициализирован, строк нет»)

if (!vo.isPreparedForExecution()) {
    vo.setWhereClause("1=0");
    vo.setWhereClauseParams(null);
    vo.executeQuery();
    vo.setWhereClause(null);
}

2. Доступ к элементам, находящимся в tableActions или tableSelection

Для доступа к элементам из областей tableActions или tableSelection, нужно сначала получить саму область, а потом искать элемент внутри нее

OAAdvancedTableBean tableBean = (OAAdvancedTableBean)webBean.findIndexedChildRecursive("invoicesTable");
OARowLayoutBean actionsBean = (OARowLayoutBean)tableBean.getTableActions(); // или OAFlowLayoutBean
OAMessageChoiceBean pt = (OAMessageChoiceBean)actionsBean.findIndexedChildRecursive("prepaymentTypesItem");
pt.setValue(pageContext, pageContext.getProfile("XXAP001_INVOICE_PREPAYMENT_DEFAULT"));

3. Связывание свойств с атрибутами VO для элементов внутри Столбца

Для некоторых элементов, являющихся дочерними по отношению к столбцу AdvancedTable, не удалось связать свойства с атрибутами VO. Такая особенность наблюдалась для любого региона (flowLayout, tableLayout и т.п.) и для компонента spacer. Например, свойство Rendered не получилось связать ни с использованием EL, ни через OADataBoundValueViewObject. Для spacer-а можно применить workaround:

  • вместо компонента spacer использовать компонент rawText
  • в свойстве Text указать HTML-код, который генерится компонентом spacer (задать нужные значения в атрибутах width и height): <img src="/OA_HTML/cabo/images/skyros/t.gif" width="10" height="10">
  • свойство Rendered связать с атрибутом VO
Categories: OA Framework Tags: ,

JSP страница для входа в OEBS с логином и паролем

26 Декабрь 2017 1 комментарий


Весьма полезная JSP страница для авто входа в OEBS с логином и паролем:

http://host:port/OA_HTML/fndvald.jsp?username=!login&password=!pwd

Пример ссылки:

Читать дальше про “JSP страница для входа в OEBS с логином и паролем” »

OAF: Передача параметра с кириллицей в URL

27 Октябрь 2014 Нет комментариев

Oracle Application Framework: Пример кода для передачи параметра с кириллицей в URL.

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import oracle.apps.fnd.framework.OANLSServices;
import oracle.apps.fnd.framework.server.OAApplicationModuleImpl;
...
OAApplicationModuleImpl am = (OAApplicationModuleImpl)pageContext.getApplicationModule(webBean);  
OANLSServices nls = am.getOADBTransaction().getOANLSServices();
           
try {
         pAssignmentSet = URLEncoder.encode(pAssignmentSet, nls.getJAVAClientEncoding());
     
    } catch (UnsupportedEncodingException e) {
        throw new OAException(e.getMessage());
    }
...

OAF: Поиск страниц с отключенной персонализацией

Запрос для поиска страниц или регионов OEBS OAF с отключенной персонализацией:

select *
from (select att.att_value base_path
            ,jdr_mds_internal.getDocumentName(pat.path_docid) custom_path
            ,regexp_replace(jdr_mds_internal.getDocumentName(pat.path_docid),
                            '.*/customizations/([[:alpha:]]*)/.*',
                            '\1') custom_level
            ,decode(regexp_replace(jdr_mds_internal.getDocumentName(pat.path_docid),
                                   '.*/customizations/([[:alpha:]]*)/.*',
                                   '\1'),
                    'site',
                    'SITE',
                    (regexp_replace(jdr_mds_internal.getDocumentName(pat.path_docid),
                                    '.*/customizations/([[:alpha:]]*)/([0-9A-Za-z_]*)/.*',
                                    '\2'))) custom_level_value
            ,nvl((select 'N'
                 from jdr_attributes cat
                 where cat.att_comp_docid = pat.path_docid
                       and cat.att_name = 'MDSActiveDoc'
                       and cat.att_value = 'false'),
                 'Y') is_active
            ,pat.created_by
            ,pat.creation_date
            ,pat.last_updated_by
            ,pat.last_update_login
            ,pat.LAST_UPDATE_DATE
      from jdr_paths pat
      join jdr_attributes att on (pat.path_docid = att.att_comp_docid)
      where att_comp_seq = 0
            and att_name = 'customizes'
      --and regexp_like( jdr_mds_internal.getDocumentName(path_docid), 'apps/(iby|fnd)' )
      )
where is_active = 'N'

Читать дальше про “OAF: Поиск страниц с отключенной персонализацией” »

OAF: Вывести список VO и значения атрибутов

22 Август 2013 Нет комментариев

Вывести все View Objects (VO) и значения атрибутов для OAApplicationModule

    // Вывод всех значений VO
    public void printALLVO(OAApplicationModule am)
    {
      OADBTransaction tr = am.getOADBTransaction();
      if(tr.isLoggingEnabled(1)) 
      {
        tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " ",1);
        tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " AM "+am.getName(), 1);
      }
      String[] rootViewNames = am.getViewObjectNames();
      if(tr.isLoggingEnabled(1)) 
      {  
        tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " count of VOs from AM = " +rootViewNames.length,1 );
      }
      for (int j =0 ;j < rootViewNames.length ;j++ )
      {
        if(tr.isLoggingEnabled(1)) 
        {  
          tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " ",1);
          tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", "================",1);
          tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " VO "+rootViewNames[j],1 );
        }
     
        oracle.jbo.ViewObject lVO = (oracle.jbo.ViewObject)am.findViewObject(rootViewNames[j]);
        if (lVO!=null && lVO.isExecuted()) {
          oracle.jbo.server.ViewRowImpl lVORow;
          int numRow = 1;
          for(lVORow = (oracle.jbo.server.ViewRowImpl)lVO.first(); lVORow != null;
              lVORow = (oracle.jbo.server.ViewRowImpl)lVO.next())
          {
              if (lVORow!=null) {
                  int attrCount = lVORow.getAttributeCount();
                  if(tr.isLoggingEnabled(1)) 
                  {              
                    tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " ",1);
                    tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " [row "+numRow+"]",1);
                    tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " count of attributes = "+attrCount,1);
                  }
     
                  String[] attributeNames = lVORow.getAttributeNames();
                  for (int i = 0 ;i< attributeNames.length ;i++ )
                  {
                    if(tr.isLoggingEnabled(1)) 
                    {              
                      tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", attributeNames[i]
                      +" = "
                      +lVORow.getAttribute(i),1);
                    }
                  }
              }
              numRow ++;
          }
          if (numRow==1) {
            if(tr.isLoggingEnabled(1)) 
            {          
              tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " not exists rows",1);
            }
          }
        }
        else {
          if(tr.isLoggingEnabled(1)) 
          {                
            tr.writeDiagnostics(this.getClass().getName() + ".printALLVO XX", " not executed",1);
          }
        }
      }              
     
    }

Цикл по вложенным Application Modules (текущий AM не входит во вложенные AM)

String nestedAMArray[]=oapagecontext.getRootApplicationModule().getApplicationModuleNames();
for(int i = 0; i < nestedAMArray.length; i++)
{
    String amName = nestedAMArray[i];
    OAApplicationModule amIter = (OAApplicationModule)am.findApplicationModule(amName);
    oapagecontext.writeDiagnostics(this,"Nested AM Name=>"+amName,1);
}    

OAF: Как получить дочерний Application Module

22 Август 2013 Нет комментариев

Пример получения дочернего Application Module (AM) из контроллера

// Возвращает дочерний AM по его названию
public static OAApplicationModule getRequestedAM(OAPageContext oapagecontext,
                                                 String requestedAMName
                                                )  
{  
  OAApplicationModule rootAM    = oapagecontext.getRootApplicationModule();
  OAApplicationModule currentAM = null;  
  oapagecontext.writeDiagnostics(oapagecontext, "XX find applicationModule = "
                                                +requestedAMName,1);  
  String amName = "";  
  String nestedAMArray[] = rootAM.getApplicationModuleNames();  
  oapagecontext.writeDiagnostics(oapagecontext,"XX Root AM = "
                                 + rootAM.getName()
                                 + "; count child AMs = "
                                 + nestedAMArray.length,1);  
  for(int i = 0; i < nestedAMArray.length; i++)  
  {  
      amName = nestedAMArray[i];  
      currentAM = (OAApplicationModule)rootAM.findApplicationModule(amName); 
      String originalAmName = currentAM.getDefName();
      oapagecontext.writeDiagnostics(oapagecontext,"XX nested AM name = "
                                     +originalAmName,1);  
      if (originalAmName.equals(requestedAMName)) {
        oapagecontext.writeDiagnostics(oapagecontext,"XX found nested AM " 
                                       + originalAmName ,1);  
        break;  
      }  
  }  
  return currentAM;  
}  

OAF R12 Developer’s guide

4 Декабрь 2012 1 комментарий

Весьма полезные гайды по Oracle Application Framework (OAF)

Ноты на металинке:
Oracle Application Framework Developer’s Guide Release 12.1.3 [ID 1107973.1]
Oracle Application Framework Developer’s Guide Release 12.1.2 [ID 972774.1]
Oracle Application Framework Developer’s Guide Release 12.1.1 [ID 744832.1]

У кого нет доступа, тот может взять
Oracle Application Framework Developer’s Guide Release 12.1.3 по ссылкам:
Depositfiles
Google Docs

Ant при разработке с использованием OAF

24 Апрель 2012 3 comments

При разработке проектов с использованием OAF и JDeveloper возникла необходимость частого переноса (или развертывания — deploy) приложений с одного экземпляра системы на другой.

Операция переноса состоит из пяти шагов:

  1. Компиляция java классов
  2. Перенос java классов на сервер приложений (в каталог $JAVA_TOP)
  3. Перенос xml файлов Entity Objects, View Objects, Application Modules ($JAVA_TOP)
  4. Импорт xml файлов Pages, Regions с помощью утилиты import
  5. Импорт xliff файлов

Проделав эту операцию пару раз вручную, решил все это дело автоматизировать.
Вся автоматизация построена на известном продукте Apache Ant.

Состоит из четырех файлов

  1. <project>.bat
  2. <project>.xml
  3. build.xml
  4. <project>.properties

, где <project> имя Вашего проекта.

Читать дальше про “Ant при разработке с использованием OAF” »

JBO-25009: Невозможно создать объект типа:oracle.jbo.domain.Number

14 Сентябрь 2011 Нет комментариев

Если вы столкнулись с ошибкой JBO-25009, то вот вариант как ее быстро и успешно победить.

Получил ошибку на странице OAF:
US: JBO-25009: Cannot create an object of type:oracle.jbo.domain.Number
RU: JBO-25009: Невозможно создать объект типа:oracle.jbo.domain.Number

Решение:
На странице присутствовало поле xBean (тип messageChoice);
связанное с атрибутом ViewObject типа NUMBER.

Тип поля xBean был VARCHAR2, заменил его на NUMBER и все заработало успешно.