пʼятниця, 9 серпня 2019 р.

GIT remove commit

Small hints for myself regarding GIT.
Imagine we added 1.txt to some project and committed this file:
git add 1.txt
git commit -m 'test 1'
Then we added another file 2.txt and also committed:
git add 2.txt
git commit -m 'test 2'

After manipulations above we have the following situation:
$ git log --graph
* commit 53ec09a2cee2444877233ceca32c15779bb1d02d (HEAD -> master)
| Author: Yurii Petrovskyi
| Date:   Fri Aug 9 10:35:32 2019 +0300
|
|     test 2
|
* commit afb41e2d1fbab67a8cfaf316d41f81b73138b730
| Author: Yurii Petrovskyi
| Date:   Fri Aug 9 10:35:07 2019 +0300
|
|     test 1
|
* commit 0796e3cd0b010b3e84f565fd777811bfc3b225c4 (origin/master)

Then we need to undo the last commit (where we added 2.txt). In this case, it depends on do we want to save 2.txt file or we want to delete it. If we want to save the file and reset the last commit we need to use the next command:
git reset --soft HEAD~1
if we do not need this file at all:
git reset --hard HEAD~1

There is another scenario. We don`t want to push 1.txt from the first commit, so we should remove the file from repository's history:

git rm --cached 1.txt
git commit --amend -CHEAD

After commands above our "test 2" commit will contain removed 1.txt file and if we push it to the remote only 2.txt will be sent.

Also if we want to revert the whole specific commit we can use:
git revert commit_id

For example, I reverted "test 1" commit and this is a result:
git revert afb41e2d1fbab67a8cfaf316d41f81b73138b730
git log
commit 3ff659b964ca741a8c71dfa9ba45bcc74b66aa90 (HEAD -> master)
Author: Yurii Petrovskyi
Date:   Fri Aug 9 12:45:32 2019 +0300

    Revert "test 1"

    This reverts commit afb41e2d1fbab67a8cfaf316d41f81b73138b730.

commit 2d006836dda2d5558b4e1d2701b291c5187abfd1
Author: Yurii Petrovskyi
Date:   Fri Aug 9 12:43:44 2019 +0300

    test 2

commit afb41e2d1fbab67a8cfaf316d41f81b73138b730
Author: Yurii Petrovskyi
Date:   Fri Aug 9 10:35:07 2019 +0300

    test 1

commit 0796e3cd0b010b3e84f565fd777811bfc3b225c4 (origin/master)

If you pushed some changes and it was a mistake, in that case I used the following commands:
git reset --soft HEAD~1
git push origin -f

вівторок, 6 серпня 2019 р.

j_spring_security_check and Spring Security 4 and 405

Long story short, I migrated from Spring Security 3 to version 4.0.3.RELEASE. When I changed the version in pom file I faced with 405 error. In my login.jsp I had something like that:
*(I changed the character "<" to "!" to display the code)

!form style="margin-bottom: 0px;" action="../../j_spring_security_check" method="post">
Username:!input type="text" name="j_username" />!br/>
Password:!input type="password" name="j_password" />!br/>

Digging through Stackoverflow and other articles I found this useful link (note for the future: try to search in official documentation first :-) ):
https://docs.spring.io/spring-security/site/migrate/current/3-to-4/html5/migrate-3-to-4-xml.html#m3to4-xmlnamespace-form-login

So now I have login.jsp with the following text:

!form style="margin-bottom: 0px;" action="!c:url value='/login' />" method="POST">
Username:!input type="text" name="username" />!br/>
Password:!input type="password" name="password" />!br/>
!input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> !br/>
!input type="submit" value="Login" />

Update: For now I do not need CSRF filter in my project, so I removed one line from the code above (crossed out text) and added the following string in my spring-security.xml:
<security:csrf disabled="true" /> 

середа, 31 липня 2019 р.

NoClassDefFoundError and tools.jar

On my current project, I faced up with some bug which made me crazy:
java.lang.NoClassDefFoundError: com/sun/tools/attach/AttachNotSupportedException
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.getDeclaredMethods(Class.java:1975)
at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:609)
at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:521)

I used IDEA, Maven and Tomcat 9. Using IDEA Ultimate I created a configuration which should run my MVC project. In POM I had:
<dependency>
   <groupId>com.sun</groupId>
   <artifactId>tools</artifactId>
   <version>1.0.0</version>
   <scope>system</scope>
   <systemPath>${project.basedir}/lib/tools.jar</systemPath>
</dependency>
And everytime I saw the exception.
The Internet did not help and I was merely suffering. However, my teammate had already faced up with this kind of issue. So he advised me to put tools.jar into:
C:\Program Files\Apache Software Foundation\Tomcat 9.0\lib

And at last, it has worked.    

середа, 17 квітня 2019 р.

Unpivot the table

Recently I had an interview and interviewer asked me how I can to rotate the following table:
To rotate means to get the following result (example for shop_id = 1):
I suggested using unpivot and e.g. in Oracle it could be smth like that:

But I was interrupted and the additional requirement was what would I do if the use of unpivot is prohibited? I proposed to rewrite the sql-query via UNION ALL:

However, my opponent asked me to figure out one more method via a recursive query. And here it is:

And in general using queries above you can get the following result:

середа, 13 березня 2019 р.

The frequency of unique elements in the list

Just a small reminder for myself. You have a class:
public class Entity {
    private String name;
    private int count;

    public Entity(String name, int count) {
        this.name = name;
        this.count = count;
    }

    @Override
    public String toString() {
        return "Entity{" +
                "name='" + name + '\'' +
                ", count=" + count +
                '}';
    }
}

Then you create a test where you want to find out the frequency of every unique element (which is an instance of the class above) in the list. How can you do this? I am thinking to put all elements to HashSet to get distinct elements and then move through Set and call Collections.frequency. So the test could be like that:
import org.junit.Assert;
import org.junit.Test;
import java.util.*;

public class EntityTest {

    @Test
    public void testListToSet(){
        Entity entity1 = new Entity("Entity1", 1);
        Entity entity2 = new Entity("Entity2", 2);
        Entity entity3 = new Entity("Entity1", 1);
        Entity entity4 = new Entity("Entity2", 1);

        List entityList = new ArrayList<>(Arrays.asList(entity1, entity2, entity3, entity4));
        System.out.println("ArrayList: " + entityList);
        Assert.assertEquals(4, entityList.size());

        Set entityHashSet = new HashSet<>(entityList);
        System.out.println("HashSet: " + entityHashSet);
        Assert.assertEquals(3, entityHashSet.size());

        System.out.println("Frequency:");
        for (Entity entity : entityHashSet) {
            int frequency = Collections.frequency(entityList, entity);
            System.out.println(entity + " => " + frequency);
        }
    }

}

However, it will not work. Because you should override the equals and the hashCode methods. IDEA did it instead of me:
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Entity entity = (Entity) o;
    return count == entity.count &&
            Objects.equals(name, entity.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, count);
}

And after that the output will be next:
ArrayList: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}, Entity{name='Entity2', count=1}]
HashSet: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity2', count=1}]
Frequency:
Entity{name='Entity1', count=1} => 2
Entity{name='Entity2', count=2} => 1
Entity{name='Entity2', count=1} => 1

If we need to store our list to TreeSet we should implement Comparable interface and override compareTo method. My approach:
public class Entity implements Comparable {
    private String name;
    private int count;

    public Entity(String name, int count) {
        this.name = name;
        this.count = count;
    }

    @Override
    public String toString() {
        return "Entity{" +
                "name='" + name + '\'' +
                ", count=" + count +
                '}';
    }

    @Override
    public int compareTo(Entity o) {
        return Integer.compare(o.count, this.count);
    }
} 

And the test:
@Test 
public void testListToSet(){
    Entity entity1 = new Entity("Entity1", 1);
    Entity entity2 = new Entity("Entity2", 2);
    Entity entity3 = new Entity("Entity1", 1);
    Entity entity4 = new Entity("Entity2", 1);

    List entityList = new ArrayList<>(Arrays.asList(entity1, entity2, entity3, entity4));
    System.out.println("ArrayList: " + entityList);
    Assert.assertEquals(4, entityList.size());

    Set entityTreeSet = new TreeSet<>(entityList);
    System.out.println("TreeSet: " + entityTreeSet);
    Assert.assertEquals(2, entityTreeSet.size());
}

Output:
ArrayList: [Entity{name='Entity1', count=1}, Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}, Entity{name='Entity2', count=1}]
TreeSet: [Entity{name='Entity2', count=2}, Entity{name='Entity1', count=1}]

System environment variable in Centos 7

On my virtual-box machine (Centos 7) I tried to set the system environment variable via terminal like that:
export ADMIN_CONSOLE_HOME=" path to the folder"

and got the system environment variable in my Java code:
System.getenv("ADMIN_CONSOLE_HOME")

However, it didn`t help and returned NULL. Using Google-power I found out the solution how to set variables in Linux OS.
In my case, I added the following record to /root/.profile:
export ADMIN_CONSOLE_HOME=" path to the folder"

