суббота, 29 декабря 2018 г.

Разница во времени (минус один час) на сервере Oracle Enterpise Linux 5.11

Не помню из-за чего и как давно началась проблема:
на сервере СУБД Oracle время ОС стало отставать от реального времени на 1 час.

Решение:
yum update tzdata

пятница, 28 декабря 2018 г.

Установка yum для Oracle Enterprise Linux 5.11 x64

При выполнении команды "yum" (например, "yum search java") появлялось сообщение:
"No module named yum".
Не помню, после чего.

Помогла переустановка yum:
скачал отсюда файл "yum-2.4.2-0.4.el5.rf.noarch.rpm" и установил командой:
rpm -Uvh yum-2.4.2-0.4.el5.rf.noarch.rpm

суббота, 22 декабря 2018 г.

PostgreSQL: пример исполняемого блока кода с динамически формирующимся содержимым и уведомлениями

create or replace function refresh_jenki_postgres_schemalist() returns void AS $$
declare
slct RECORD;
i integer;
i2 integer;
begin
/* Удаляет из таблицы «azk» для «jenki» записи об отсутствующих базах */
delete from azk a where not exists (select null from pg_database d where d.datname = a.dbname);
GET DIAGNOSTICS i = ROW_COUNT;
RAISE NOTICE 'Deleted rows: %', i;
/* Вставляем записи о базах, которые есть на сервере, но которых нет в таблице «azk» для «jenki» (за исключением баз, которые не относятся к АЦК) */
i = 0;
for slct in select 'insert into azk(id,dbname) values(nextval(''azk_seq''),'''||d.datname||''')' as stmt from pg_database d where not exists (select null from azk a where d.datname = a.dbname) and d.datname not in ('postgres','template0','template1','zabbix') order by d.datname loop
execute slct.stmt;
i = i + 1;
end loop;
RAISE NOTICE 'Inserted rows: %', i;
end $$ language plpgsql;

пятница, 21 декабря 2018 г.

[решено] Ошибка запуска службы Apache Tomcat под Windows

Столкнулся с проблемой:
после установки службы Apache Tomcat запуск этой службы прерывается ошибкой
«
Не удалось запустить службу Apache Tomcat 8.5 (для Jenki) на Локальный компьютер. Подробности содержатся в журнале системных событий. Если эта служба разработана не в Майкрософт, обратитесь к разработчику службы, и сообщите специфический для этой службы код ошибки 1.
»:


Отражение ошибки в журнале событий Windows:
«
Имя журнала: System
Источник: Service Control Manager
Код события: 7024
Уровень: Ошибка
Описание:
Служба "Apache Tomcat 8.5 (для Jenki)" завершена из-за следующей внутренней ошибки:
Неверная функция.
».

Причина оказалась в том, что при использовании скрипта (_installService.bat) установки службы в среде пользователя, под которым данный скрипт выполнялся, не были заданы переменные среды "JAVA_HOME" и "JRE_HOME", что привело к тому, что одна из настроек службы (а именно поле "Java Virtual Machine" на вкладке "Java" окна свойств службы, которое открывается с помощью копии "tomcat8w.exe") заполнилось некорректным значением "bin\server\jvm.dll" вместо правильного значения "C:\PROGRA~1\JAVA\JDK1.8.0_181\jre\bin\server\jvm.dll":

четверг, 22 ноября 2018 г.

Утилита "wushowhide.diagcab": показать или скрыть некоторые обновления Windows 10

Накопительное обновление для Windows 10 Version 1803 для систем на базе процессоров x64, 2018 11 (KB4467702)
по неустановленной причине неустанавливается (прерывается с ошибкой с кодом "0x80073712").

Обращение в службу техподдержки Microsoft проблему не решило (обращение № "Pro support: 800-936-4900 / 1-800-936-5800").

Временное решение:
отключить постоянную загрузку (и напоминание об установке) проблемного обновления с помощью утилиты "wushowhide.diagcab" из статьи:
https://support.microsoft.com/en-us/help/3073930/how-to-temporarily-prevent-a-driver-update-from-reinstalling-in-window

среда, 7 ноября 2018 г.

Многооконный режим MS Excel 2010

Windows 10 (x64) + MS Office 2010 (x32):

1. в папке «%USERPROFILE%\SendTo» создаем ярлык на файл «EXCEL.EXE», например «Ярлык Excel.lnk».
2. нажимаем правой кнопкой мыши на нужном файле и выбираем в контекстном меню Отправить —> Ярлык Excel, книга откроется в отдельном окне Excel.

Отсюда.

От Саши К.:
В приложении пункт меню Файл —> Открыть - дальше выбрать файл и открыть его - он откроется в новом окне.

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

АЦК jars (unistr <—> asciistr)

Для поиска в сборке:
select replace(replace(ASCIISTR('Документ "Сведение о платеже" не создан'),'\','\u'),'"','\"') from dual;
В обратную сторону:
select UNISTR(replace(replace('\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \"\u0421\u0432\u0435\u0434\u0435\u043D\u0438\u0435 \u043E \u043F\u043B\u0430\u0442\u0435\u0436\u0435\" \u043D\u0435 \u0441\u043E\u0437\u0434\u0430\u043D','\u','\'),'\"','"')) from dual;

суббота, 20 октября 2018 г.

В jenki сломалась sorttable

Перестала работать сортировка таблиц (функционал "sorttable"). Одновременно в консоли браузера (Ctrl+Shift+i) при загрузке главной страницы стала появляться ошибка:
sorttable.js:211 Uncaught TypeError: node.getAttribute is not a function
at Object.getInnerText (sorttable.js:211)
at Object.getInnerText (sorttable.js:236)
at Object.guessType (sorttable.js:170)
at Object.makeSortable (sorttable.js:87)
at sorttable.js:36
at Function.Array.forEach (sorttable.js:453)
at forEach (sorttable.js:492)
at HTMLDocument.init (sorttable.js:34)
getInnerText @ sorttable.js:211
getInnerText @ sorttable.js:236
guessType @ sorttable.js:170
makeSortable @ sorttable.js:87
(anonymous) @ sorttable.js:36
Array.forEach @ sorttable.js:453
forEach @ sorttable.js:492
init @ sorttable.js:34

Ошибка стала появляться, начиная с версии 0.8.
К ней приводят эти три строки (№№ 51-53):
<td style="width: 20px;">
<input type="button" class="btn-nice" value="${recnum}" onclick="window.open('spec.jsp?inID=${row.id}&name=${row.schemaname}','_self')"/>
</td>

Причину я так и не понял, но если убрать переносы строк, тогда ошибки нет и сортировка работает:
<td style="width: 20px;"><input type="button" class="btn-nice" value="${recnum}" onclick="window.open('spec.jsp?inID=${row.id}&name=${row.schemaname}','_self')"/></td>

Исправлено в jenki 0.11.6.

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

CMD и FAR: блочное и построчное выделение текста в режиме просмотра файлов (F3)

Режим выделения фрагмента текста зависит от галочки "Включить выделение переноса строк":
- галочка включена - выделение построчное;
- галочка отключена - выделение блочное.
См. пример:

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

Восстановление DBSERVER

[root@dbserver38 ~]# umount /mnt/hd2tb
umount: /mnt/hd2tb: not mounted
[root@dbserver38 ~]# mdadm --stop /dev/md0
mdadm: stopped /dev/md0
[root@dbserver38 ~]# mdadm --create --verbose /dev/md0 --level=10 --raid-devices=4 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
mdadm: layout defaults to n1
mdadm: chunk size defaults to 64K
mdadm: /dev/sda1 appears to contain an ext2fs file system
size=1953519872K mtime=Fri Sep 28 19:39:38 2018
mdadm: /dev/sda1 appears to be part of a raid array:
level=raid10 devices=4 ctime=Wed Apr 4 12:07:08 2018
mdadm: /dev/sdb1 appears to contain an ext2fs file system
size=1953519872K mtime=Wed Apr 4 18:18:58 2018
mdadm: /dev/sdb1 appears to be part of a raid array:
level=raid10 devices=4 ctime=Wed Apr 4 12:07:08 2018
mdadm: /dev/sdc1 appears to be part of a raid array:
level=raid10 devices=4 ctime=Wed Apr 4 12:07:08 2018
mdadm: /dev/sdd1 appears to be part of a raid array:
level=raid10 devices=4 ctime=Wed Apr 4 12:07:08 2018
mdadm: size set to 976759936K
Continue creating array? y
mdadm: array /dev/md0 started.
[root@dbserver38 ~]# mount -t ext4 -o rw,noatime,max_batch_time=0,nobarrier,data=writeback /dev/md0 /mnt/hd2tb

среда, 3 октября 2018 г.

вторник, 2 октября 2018 г.

УРВ в Jira

В Jira трудозатраты по задачам можно увидеть с помощью отчетов в пунктах меню:
1) Timetracker —> Reporting:

2) Tempo —> Расписания:

понедельник, 17 сентября 2018 г.

АЦК-Финансы и буфер обмена

Наблюдение: в дельфи-клиенте АЦК-Финансы 2.27.2.60 при нажатии на кнопку со статусом в окне редактирования документа (например, ЭД 17 класса) появляется сообщение об ошибке:
"Cannot open clipboard."
Помогает следующее:
1) открыть офисное приложение (например, "MS Excel");
2) на панели "Буфер обмена" нажать кнопку "Очистить все";
3) повторить работу с документом.




Примечание:
Аналогичная проблема замечена и для 2.46.0.155. Лечение такое же.

среда, 12 сентября 2018 г.

Java: гадание по стеку ошибки

Пример стека ошибки:
java.text.ParseException: Unparseable date: ""
    at java.text.DateFormat.parse(DateFormat.java:366) ~[na:1.8.0_45]
    at com.bssys.shared.BankUpdateED807Launcher.processRecord(BankUpdateED807Launcher.java:352) [AzkServer.jar:na]
    at com.bssys.shared.BankUpdateED807Launcher.processSingleFile(BankUpdateED807Launcher.java:265) [AzkServer.jar:na]
    at com.bssys.shared.BankUpdateED807Launcher.process(BankUpdateED807Launcher.java:116) [AzkServer.jar:na]
    at com.bssys.shared.BankUpdateED807Launcher.run(BankUpdateED807Launcher.java:95) [AzkServer.jar:na]
    at com.bssys.server.schedule.GenericSchTaskProcessor$1.process(GenericSchTaskProcessor.java:50) [Server.jar:na]
    at com.bssys.server.processor.AbstractProcessor.process(AbstractProcessor.java:90) [Server.jar:na]
    at com.bssys.server.system.XMLProcessor.processElementRes(XMLProcessor.java:123) [Server.jar:na]
    at com.bssys.server.system.TransactJob.process(TransactJob.java:386) [Server.jar:na]
    at com.bssys.server.system.TransactJob.run(TransactJob.java:293) [Server.jar:na]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_45]

Пример нахождения проблемной строки в байткоде на примере "luyten" (в меню "Settings" включить режим "Bytecode" и галочку "Show Line Numbers Bytecode"):

Примечание: для данного стека ошибки не удалось найти отражение нужной строки байткода (строки № 352) в режиме просмотра "Java", но и в режиме "Bytcode" информации оказалось достаточно.


Иногда проблемную строку байткода можно увидеть в режиме "Java", вот пример стека ошибки:
java.lang.NullPointerException: null
    at com.bssys.azkserver.sofit.common.expimp.export_fk.doc.zr.ExportZR195.getKbkRcp(ExportZR195.java:162) ~[AzkSofit.jar:na]
    at com.bssys.azkserver.sofit.common.expimp.export_fk.doc.zr.ExportZR195.getZRST(ExportZR195.java:118) ~[AzkSofit.jar:na]

Вот проблемная строка в байткоде в режиме "Java":


Та же проблемная строка в байткоде в режиме "Bytecode":

пятница, 3 августа 2018 г.

Неугодная языковая раскладка при терминальном подключении (RDP)

При терминальном подключении (RDP) на удаленном хосте (иногда) появляется дополнительная языковая раскладка (RU-EN). Бесит.
Проверяю способ лечения:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"IgnoreRemoteKeyboardLayout"=dword:00000001

пятница, 18 мая 2018 г.

Термины КС1 и КС2 по отношению к КриптоПро

КС1 и КС2 - разные классы защиты в соответствии с классификацией, используемой при сертификации ФСБ.
КС2 - более высокий класс защиты. Соответственно, дистрибутив КС1 сертифицирован по классу защиты КС1, дистрибутив КС2 - по КС2 (при условии использования дополнительных аппаратных средств).
С технической точки зрения CSP версии 3.0 КС1 отличается от КС2 тем, что в них по-разному организована работа с ключами. КС1 при работе с ключами хранит их в памяти приложений, КС2 при работе с ключами хранит их в службе хранения ключей (служба, которая ставится вместе с CSP). Второй вариант более безопасен, также во втором случае имеется возможность включения кеширования ключей.
Есть некоторые особенности функционирования, связанные как раз с разными методами хранения ключей и, следовательно, с разными правами (например, на рисование окошек). В виду этих особенностей на машинах, на которых работа с ключами будет осуществляться от имени сервиса (например, на сервере IIS или SQL) рекомендуется использовать КС2 (у КС1 будут проблемы с рисованием окошек запроса ключевых носителей); на терминальных серверах наоборот рекомендуется использовать КС1 (окошки службы могут не пробрасываться).

Сводная таблица:
Работа Хранение ключей Работа от имени Результат
Локально КС1 пользователь +
служба окна не рисуются
КС2 пользователь +
служба +
RDP КС1 пользователь +
служба окна не рисуются
КС2 пользователь +
служба окна не пробрасываются

Отсюда.

четверг, 10 мая 2018 г.

Java: получение имени хоста по IP-адресу

Пример:
package com.myjava.ip;
 
import java.net.InetAddress;
import java.net.UnknownHostException;
 
public class MyHostName {
 
    public static void main(String args[]){
     
        try {
            InetAddress host = InetAddress.getByName("72.167.232.155");
            System.out.println(host.getHostName());
        } catch (UnknownHostException ex) {
            ex.printStackTrace();
        }
    }
}

Если имя хоста найдено, тогда возвращает имя хоста.
Если имя хоста не найдено, тогда возвращает IP-адрес.
Если IP-адрес некорректный, тогда возвращает java.net.UnknownHostException.

Отсюда.

четверг, 12 апреля 2018 г.

Tomcat: перенаправления потока из окна консоли в файл

Для перенаправления потока из окна консоли в файл можно в скрипте запуска Tomcat (startup.bat или startup.sh) заменить эту строку:
call "%EXECUTABLE%" start %CMD_LINE_ARGS%
на эту:
call "%EXECUTABLE%" run >..\logs\outputfile.log 2>&1 start %CMD_LINE_ARGS% run >..\logs\outputfile.log 2>&1
Таким образом, все, что выводится в окно консоли, будет выводиться в файл outputfile.log

понедельник, 9 апреля 2018 г.

Скрипты для сборки АЦК-Транспорт и АРМ ПБС

!.BAT:
SET pth1=%cd:~0%
cd ..\
SET pth2=%cd:~0%
cd %pth1%
SET PATH=%pth2%\SYSTEM;%pth2%\USER;%PATH%
START %1 %2 %3 %4 %5 %6 %7 %8 %9
pause

!cbank.bat:
!.bat cbank.exe %1 %2 %3 %4 %5 %6 %7 %8 %9

!dedug_cbank.bat:
!.bat bsdebug.exe cbmain.ex %1 %2 %3 %4 %5 %6 %7 %8 %9

!dictman.bat:
!.bat dictman.exe %1 %2 %3 %4 %5 %6 %7 %8 %9

!operedit.bat:
!.bat operedit.exe %1 %2 %3 %4 %5 %6 %7 %8 %9

!setlogin.bat:
!.bat setlogin.exe %1 %2 %3 %4 %5 %6 %7 %8 %9

(черновик) Неконтролируемая перезагрузка Windows 10

09.04.2018
Столкнулся с проблемой: неконтролируемая перезагрузка Windows 10 Pro x64.
Не могу вспомнить, после чего началась проблема.
Проявляется довольно странно: только тогда, когда я блокирую компьютер и плюс некоторое время, пока он бездействует. Своими глазами перезагрузку я ни разу не видел, наблюдается это так:
- работаю, оставляю какие-нибудь программы или файлы открытыми;
- блокирую компьютер (либо отключаю RDP-клиент);
- отлучаюсь куда-нибудь;
- возвращаюсь, ввожу пароль;
- весь рабочий стол чист, будто ничего не оставлял.

В журнале событий обратил внимание на такое событие:
Имя журнала: System
Источник: Service Control Manager
Дата: 27.03.2018 3:42:33
Код события: 7040
Категория задачи:Отсутствует
Уровень: Сведения
Ключевые слова:Классический
Пользователь: СИСТЕМА
Описание:
Тип запуска службы "Фоновая интеллектуальная служба передачи (BITS)" был изменен с "Вручную" на "Автоматически".
Временно отключил эту службу, чтобы проверить догадку.
Вот уже несколько недель перезагрузок больше нет.

Нужно будет узнать, что это за служба и устранить причину перезагрузок.


Плюс огромное количество сообщений в журнале событий об этом:
Имя журнала: System
Источник: CProCtrl
Дата: 09.04.2018 10:31:33
Код события: 256
Категория задачи:Отсутствует
Уровень: Ошибка
Ключевые слова:Классический
Пользователь: Н/Д
Описание:
Ошибка проверки контрольной суммы. Файл: C:\WINDOWS\system32\cryptsp.dll. Причиной ошибки может быть обновление операционной системы или некорректная установка КриптоПро CSP. Переустановите КриптоПро CSP или обновите контрольную сумму библиотеки в реестре, запустив с правами администратора: start cpverify -addreg -file "C:\WINDOWS\system32\cryptsp.dll"

03.05.2018
Перезагрузки снова вернулись. Около 3-х недель назад. Уже не помню, после чего именно. Сегодня удалось увидеть перезагрузку своими глазами: оказалось, что действительно, обычный BSOD.
В нем было событие "DRIVER_OVERRAN_STACK_BUFFER". К сожалению соответствующий по времени файл дампа от 03.05.2018 16:07 (C:\WINDOWS\Minidump\050318-36375-01.dmp) оказался нулевого размера.
С помощью BlueScreenView посмотрел другой файл дампа (утренний за 03.05.2018), там оказалась информация:
==================================================
Filename : ntoskrnl.exe
Address In Stack : ntoskrnl.exe+e83db
From Address : fffff800`33408000
To Address : fffff800`33cde000
Size : 0x008d6000
Time Stamp : 0x5a7e7659
Time String : 10.02.2018 12:34:33
Product Name : Microsoft® Windows® Operating System
File Description : NT Kernel & System
File Version : 10.0.16299.248 (WinBuild.160101.0800)
Company : Microsoft Corporation
Full Path : C:\WINDOWS\system32\ntoskrnl.exe
==================================================

В общем, однозначно определить причину пока (мне) трудновато, поэтому погуглив решил предпринять следующее (отсюда):
удалил драйвера NVIDIA:
- NVIDIA 3D Vision;
- NVIDIA Аудиодрайвер HD.
Службе "Фоновая интеллектуальная служба передачи (BITS)" тип запуска вернул обратно "Автоматически".

пятница, 6 апреля 2018 г.

setenv для Tomcat

Как указывать переменные для Windows:
setenv.bat:
set JAVA_OPTS=%JAVA_OPTS% -XX:+UseG1GC -XX:+DisableExplicitGC -XX:MaxGCPauseMillis=1000 -Xmx2048m

Как указывать переменные для Linux (внимание на кавычки):
setenv.sh:
export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:+DisableExplicitGC -XX:MaxGCPauseMillis=1000 -Xmx2048m"

понедельник, 26 марта 2018 г.

Дерево сценариев, нюансы

Когда нужно отправить действие <action_name> в те документы, которые указаны на вкладке "Связанные документы" обрабатываемого документа:
notify_documents event="<action_name>"

Когда нужно отправить действие <action_name> в родительский документ обрабатываемого документа:
notify_parent event="<action_name>"

Когда нужно отправить действие <action_name> в дочерние документы обрабатываемого документа:
notify_child event="<action_name>"

пятница, 9 марта 2018 г.

GET и POST

Пример передачи параметров с помощью метода GET:
<input type="button" value="Кнопка открытия второй страницы" onclick="window.open('secondpage.jsp?param1=${param1}','_self')"/>
Пример передачи параметров с помощью метода POST:
<form action="secondpage.jsp" method="POST" target="_self">
  <input type="hidden" name="param1" value="${param1}"/>
  <input type="submit" name="btn1" value="Кнопка открытия второй страницы">
</form>

вторник, 6 марта 2018 г.

Пример Hello World + JSP + Java-classes

WEB-INF/classes/com/example/HelloWorld.java:
package com.example;

public class HelloWorld
{
  public static String hello;
// setter-method:
  public static void setHello(String newhello) {
    hello = newhello;
  }
// getter-method:
  public static String getHello() {
    return hello;
  }
}

index.jsp:
<%@ page import="com.example.HelloWorld"%>

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Servlet example</title>
  </head>
  <body>
    <%
    HelloWorld.setHello("Hello World 2");
    out.println(HelloWorld.getHello());
    %>
  </body>
</html>

Пример сервлета

На деле так никто, конечно, делать не будет, но в качестве примера пойдет:

index.jsp:
<%@ page import="java.sql.Connection"%>
<%@ page import="java.sql.DriverManager"%>
<%@ page import="java.sql.DatabaseMetaData"%>
<%@ page import="java.sql.ResultSet"%>
<%@ page import="java.sql.SQLException"%>
<%@ page import="java.sql.Statement"%>
<%@ page import="java.util.Properties"%>
<%@ page import="java.io.FileInputStream"%>
<%@ page import="java.io.File"%>
<%@ page import="java.io.IOException"%>

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Servlet example</title>
  </head>
  <body>
    <b><%
    int count;
    Properties props = new Properties();
    props.load(new FileInputStream(new File(application.getRealPath("WEB-INF/classes/myapp.properties"))));
    String dbUrl = props.getProperty("myapp.db.url");
    String dbUser = props.getProperty("myapp.db.user");
    String dbPass = props.getProperty("myapp.db.password");
    String[] splt = dbUrl.split(":",3);
    String dbType = splt[1].toUpperCase();
    String query = "select count(*) from sysuser";
    Properties conProps = new Properties();
    conProps.put("user", dbUser);
    conProps.put("password", dbPass);
    conProps.put("charSet", "Cp1251");
    Connection con = DriverManager.getConnection(dbUrl, conProps);
    DatabaseMetaData meta = con.getMetaData();
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(query);
    while (rs.next()) {
      count = rs.getInt(1);
      out.println("Count of users = " + count);
      out.println("<br>dbType=" + dbType);
    }
    %></b>
  </body>
</html>

Вывод даты-времени на JSTL и Java

Java:
<%@ page import="java.util.Date"%>
<%@ page import="java.text.SimpleDateFormat"%>
<%
SimpleDateFormat fmt = new SimpleDateFormat("dd.MM.yyyy HH:mm");
date = new Date();
out.println(fmt.format(date));
%>

Java (то же самое, только без переменных):
<%@ page import="java.util.Date"%>
<%@ page import="java.text.SimpleDateFormat"%>
<%out.println(new SimpleDateFormat("dd.MM.yyyy HH:mm").format(new Date()));%>
JSTL:
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<fmt:formatDate type="both" pattern="dd.MM.yyyy HH:mm" value="<%=new java.util.Date()%>"/>

понедельник, 5 марта 2018 г.

Import class in JSP

index.jsp:
<%@ page import="MyPackage.MyClass" %>
...
MyClass.class file location:
<tomcat>\webapps\<MyWebApp>\WEB-INF\classes\MyPackage\MyClass.class

MyClass.java:
package MyPackage;
...
import com.example.MyAnotherClass;

MyAnotherClass.class file location:
<tomcat>\webapps\<MyWebApp>\WEB-INF\classes\com\example\MyAnotherClass.class

воскресенье, 4 марта 2018 г.

Пример считывания ini-файла в Java

Example1.java:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.File;
import java.util.Properties;

public class Example1
{
  private static String dbUrl;

  public Example1() throws IOException
  {
    Properties props = new Properties();
    props.load(new FileInputStream(new File("./myfile.properties")));
    dbUrl = props.getProperty("db.url");
    System.out.println(dbUrl);
  }

  public static void main(String[] args) throws IOException
  {
    new Example1();
  }
}

javac Example1.java
java -cp . Example1

Firebird JDBC Encoding

При подключении к базе Firebird с помощью JDBC (jaybird-full-3.0.3.jar) появляется сообщение:
Фев 04, 2018 5:18:52 PM org.firebirdsql.logging.JulLogger warn
WARNING: WARNING: No connection character set specified (property lc_ctype, encoding, charSet or localEncoding), defaulting to character set NONE

Чтобы этого не происходило нужно:
- либо в строке подключения необходимо указывать кодировку "encoding=ISO/UTF/WIN...", например:
jdbc:firebirdsql:url:db?encoding=ISO8859_1
- либо:
Properties connInfo = new Properties();
connInfo.put("user", username);
connInfo.put("password", password);
connInfo.put("charSet", "Cp1251");
Connection db = DriverManager.getConnection(dataurl, connInfo);

пятница, 2 марта 2018 г.

CLI: Конвейер

Вертикальная черта, "конвейер", "перенаправление вывода", "трубопровод", pipe, пайп:
пример работы с двойной чертой для bash (аналогично и в cmd):
rm * || echo "Не могу удалить файлы"
Если при выполнении команды "rm" произойдет ошибка, например, удаляемые файлы будут заняты другим процессом, тогда на экране появится сообщение:
"Не могу удалить файлы"

вторник, 27 февраля 2018 г.

Java + SQL = JDBC

Select1.java:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Select1 {

    private static final String url = "jdbc:oracle:thin:@172.21.10.56:1521:ora";
    private static final String user = "AZ_USER";
    private static final String password = "AZ_PSWD";

    private static Connection con;
    private static Statement stmt;
    private static ResultSet rs;

    public static void main(String args[]) {
        String query = "select count(*) from sysuser";
        try {
            con = DriverManager.getConnection(url, user, password);
            stmt = con.createStatement();
            rs = stmt.executeQuery(query);

            while (rs.next()) {
                int count = rs.getInt(1);
                System.out.println("Total number of users: " + count + ".");
            }

        } catch (SQLException sqlEx) {
            sqlEx.printStackTrace();
        } finally {
            try { con.close(); } catch(SQLException se) { /*can't do anything */ }
            try { stmt.close(); } catch(SQLException se) { /*can't do anything */ }
            try { rs.close(); } catch(SQLException se) { /*can't do anything */ }
        }
    }
}

Компиляция:
javac Select1.java
Если поместить "ojdbc6.jar" в папку .\lib\ тогда команда запуска будет выглядеть так:
java -cp .;.\lib\ojdbc6.jar Select1
или так:
java -cp .;.\lib\* Select1

понедельник, 26 февраля 2018 г.

Groovy-скрипты для АЦК. Примеры.

Само выражение groovy-скрипта дожно быть условием (при этом указывать "if" необязательно, см.примеры ниже, сам groovy-скрипт всегда возвращает только 2 значения: "true" или "false" (по-умолчанию "false"), соответственно, пункт "Подписать" либо будет показан пользователю, либо - нет):
Примеры:
1) покажет пункт "Подписать" только если пользователь открывает меню действий документа класса 197:
document.documentclass_id.value == 197L;
2) покажет пункт "Подписать" только если пользователь открывает меню действий документа классов, у которых есть поле "CONTRACTOR_ID" (например, 3, 210, 197) и это поле содержит значение "302000014441":
document.contractor_id.value == 302000014441L;
Примечание: после слова "document" можно указывать те реквизиты, что упомянуты в классе, на который ссылается "Имя серверного класса обработчика документа".

Обратная связь:
Можно проверять значения реквизитов объектов, например, скрипт "println document.documentclass_id.value" будет выводить в окно консоли СП номер класса документа, который запустил скрипт.

Можно писать целые блоки:
import java.sql.*;
// Получаем ID органиации, которая указана в поле "Принадлежность к организации" текущего пользователя:
final PreparedStatement pstmt = con.prepareStatement("select u.org_id from usersession s join sysuser u on u.id=s.sysuser_id where s.id=?");
pstmt.setLong(1, con.session.getId());
//Можно применять запрос без параметров (см.конец следующей строки):
//final PreparedStatement pstmt = con.prepareStatement("select u.org_id from usersession s join sysuser u on u.id=s.sysuser_id where s.id=" + con.session.getId());
final ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
println rs.getString("org_id");
}
//Без этой строки в потоке вывода будет появляться предупреждение: "Some statements were not closed":
pstmt.close();

Еще пример:
import java.sql.*;
// Получаем ID организации из поля "Принадлежность к организации" текущего пользователя
Long usrOrgId = 0;
final PreparedStatement pstmt_usr = con.prepareStatement("select u.org_id from usersession s join sysuser u on u.id=s.sysuser_id where s.id=?");
pstmt_usr.setLong(1, con.session.getId());
final ResultSet rs_usr = pstmt_usr.executeQuery();
while (rs_usr.next()) {
usrOrgId = rs_usr.getLong("org_id");
}
pstmt_usr.close();
// Получаем ID бюджетополучателя текущего документа
Long docRecId = 0;
final PreparedStatement pstmt_doc = con.prepareStatement("select recipient_id from conbudget where contract_id=?");
pstmt_doc.setLong(1, document.id.value);
final ResultSet rs_doc = pstmt_doc.executeQuery();
while (rs_doc.next()) {
docRecId = rs_doc.getLong("recipient_id");
}
pstmt_doc.close();
//Сравниваем:
usrOrgId == docRecId;

В логе АЦК:

В логе СП АЦК информация о документе, связанном с ним groovy-скрипте, и результате выполнения этого скрипта выводится, начиная с уровня журнализации "DEBUG", в следующем виде (данные о документе отражаются после слова "document:", содержимое скрипта - после слова "script:", результат выполнения скрипта - после слова "result:", результатом выполнения скрипта могут быть три значения: "false", "null", "true" (примечание: если в правиле указан скрипт, тогда действие "Подписать" появляется у документа только при этом значении)), см. пример:

22.07.22 12:28:26.899,ORB-726433(535),DEBUG,GroovyExecutor,Script completed for:
document: EXPASSIGNMENT: ID=2400000129811;VERSION=3;DOCUMENT_ID=2400005674113;DOCUMENTCLASS_ID=128;DISPSTATUS_ID=0;...
script: return false;
result: false

четверг, 15 февраля 2018 г.

Для поиска в логе: запуск и завершение задания планировщика

25.10.18 13:13:37.234,ORB-2218563(53),DEBUG,TransactJob,Run TransactJob XML task=
<SESSIONCLEANERTASK action="run" sch_task="1"><PARAMS/></SESSIONCLEANERTASK>
25.10.18 13:13:37.235,ORB-2218563(53),DEBUG,TransactEngineImpl,Job started ID=53
25.10.18 13:13:37.235,ORB-2218563(53),DEBUG,SchTaskInfo,Running "Session cleaner" task
...
25.10.18 13:13:37.251,TRANSACT-53,DEBUG,XML,PROCESSOR: SESSIONCLEANERTASK: Processing input XML task<SESSIONCLEANERTASK action="run">
<PARAMS/>
</SESSIONCLEANERTASK>
...
25.10.18 13:13:37.625,TRANSACT-53,DEBUG,TransactEngineImpl,Job result=
<SESSIONCLEANERTASK completed="true"/>

вторник, 13 февраля 2018 г.

list_azkports.py

Аналог "azk_dir_port_listing.bat", только на Python3.
Отступы важны!
«
#22.04.2018 18:17 IRKT (изменен)
#13.02.2018 00:32 IRKT (создан)
#d.aryshtaev@bftcom.com

#Из названия папки, которая дожна быть именована в соответствии с форматом: <Версия АЦК>_<СУБД>_<порт СП>_<произвольный текст>
#утилита извлекает значение паттерна <порт СП> и сохраняет его в переменной s_port.
#Например, из названия папки "2.43.0.166e_FB_21013_BOD_170914" извлекает "21013".

import os, time, collections, sys, webbrowser

#Инициализация списков:
ls_port=[]
ls_port_ok=[]
ls_port_bad=[]
ls_port_dupl=[]
ls_port_ix = 0
ls_port_ok_ix = 0
ls_port_bad_ix = 0
ls_port_dupl_ix = 0

#Обработка папок:
ddirs = [d for d in os.listdir('.') if os.path.isdir(d)]
for d in ddirs:
  s_port = d[d.find("_",d.find("_")+1)+1:d.find("_",d.find("_",d.find("_")+1)+1)]
  try:
    i_port = int(s_port)
    ls_port_ix = ls_port_ix + 1
    ls_port.insert(ls_port_ix, i_port)
  except ValueError:
    ls_port_bad_ix = ls_port_bad_ix + 1
    ls_port_bad.insert(ls_port_bad_ix, s_port)

#Проверка списка ls_port на наличие дублей (информация о дублях заносится в список ls_port_dupl):
for tmpvar in ls_port:
  if ls_port.count(tmpvar) > 1:
    ls_port.remove(tmpvar)
    ls_port_dupl.insert(ls_port_dupl_ix, tmpvar)

#Убираем дубли из списков
ls_port = list(set(ls_port))
ls_port_dupl = list(set(ls_port_dupl))
ls_port_bad = list(set(ls_port_bad))

#Сортировка списков:
ls_port.sort()
ls_port_bad.sort()
ls_port_dupl.sort()

#Поиск пропущенных (по порядку) портов в списке:
for tmpvar in ls_port:
  ls_port_ok_ix = ls_port_ok_ix + 1
  if ls_port.index(tmpvar) > 0:
    if (tmpvar - ls_port[ls_port.index(tmpvar)-1]) > 1:
      #Если найдены пропущенные порты, то на их место ставим пустую строку, чтобы в конечном файле их было хорошо видно, затем найденный порт и приращиваем поисковый индекс:
      ls_port_ok.insert(ls_port_ok_ix, '')
      ls_port_ok.insert(ls_port_ok_ix, tmpvar)
      ls_port_ok_ix = ls_port_ok_ix + 1
    else:
      ls_port_ok.insert(ls_port_ok_ix, tmpvar)
  else:
    ls_port_ok.insert(ls_port_ok_ix, tmpvar)
#ls_port.insert(ls_port.index(tmpvar), 0)

#Вывод списков на экран:
#print("Все порты в названии папок:\n", ls_port, "\n")
#print("Дублирующиеся порты:\n", ls_port_dupl, "\n")
#print("Некорректные порты:\n", ls_port_bad, "\n")

#Вывод списков в файл:
filename = "azkport_listing.txt"
tmpdir=os.environ['TEMP']
filepath = os.path.join(tmpdir, filename)
ss_out = sys.stdout
f = open(filepath, 'w')
sys.stdout = f
if len(ls_port_ok) > 0:
  #print("Все порты в названии папок:\n", ls_port_ok)
  for tmpvar in ls_port_ok:
    print(tmpvar)

if len(ls_port_dupl) > 0: print("\nДублирующиеся порты:\n", ls_port_dupl)
if len(ls_port_bad) > 0: print("\nНекорректные порты:\n", ls_port_bad)
sys.stdout = ss_out
f.close()

#Открыть файл в ассоциированном приложении:
webbrowser.open(filepath)

#time.sleep(10)
»

понедельник, 5 февраля 2018 г.

Resultset after last row

При поиске причины ошибки
- для Oracle: "Resultset after last row" или "Набор результатов после последней строки");
- для Firebird: "The resultSet is not in a row, use next";
необходим лог (с полным текстом ошибки, включая ее стек).
При анализе методы из стека ошибки нужно сопоставлять "по смыслу" с XML-заданиями или SQL-запросами в логе.

azk_dir_port_listing.bat

@echo off

REM date-change 2018-02-05
REM date-create 2017-10-13
REM d.aryshtaev@bftcom.com
REM Утилита предназначена для сопровожденца АЦК.
REM Она выводит на экран текстовый файл со списком портов сборок (для удобства учета портов).
REM Ее нужно поместить в папку, в которой находятся сборки АЦК.
REM При этом наименования папок сборок должны соответсвовать формату <ВерсияАЦК>_<ИдентификаторСУБД>_<ПОРТ>_<ПРОИЗВОЛЬНЫЙ ТЕКСТ>, например:
REM 2.43.2.49e_21118_OR_AZ_IRKOBL_280917
REM 2.43.2.49e_21123_OR_AZ_LENOBL_8747_181017
REM 2.43.2.66e_21107_OR_AZ_AMUROBL_8898_221017
REM 2.43.2.72e_21114_FB_USTILIMSKE_170808

set tmp_rslt_file=%TEMP%\list_ports_result.csv
set rslt_file=%TEMP%\list_ports_result.txt
if exist %tmp_rslt_file% del %tmp_rslt_file%
for /f "delims=_, tokens=3" %%a in ('dir /A:D /B') do echo %%a>>%tmp_rslt_file%
sort %tmp_rslt_file%>%rslt_file%
start %rslt_file%

понедельник, 29 января 2018 г.

Запрос для запросов

Формирует пакет SQL-запросов типа "SELECT" с фильтром по одному констрейнту (PK_PURPOSEFULGRANT) и с условием по другому констрейнту (PK_BUDGET):

Варианты попроще
(по одному констрейнту):

Для Oracle:
select 'select * from (' as STMT1 from dual union all
select
'select '''||c.table_name||'.'||cc.column_name||''' as TBLCOL, count(*) as CNT from '
||c.table_name
||' t where t.'||cc.column_name||' in (123456789) union all'
from user_constraints c
join user_cons_columns cc on cc.constraint_name = c.constraint_name
where c.r_constraint_name='PK_ESTIMATE'
union all select ') where CNT <> 0' from dual
;

Для Firebird:
/* в закомментированном блоке - отсылки к знакомым мне обозначениям из Oracle */
select 'select * from (' as STMT1 from rdb$database union all
select
/*
cc.rdb$index_name as CONSTRAINT_NAME
,trim(c.rdb$relation_name) as TABLE_NAME
,trim(cc.rdb$field_name) as COLUMN_NAME
,trim(c2c.rdb$field_name) as COLUMN_NAME2
,c.rdb$foreign_key as R_CONSTRAINT_NAME
,trim(cci.rdb$relation_name) as R_TABLE_NAME
,trim(ccs.rdb$field_name) as R_COLUMN_NAME
,trim(c.rdb$relation_name)||'.'||trim(cc.rdb$field_name) as TBL_COL
*/
'select '''||trim(c.rdb$relation_name)||'.'||trim(cc.rdb$field_name)||''' as TBL_COL, count(*) as CNT from '
||trim(c.rdb$relation_name)
||' t where t.'||trim(cc.rdb$field_name)||' in (123456789) union all' as SQLA
from rdb$indices c
join rdb$index_segments cc on cc.rdb$index_name = c.rdb$index_name
join rdb$index_segments ccs on ccs.rdb$index_name = c.rdb$foreign_key
join rdb$indices cci on cci.rdb$index_name = ccs.rdb$index_name
where
trim(c.rdb$foreign_key) = 'PK_ESTIMATE'
union all select ') where CNT<>0' from rdb$database
;


Вариант посложнее:
(по двум констрейнтам одновременно)

Для Oracle:
select 'select * from (' as STMT1 from dual union all
select
'select '''||c.table_name||'.'||cc.column_name||' ('||c2c.column_name||')'' as TBLCOL, count(*) as CNT from '
||c.table_name
||' t where t.'||cc.column_name||' is not null and exists (select null from PURPOSEFULGRANT p where p.ID=t.'||cc.column_name||' and p.BUDGET_ID<>t.'||c2c.column_name||') union all'
from user_constraints c
join user_cons_columns cc on cc.constraint_name = c.constraint_name
join user_constraints c2 on c2.table_name=c.table_name and c2.r_constraint_name='PK_BUDGET'
join user_cons_columns c2c on c2c.constraint_name = c2.constraint_name
where c.r_constraint_name='PK_PURPOSEFULGRANT'
union all select ') where CNT <> 0' from dual
;

