Джавапокалипсис в отдельно взятой системе

в 9:27, , рубрики: ERP-системы, Excel, java-апплет, разработка

Эта статья ориентирована на ABAP-разработчиков в системах SAP ERP. Она содержит много специфических для платформы моментов, которые малоинтересны или даже спорны для разработчиков, использующих другие платформы.

Есть такой эвфемизм: “исторически сложилось”.

Так вот, в моей основной системе исторически так сложилось, что:

  • много пользователей работают через SAP GUI for HTML;
  • практически вся отчетность выгружается в Excel через ZWWW.

А это значит что без правильно настроенной связки Браузер+Java жить непросто.

Java нужна для работы с файлами (выгрузить, загрузить). Принципиально веб-приложение должно работать только внутри своего окна и его нельзя подпускать к файловой системе пользователя даже на пушечный выстрел. С файлами должен работать лично браузер удобным ему способом, но это противоречит подходу SAP GUI, который хочет контролировать всё: показ диалога открытия, заголовок окна диалога, список доступных расширений файлов, разрешение множественного выбора, выбор каталога, чтение каталога, считывание содержимого файла или запись. Так как SAP GUI for HTML должен повторять функциональность большого брата, поэтому они там решили не менять подход, а ввести дополнительную прослойку в виде Java-апплета, который бы выполнял эти действия на стороне клиента. ABAP-часть при таком подходе остаётся практически без изменений.

Кроме этого, ZWWW работает через технологию OLE, без вариантов. А веб-приложение нельзя подпускать к OLE-интерфейсам клиентской машины даже в радиусе поражения ракет класса “земля-воздух”. Следовательно, нужна ещё одна прослойка в виде Java-апплета, которая будет проксировать OLE-вызовы и выполнять сопутствующие махинации.

Так как SAP GUI for HTML и сам является прослойкой между ABAP-инстанцией и ITS-сервером, то это всё это сооружение начинает походить на игру Дженга.
Джавапокалипсис в отдельно взятой системе - 1

Такая игра идёт постоянно. То браузеры начинают отключать старую джаву, то джава-апплеты теряют полномочия, то что-то происходит с проверкой подписи апплета, то появляются какие-то черные/белые списки исключений, то вдруг апплет начинает жутко тормозить на какой-то версии JRE, то выходит новая версия офиса, то обновляют ITS/ABAP, то пользователи в другом конце страны не могут настроить политику безопасности, то вдруг кому-то кажется что проще выставить в браузере низкий уровень безопасности …

Если следить за хронологией, то можно заметить:

Скоро останется только старый и не очень добрый IE. Евошний разработчик хоть и обещал поддерживать IE11 в Windows 10, но мы-то с вами знаем …

Что будет, если у бухгалтера внезапно отобрать возможность выгрузить любой отчет в Excel? Апокалипсис!
И вот Джавапокалипсис прилижается.


Рассмотрим варианты.

* * *
Поменять браузер (SAP GUI for HTML) на полноценный SAP GUI. Отпадает по административным показаниям.

Поменять браузер (SAP GUI for HTML) на NWBC. Но NWBC — это только оболочка вокруг того же IE, поэтому глубинных проблем данный подход не решает. Отпадает.
* * *
Заставить ZWWW работать на сервере и скидывать результат клиенту. Невозможно.
* * *
Если гора не идет к платформа не походит к движку, то можно поменять ZWWW на другой движок:

  1. Формуляры PDF
  2. Отчеты BI (BObj/BW/другое)
  3. Альтернативный движок Abap2xlsx

Все три сценария трудоёмки, но есть показания:

1. PDF генерируется на стороне сервера. Пользователь не может подправить содержимое. Некоторые формы нужны только для печати (“не отходя от кассы”) и не нужны в качестве рабочих документов в файловом виде. Самые простые примеры: приходный кассовый ордер, расходный кассовый ордер, счет к оплате и другие мелкие формы на одну страницу.

2. Некоторые отчеты нужны не только пользователям внутри системы, но и внешним пользователям, причём у этих внешних пользователей есть доступ к BI системе. Отчеты не требуют актуальности в режиме реального времени. Если в отчете есть нетривиальные расчеты, то можно выгружать итоговые расчеты в BI-систему и не заставлять BI-систему повторять эту сложную логику. Снижение нагрузки на ERP-систему. Возможна экономия на количестве лицензий. Рабочие отчеты могут остаться в системе, но без выгрузки в красивый Excel.

3. Всё оставшееся можно переписать с ZWWW на Abap2xlsx. Эта библиотека позволяет сделать генерацию файла Excel непосредственно на сервере. Подходы у этих двух библиотек кардинально разные, тут просто нельзя одни вызовы заменить на другие вызовы. Скорость существенно возрастёт, особенно для сложных документов. Необходимость поддержки старых форматов XLS уже не актуальна.