And after reboot all was fine. 

середа, 20 грудня 2017 р.

Batch script for removing extra symbols after extension

I try to develope my English skills that is why I going to write articles on English. Please enjoy :) 

Script which I have been using for deleting extra right's symbols after extension or other lookup string:

@echo off
setlocal EnableDelayedExpansion

set /p pth=Please input the path to the folder:
set /p ext=Please input the extension:
set replace=

for %%a in ("%pth%\*") do (
set fpath=%%~dpa

set fileVariable=%%~nxa
REM echo.!fileVariable!

CALL SET delPart=%%fileVariable:*%ext%=%%
REM echo.!delPart!

IF defined delPart (
CALL set string=%%fileVariable:!delPart!=!replace!%%
REM echo.!string!

IF defined string (
set "fullNameB=!fpath!!fileVariable!"
REM echo !fullNameB!

ren "!fullNameB!" "!string!"
echo "File: !fileVariable! was renamed to !string!"
)
)

)


pause

понеділок, 10 липня 2017 р.

Список COM-портов в Delphi

Появилась задачка определять к какому COM-порту подключен кассовый аппарат. Стал искать как получить список доступных портов в системе. В итоге нагуглил вот такой способ через реестр:

середа, 5 липня 2017 р.

Code Assistant в PL/SQL Developer не работает