Для Firebird:
/* в закомментированном блоке - отсылки к знакомым мне обозначениям из Oracle */
select 'select * from (' as STMT1 from rdb$database union all
select
/*
cc.rdb$index_name as CONSTRAINT_NAME
,trim(c.rdb$relation_name) as TABLE_NAME
,trim(cc.rdb$field_name) as COLUMN_NAME
,trim(c2c.rdb$field_name) as COLUMN_NAME2
,c.rdb$foreign_key as R_CONSTRAINT_NAME
,trim(cci.rdb$relation_name) as R_TABLE_NAME
,trim(ccs.rdb$field_name) as R_COLUMN_NAME
,trim(c.rdb$relation_name)||'.'||trim(cc.rdb$field_name) as TBL_COL
*/
'select '''||trim(c.rdb$relation_name)||'.'||trim(cc.rdb$field_name)||' ('||trim(c2c.rdb$field_name)||')'' as TBL_COL, count(*) as CNT from '
||trim(c.rdb$relation_name)
||' t where t.'||trim(cc.rdb$field_name)||' is not null and exists (select null from PURPOSEFULGRANT p where p.ID=t.'||trim(cc.rdb$field_name)||' and p.BUDGET_ID<>t.'||trim(c2c.rdb$field_name)||') union all' as SQLA
from rdb$indices c
join rdb$index_segments cc on cc.rdb$index_name = c.rdb$index_name
join rdb$index_segments ccs on ccs.rdb$index_name = c.rdb$foreign_key
join rdb$indices cci on cci.rdb$index_name = ccs.rdb$index_name
join rdb$indices c2 on c2.rdb$relation_name = c.rdb$relation_name and c2.rdb$foreign_key = 'PK_BUDGET'
join rdb$index_segments c2c on c2c.rdb$index_name = c2.rdb$index_name
where
trim(c.rdb$foreign_key) = 'PK_PURPOSEFULGRANT'
union all select ') where CNT<>0' from rdb$database
;