Это всё предыстория, а ради чего я начал писать-то… Допустим, переписали генерацию файла на Abap2xlsx, но его ещё и как-то скинуть на клиента надо красиво!

Скидывание файла на клиента по браузерному подходу можно выполнить с использованием функционального метода ALEWEB_DOWNLOAD. Дело-то он делает, но вот не очень красиво. Например, в нём нельзя управлять именем файла, а временные имена из случайных букв нравятся только системе, а людей от такого просто тошнит. Если покрутиться в том районе, то можно и подстучать, допилить, скопировать в Z-область. Скукота!

А можно сделать финт через сервис и HTTP-обработчик. Это очень интересно!

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

В эту таблицу мы будем складывать бинарные файлы, которые необходимо отдать клиенту. Сам файл хранится в поле XDATA.

HTTP-обработчики в системе реализуются в виде классов. За образец возьмём класс CL_HTTP_EXT_PING.

Создадим класс ZCL_WWW_FILE_DOWNLOAD и реализуем в нём метод HANDLE_REQUEST:

  data lt_query_string type tihttpnvp,
       ls_query_string type ihttpnvp.
  data ls_zwww_content type zwww_content.
  data lv_mimetype type string.
  data lv_filename type string.

  server->request->get_form_fields( changing fields = lt_query_string ).
  read table lt_query_string into ls_query_string 
    with key name = 'file_uid'.

  ls_zwww_content-file_uid = ls_query_string-value.
  select single * from zwww_content into ls_zwww_content 
    where file_uid = ls_zwww_content-file_uid.

  lv_mimetype = ls_zwww_content-mimetype.

  concatenate 'attachment; filename="' 
              ls_zwww_content-filename 
              '"'  into lv_filename.

  server->response->set_header_field( name = 'Content-Type' 
                                              value = lv_mimetype ).
  server->response->set_header_field( name = 'Content-Disposition' 
                                              value = lv_filename  ).

  server->response->set_data( ls_zwww_content-xdata ).

Всё тривиально:

  1. Считываем параметр file_uid из HTTP-запроса
  2. Достаём содержимое из таблицы
  3. Выставляем заголовки HTTP-ответа
  4. Скидываем содержимое файла в тело HTTP-ответа

Затем мы зарегистрируем в транзакции SICF новый сервис, и присвоим ему только что созданный обработчик:
Джавапокалипсис в отдельно взятой системе - 3

После этого сервис станет доступен по ссылке вида:
http://host:8000/sap/bc/ZFILE_DL?file_uid=5A2D5067C04D1ED5AFB71835DF981A07

Отлично! Осталось дело за малым: сделать выгрузку.

Сначала любым способом получаем бинарный файл XLSX. Например: посредством конвертации из ALV:

  data lo_converter type ref to zcl_excel_converter.

  create object lo_converter.

  lo_converter->convert(
    exporting
      io_alv        = gr_table
      it_table      = gt_report[]
      i_row_int     = 2
      i_column_int  = 2  ).

Затем добавляем файл в таблицу:

  data ls_zwww_content type zwww_content.

  clear ls_zwww_content.

  call function 'GUID_CREATE'
    importing ev_guid_32 = ls_zwww_content-file_uid.

  ls_zwww_content-filename = sy-repid && '.xlsx'.
  ls_zwww_content-mimetype = 'application/msexcel'.
  ls_zwww_content-uname = sy-uname.
  get time stamp field ls_zwww_content-timestamp.

  lo_converter->get_file( importing e_file = ls_zwww_content-xdata ).

  insert into zwww_content values ls_zwww_content.
  commit work  and wait.

Затем пинаем загрузчик:

  data lv_url type string.

  concatenate 'http://host:8000/sap/bc/ZFILE_DL?file_uid='
               ls_zwww_content-file_uid 
              '&sap-client=100&sap-language=RU' into lv_url.

  call function 'ITS_BROWSER_WINDOW_OPEN'
    exporting
      url               = lv_url
      window_name       = '_top'
    exceptions
      its_not_available = 1
      others            = 2.

Пробуем, драфт работает!

Но как можно подход ZWWW применить к Abap2xlsx?

А дальше происходит диалог:

  • А давай переделаем все отчеты…
  • Все?
  • Их сто! А у нас есть на это время?
  • Там есть группировки, динамические столбцы и макросы!
  • Макросы на бейсике, Карл!

То же самое, но в картинках

Джавапокалипсис в отдельно взятой системе - 4

На этой оптимистичной ноте я откланиваюсь. Спасибо за внимание и до новых встреч!

Автор: ivanbolhovitinov

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js