Восстановившись после petya.a я столкнулся с некоторыми проблемами, одной из которых была неработоспособность функции подсказки названия объектов БД в PL/SQL Developer. Функционал этот называется Code Assistant и включается в настройках:
Но что бы я ни делал, при вводе 3 первых символов названия таблицы/процедуры/пакета/т.д. подсказка не выдавалась. Также ничего не происходило  и при нажатии на F6 (клавиша по-умолчанию для вызова Code Assistant). Точнее какие-то подсказки выдавались, например, если написать SEL, то появится подсказка SELECT и т.д., но объекты моей схемы я не видел.
Поиски по интернету привели меня к тому, что Code Assistant берет данные с запроса, который находится в файле CANames.sql в папке PLSQL Developer. Открыв файл я увидел иероглифы и все сразу стало на свои места: вирус petya.a шифрует файлы *.sql. В итоге, я взял файл с компьютера, где все работало , перезапустил PL/SQL Developer и Code Assistant заработал.

Вот что должно находится в файле:

середа, 28 червня 2017 р.

petya.a и как я восстанавливался

Windows Defender на работе выдает сообщение, что найден вирус, жму удалить - пишет, что невозможно. Забиваю, сижу, пишу код и тут PL/SQL Developer говорит, что мой файл с запросами был изменен. Нажимаю показать изменения и вижу слева SQL, а справа "привет с Алиэкспресса" (иероглифы). К нам заходят програмеры с соседнего отдела и говорят про вирус, советуют выключать комп. Жму кнопку выключения, компьютер тухнет. Через час, в новостях уже во всю пишут про вирус petya.a.
Вечером захожу в ближайший магазин, покупаю флешку и иду домой делать ее загрузочной. Прогуглив, нахожу утилиту YUMI с помощью которой записываю на флешку 2 образа: Boot-Repair-Disk и Avira Rescue System
Винда 10-ка, загружать нельзя, так как сразу начинается шифрование файлов под видом чекдиска, а потом и предложение заплатить 300 долл. Я загрузил Авиру и прогнал полную проверку - нашло каких-то 10 объектов (кряки тоже вошли в список) и удалило. Далее я перезагрузился и запустил Boot-Repair, нажал на кнопку, как было описано в инструкции.
Снова перезагрузился и попробовал запустить десятку - появилась ошибка:
A disk read error occurred Press Ctrl+Alt+Del to restart 
Полез искать в интернет - найденные варианты не подошли; еще пару раз повторил вышеописанное - та же ошибка. Пробую методом научного тыка: в live-usb от авиры есть программка GParted, в ней можно посмотреть на разделы винчестера. У меня 2 винта: SSD, на котором установлена 10-ка и HDD, на котором раньше была 8-ка. Я замечаю, что флаг boot для 10 установлен на раздел, который в 8-ке такого флага не имеет. В Windows 8 флаг boot установлен для секции system reserved. Решаю, что для Windows 10 тоже надо поставить boot на system reserved. Перезагружаюсь. Начинается загрузка винды :)
Пару замечаний:
- Я также воспользовался рекомендацией по поводу файла perfc (ищите в интернете).
- После загрузки Windows некоторые программы не запускались, либо слетела лицензия.