пятница, 26 января 2018 г.

ГИС ГМП: Пример настройки для тестового стенда

Azk2Server.properties:
#---------------Сопровождение 2016-1, #8171-----------------------
#(Тестовый контур ГИС ГМП)
gisgmp.wsdlLocation=http://smev-mvf.test.gosuslugi.ru:7777/gateway/services/SID0003663?wsdl
gisgmp.wsdlLocation.endPoint=http://smev-mvf.test.gosuslugi.ru:7777/gateway/services/SID0003663
gisgmp.sign=true
gisgmp.recipientCode=RKZN35001
gisgmp.recipientName=Казначейство России
#----------------------------------------------------------

Для тестирования связки между АЦК-Финансы и ГИС ГМП для ЭП ОВ можно использовать любую валидную тестовую ЭП, для этого, необходимо импортировать ее в АЦК-Финансы и в ее карточке в поле «Статус субъекта» указать значение «Юр. лицо».
После этого, нужно указать ее в поле «Сертификат ОВ» в карточке организации финоргана.
Но ЭП СП должна быть настоящей.

Было актуально на 2016 год.
Больше не проверял.

вторник, 23 января 2018 г.

Для телеграм-бота

Журнал бота:
https://api.telegram.org/bot<TOKEN>/getUpdates;
Отправить сообщение от бота в чат/адресату:
https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<CHAT_ID>&text=<MY_TEXT>

Директории ".xasystem" и "STORE_DATA_ON_CLIENT_IN_FILE" (не отвечено)

От чего зависит появление (или непоявление) папок ".xasystem" и "STORE_DATA_ON_CLIENT_IN_FILE" в сборке АЦК?
В поисках ответа пока что ...

Примечание 1:
Предварительная версия:
зависит от параметра "Способ обновления по умолчанию" (
пункт меню Сервис —> Системные параметры —> Обновление клиентской части —> вкладка "Настройки обновления"):
- "Отключено" - папки не появляются;
- "Через сервер приложения" - папки появляются.
(наверное, при других значениях, отличных от "Отключено" тоже будут появляться).
- появляются только тогда, когда БД запускается впервые после рестора.

Требует дополнительной проверки.

Примечание 2:
Время создания папок совпадает с сообщениями в логе СП:
23.01.18 05:01:14.671,ORB-1225499(800),WARN,DataStorage,Parameter azk.storage.conf not specified
23.01.18 05:01:14.672,ORB-1225499(800),WARN,DataStorage,com.bssys.server.system.storage.StoreDataOnCl
23.01.18 05:01:15.813,ORB-1225499(800),INFO,FileDataDevice,Booting completed for the XADisk instance.

вторник, 9 января 2018 г.

Архив