BSOD 0x0000007B и Windows7

Запараноился я значит по поводу petya.a и решил последовать инструкции, а конкретнее этой части:
To enable or disable SMBv1 on the SMB server, configure the following registry key:
Registry subkey: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\ParametersRegistry entry: SMB1
REG_DWORD: 0 = Disabled
REG_DWORD: 1 = Enabled
Default: 1 = Enabled
 
To disable SMBv1 on the SMB client, run the following commands:
sc.exe config lanmanworkstation depend= bowser/mrxsmb20/nsi
sc.exe config mrxsmb10 start= disabled
 
А после этого накатил обновление майкософта. Перезагрузился и только начал смотреть как 4 цвета логотипа сливаются в единый флаг, всю эту идиллию, на секунду прервал синий экран. Увидев синий цвет снова я понял, что вечер перестает быть томным и попробовал разные методы загрузки: от безопасного до последней удачной. В итоге загрузившись с параметром "не перезагружаться в случае ошибки", я увидел полный текст BSOD: 
0x0000007B (0xFFFFF880009A97E8, 0xFFFFFFFFC0000034, 0x0000000000000000, 0x0000000000000000)
Попробовал вернутся к точке восстановления, которая была автоматически создана при установке пакета обновлений безопасности от Майкрософт - та же ошибка.
Привет, Гугл. Следующие пару часов я просидел на куче форумов и блогов, перепробовал кучу разных способов: 
- В режиме восстановления подкорректировать ключи реестра: установить значение в 0 для ключа Start ветки HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\msahci и ему подобных.
- Провести chkdsk /f/r 
- Выполнить BOOTREC с ключами FIXBOOT и FIXMBR
- sfc /scannow /OFFBOOTDIR=E:\ /OFFWINDIR=E:\windows (диск Е: - это, в моем случае, диск С: в режиме восстановления)
- и т.д. и в разных комбинациях.
В общем спать уже хочется, а конца истории не видно. И тут я попадаю на ЖЖ какого-то парня, у которого такая же ошибка, только винда 2008 и диск в рейде. Он тоже описывает, что гугл уже не тот и ничего ему не помогало до тех пор, пока он не скопировал файлы с папки system32/config/regback в папку system32/config (прежде чем все затирать надо сделать резервную копию). 
С помощью командной строки и команд copy, и xcopy я заменил файлы в папке system32/config. Ребут, скрещиваю пальцы и наблюдаю лого windows. На часах было 3 ночи :(
Еще несколько слов:
- В папке regback  хранится резервная копия реестра, которую система создает каждые десять дней, если планировщик заданий не отключен.
- В процессе восстановления работоспособности ОС вспоминаешь забытое и узнаешь новое (не воспринимайте как призыв к действию "поломай виндовз и проведи весело вечер").
- В следующий раз я буду делать точку восстановления перед внесением изменений в реестр (не повторяйте моих ошибок).

 

понеділок, 19 червня 2017 р.

ENABLE NOVALIDATE проверяет имеющиеся данные

Понадобился мне констрейнт для проверки дублирующих записей в таблице, в которой уже присутствовали дубли. Добавил NOVALIDATE при создании и получил ошибку:
ORA-02299: cannot validate - duplicate keys found

Как выяснилось, при создании уникального ограничения создается уникальный индекс (не всегда, если оракл находит подходящий индекс - он будет использован). Выходом из ситуации стало добавление ключевого слова DEFERRABLE:
alter table TBL_1
  add constraint UK_TBL_1#NO_DOUBLE unique (col1, col2, col3, col4, col5)
  deferrable
  novalidate

DEFERRABLE делает так, что создается НЕуникальный индекс и констрейнт благополучно создается.

Также, можно было создать неуникальный индекс с самого начала и уже потом создать NOVALIDATE констрейнт.

CDATA в XML

Для того, что бы в XML появился тег
<![CDATA[test]]>

надо использовать метод XMLCdata:
select XMLCdata('test')
from dual;

четвер, 25 травня 2017 р.

Медленно выполняется запрос при join по dblink

Есть две таблицы: одна моя, другая удаленная. Связываю по праймари полю удаленной таблицы и мой запрос висит. Если напрямую обращаться к удаленной таблице с поиском по PK, то все отрабатывает быстро, в плане запроса видно, что используется primary key. Но только join и я жду.
Гугл выдает, что можно попробовать хинт driving_site. Добавляю хинт и запрос выполняется за секунду. Еще пару полезных ссылок по этой теме: раз, два.

пʼятниця, 14 квітня 2017 р.

InputBox в Delphi для ввода пароля

Что бы скрыть звездочками ввод в InputBox надо добавить маску #1 перед вторым параметром:
sPass := InputBox('Введите пароль', #1'Пароль:', '');

Вот ссылка на InputQuery, где описана данная фича, которая подходит и для InputBox. Если я правильно понял, то функционал был добавлен в версии XE.

середа, 12 квітня 2017 р.

ORA-39726 или как удалить колонку

Добавил в таблицу 2 новые колонки, а через время пересмотрел свое решение и понял, что они не нужны, и надо сделать по-другому. Пробую удалять и ... ошибка ORA-39726:
unsupported add/drop column operation on compressed tables

Лезу в гугл. Кайт и Бурлесон пишут, что надо делать так:
--помечаем колонки как неиспользуемые
alter table TBL_1 set unused column Column1;
alter table TBL_1 set unused column Column2;
--удаляем неиспользуемые колонки
alter table TBL_ROZ_SALES drop unused columns;

Судя по тому, что Том пишет, что при этой процедуре будет перезаписан весь сегмент, решил проводить операцию удаления колонок ночью. Весь процесс занял где-то минуту.

субота, 1 квітня 2017 р.

4wd robot arduino или машинка-конструктор с Китая

Заказал на алиэкспрессе вот такую машинку:

Собирал по мануалам и видео с интернета, гуглите "4wd robot arduino".
Первоначально собрал с сервоприводом и датчиком фиксации препятствий, который и был установлен на сервопривод. Код, который идет с видео сразу не работал, подкорректировал и все заработало:

Получилось вот так:

Поигрался и решил переделать на управление по блютузу, в комплекте идет модуль. Все подключил, программу написал:

и ... ардуино не воспринимает сигналы с телефона по блютузу, машинка не едет. Разбирался с проблемой пару часов, пока в комментариях кода, в одном из китайских примеров не увидел надпись:
Rx -> Tx
Tx -> Rx
А я подключал наоборот, думал, что если написано Rx, то надо и подключать к Rx =)
В общем, поменял контакты и все заработало.
Для управления с телефона использовал программу bluetooth spp pro.

Вот некоторые фотки процесса:


































Вообще мне набор понравился, возможно 42 доллара это и много, но мне было интересно собирать "конструктор", познакомиться с Arduino и разбираться с возникнувшими проблемами.

неділя, 29 січня 2017 р.

Raspberry Pi, Pi Camera и отправка email

Вот уже как пару дней, я пользуюсь своим детектором движений на малине. Основной принцип работы, я описал в первом абзаце этого поста. Фото и видео делает Pi Camera Module. Вот статья, в которой описаны основные моменты. Питанием для всей системы я выбрал Xiaomi Mi Power Bank 16000mAh. Реальная емкость где-то на уровне 12000 мАч. Непрерывной работы от одной полной зарядки банки хватает на 24-25 часов. Значит система потребляет где-то 500мА в час.
Корпусом для мини-пк я выбрал коробку от смартфона. Прорезал в ней отверстия под питание, usb-выход и кабеля для датчика движений. В итоге, в собранном виде все это дело выглядит вот так:
На Raspberry был установлен TeamViewer и, перед каждым уходом на работу, я подключаюсь и запускаю скрипт. Для того что бы камера не фиксировала меня когда я ухожу, я поставил задержку в 1 минуту.
Привожу полный код скрипта, который сейчас благополучно работает у меня:

Код по записи видео я закомментировал - мне, пока что, без надобности.

В итоге, хочу сказать спасибо людям, которые делились (и делятся) своими знаниями в Интернете касательно Raspberry Pi и всего, что его окружает. 

пʼятниця, 27 січня 2017 р.

CLOB через DBLink

Есть 2 базы, надо передавать CLOB с одной в другую. Сначала сделали процедуру, которая принимала на вход CLOB, но:
PLS-00564: lob arguments are not permitted in calls to remote server

Решили, что будем передавать CLOB в удаленную таблицу, а на той стороне обрабатывать. Написали инсерт и:
Error: PL/SQL: ORA-22992: cannot use LOB locators selected from remote tables


Решение проблемы:
Сделали у себя темповую таблицу:
create global temporary table TBL_TMP_CLOB
(
  c_clob CLOB
)


Делаем Insert From Select в удаленную таблицу:
INSERT INTO schema.remote_table@dblink(rem_clob) SELECT * FROM TBL_TMP_CLOB;





вівторок, 24 січня 2017 р.

Проблемы с Task Scheduler в Windows 10

Продолжаю допиливать свою raspberry pi-"систему видеонаблюдения". Для себя решил, что она должна работать по принципу: датчик фиксирует движение, камера делает снимок и отправляет мне на рабочую почту письмо, на работе у меня запущен шедуллер, который мониторит определенную папку в outlook и если там поменялось количество писем, то будет вызвана процедура по отправке смс мне на телефон. 
Столкнулся с проблемой простого создания задания, которое будет выполняться по расписанию.
Сразу приведу текст батника:
python webScrap1.py

Создал задание в Task Scheduler на запуск батника по расписанию в Windows 10. Жду... Ничего не запускается :(. Запускаю вручную - тоже ничего. Погуглил и нашел, что проблема может заключатся в положении переключателя "Run only when user is logged on". 
Изначально я поставил его в положение "Run whether user is logged on or not". Поменял, запустил вручную и увидел cmd-окно.
Но, хоть окно и мигнуло на секунду - ничего не произошло, смс не пришла. Поставил паузу в батнике - ошибка "не могу найти файл webScrap1.py". Прописал полный путь к файлу - cmd запускается и висит. Попробовал другие варианты - зависает пустое окно.
Методом "научного тыка" пришел к выводу, что просто указать название батника в поле с файлом, который будет запускаться не получится. Пришлось, как мне кажется, извратиться и запускать python.exe, а в аргументах указать путь к скрипту. Также надо указать папку, где лежит скрипт. Пример:

В следующих постах детальнее опишу, как будет работать вся система. Счастья, здоровья.