Рубрика: 3. Инструментарий

  • EncryptableProperties и защита от дурака

    Все знают, что не следует хранить в конфигурационных файлах (например properties) критически важную информацию в открытом виде.
    Например логины и пароли от базы данных, почты и т.д.
    Не стоит этого делать, т.к. “случайный” сисадмин или пользователь сможет открыть этот ваш файлик и увидеть пароль.

    С учетом того, что довольно часто пароли придумывают люди, то запомнить их бывает очень просто.
    Более того, некоторые пароли настолько поражают воображение, что их очень сложно забыть. Как правило они выглядят так: 123456, sa, manager и т.д…
    Конечно это личное дело каждого, но выставлять на обозрения такие свои пароли, как-то не совсем прилично.

    Если все-таки нет желания сильно напрягаться и прятать пароли в действительно укромные места, можно довольно просто сделать “защиту от дурака” (чтобы пароль явно не читался).

    Как вариант можно использовать Jasypt. Этот довольно большой проект и его можно использовать и в других целей, но мы будем разбирать простой и конкретный случай: предотвратить хранение паролей в открытом виде в properties файле.
    Главное, что нужно понимать, мы не строим защиту от серьезного злобного хакера, а делаем простую защиту от дурака!

    Для этого: (далее…)

  • Java + Excel файлы (Apache POI)


    С периодичностью раз в два-три года сталкиваюсь с проектами, в которых опять нужно работать с Excel файлами.
    Наверно это у меня что-то кармическое…
    Сейчас, в очередной раз приходиться реализовать полуавтоматический разбор сотен excel-файлов с прайсами.
    В прошлых своих проектах использовал JExcelApi.
    Ничего плохого про эту библиотеку сказать не могу, но хочется какого-то разнообразия в жизни поэтому в этот раз с товарищем решили попробовать Apache POI.

    Apache POI поддерживает как формат для обычных *.xls файлов (HSSF) так и *.xlsx файлы (XSSF).

    Кстати, формат для *.xls файлы в Apache POI они обзывают “HSSF – Horrible SpreadSheet Format”, то есть “Вселяющий ужас формат для электронных таблиц”.
    Для того, чтобы приступить к работе, как обычно прописываем зависимости в pom.xml:

      
            
                org.apache.poi
                poi
                
                3.7
            
        
    

    Для примера, приведу очень простой файл – список ФИО, сумма + Итог:

    Если нужно просто вытащить текст, можно использовать “класс-извелкатель”: ExcelExtractor (далее…)

  • Apache HTTPD, mod_jk, Apache Tomcat, Linux

    1. Начало.

    Если Вы ставите Tomcat как-то так: (от рута) aptitude install tomcat6 tomcat6-admin tomcat6-examples,
    то прежде чем двигаться дальше, вам возможно стоит обратить внимание на настройки URIEncoding в server.xml.

      
      
    

    Здесь и далее: Томкат => Apache Tomcat, Апач => Apache HTTPD.

    2. Вяжем.

    Классическая схема работы Томката (Apache Tomcat) в продакшене, это связка его с Apache (Apache HTTP Server) через mod_jk. Так делают уже много-много лет и это проверенное на практики и рекомендованное многими решение.
    Связка делается через протокол AJP (Apache JServ Protocol). Это специальный бинарный протокол для прокидки запросов от web-сервера в глубину к другим серверам (например Tomcat-у).

    Зачем такое нужно?
    1. Снижаем нагрузку с томката. Статику (картинки, html-ки и т.д.) пусть лучше отдает апач, а запросы к сервлетами и jsp-кам прокидываются томкату.

    2. Возможна балансировка нагрузки. Например один апач – несколько томкатов.

    Кстати, можно связывать апач не только с томкатом, а например с Jetty (через mod_proxy), и наоборот томкат прикручивать например к nginix. Мы здесь такие варианты не будем рассматривать.

    Итак, допустим у вас убунта с апачем и томкатом. На других линуксовых дистрибутивах аналогично.
    Ставим mod_jk: (от рута) aptitude install libapache2-mod-jk или скачаем и ставим отсюда : http://tomcat.apache.org/download-connectors.cgi

    Из общего правила структуры линуксовой файловой структуры мы знаем, что настройки должны находиться в папке /etc/.
    Легко видеть, что:
    – настройки томката будут в папке /etc/tomcat6
    – настройки mod_jk в /etc/libapache2-mod-jk
    – настройки апача в /etc/apache2

    Внимание! Дальше приводится упрощенная схема для работы в лабораторных условиях.
    На реальных серверах ввод в эксплуатацию без тщательного изучения документации по mod_jk, веб-серверу и томкату крайне опасен!
    Нужно обратить особое внимание на настройки безопасности.

    Теперь приступим. Начнем от фронта.
    В настройках сайта (например: /etc/apache2/sites-available/default) указываем какие запросы куда перенаправлять и кто должен делать обработку таких запросов.
    Например:

     
    ... 
        JkAutoAlias /usr/share/tomcat6-examples/
        JkMount /examples/* ajp13_worker
    
    

    ajp13_worker – название “ажп-работника”, он задается в файле workers.properties (в Убунте: /etc/libapache2-mod-jk/workers.properties):

      # список работников...
      worker.list=ajp13_worker
    

    Также в этом же файле нужно проверить другие параметры (порты, директории и т.д.).
    Если нужна балансировка загрузки, там уже есть заготовка для раунд-робина.

    Где находится файл workers.properties прописано в настройках mod_jk (в /etc/apache2/mods-available файл jk.load)
    Например, что-то типа этого:

    LoadModule jk_module /usr/lib/apache2/modules/mod_jk.so
    
    JkWorkersFile /etc/libapache2-mod-jk/workers.properties
    
    JkLogFile     /var/log/apache2/mod_jk.log
    JkLogLevel    info
    JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
    JkRequestLogFormat     "%w %V %T"
    
    JkOptions +ForwardURICompatUnparsed
    

    На что обратить внимание!
    Параметр JkWorkersFile указывает именно на правильный workers.properties
    Параметр JkOptions имеет значение “+ForwardURICompatUnparsed”, это нужно для нормальной обработки кодировок.

    Значение других параметров следует посмотреть в документации.

    Далее в настройках томката (/etc/tomcat6/server.xml) нужно проверить,
    что НЕ ЗАКОММЕНТИРОВАН AJP Connector (port 8009, URIEncoding=”UTF-8″):

    
     
       
    
    

    Общая схема конфигурационных файлов выглядит так:

    Не смотря на то, что в документации все хорошо описано, и есть такие полезные параметры как “JkAutoAlias”, которые сильно упрощают жизнь.
    Рекомендую, после того как завершите настройку тщательно проверить надежность и безопасность вашей конфигурации.

    По-крайне мере нужно проверить правильно ли будут работать ваши security-constraint и различные фильтры.
    Также проверить ограничение доступа к служебным ресурсам, работу в разных режимах (отключен томкат, реальные запросы из внешней сети и т.д.).

  • XMPP (Jabber) + Smack

    Недавно с товарищем начал работу над одним проектом, в котором нужно было написать программу для отправки сообщений пользователям по протоколу XMPP (т.е. через jabber).

    Список библиотек для работы нашли на официальном сайте xmpp.org.
    После серии небольших испытаний решили для интеграции с серверной частью написанной на Java использовать библиотеку Smack. Не факт, что будем использовать ее в продакшн, пытаемся распробовать. Пока продукт внушает доверие.

    1. Подключается к проекту элементарно (т.к. есть maven-овском репозитории): (далее…)

  • Работа с видео и аудио в Java. Xuggle

    Первый раз мне пришлось столкнуться с обработкой видео на Java лет 10-12 назад. Я еще был студентом и работал над проектом, в котором мы пытались сделать видео проигрыватель в виде апплета.
    В те времена, для перекодирования видео мы пробовали использовать JMF (Java Media Framework). Нам нужно было сделать хитрую предварительную обработку видео, т.к. показ видео осуществлялся апплетом с помощью самописного алгоритма. В итоге пришлось отказаться от JMF в пользу приложения написанного на С++, т.к. JMF оказался не особо функциональным…

    С тех пор прошло много времени, я участвовал в различных более масштабных и менее сумасшедших (и наоборот) Java-проектах (никак не связанных с видео), а тот проект проект был благополучно сдан и забыт. При этом какие-то знания по способам хранения и сжатия мультимедийной информации оказалось прочно засели у меня в голове (и даже некоторое время мучили ночными кошмарами)…


    Говорят история развивается по спирали. В прошлом году взялся за проект, в котором опять-таки требуется работа с видео/аудио потоками. Небольшие исследования показали, что JMF с тех пор особо не прогрессировал. Нельзя сказать, что этот фреймворк стоял на месте, но прогресс шел явно медленней, чем развитие технологий работы с видео в целом.
    К счастью спасение пришло от проекта (далее…)

  • oracle xe + ru. >_< Rrrr!

    Нужно было поставить Oracle XE на Windows XP (RU).
    Все нормально качается с официального сайта.
    Установка супер-простая (по сравнению с обычной установкой оракла).

    Пользователь по-умолчанию: system
    SID по-умолчанию: XE
    Панель управления доступна через на порту 8080.

    Админка работает, SQLPlus подключается и уже казалось, что счастье так близко.

    Если вы попытаетесь подключиться через JDBC, напоритесь на эпохальный баг с NLS.
    Достаточно в Google вбить: oracle xe nls и вы увидите огромное множество советов по решению этой проблемы.
    Вариантов уйма: править в реестре, менять локаль, выполнять магические команды в оракле, использовать специальный jdbc-драйвера от другой версии.

    Все это конечно очень весело, но мне интересно, когда-нибудь Oracle подправит это баг или нет?… Это же ужасно.

  • Maven: Lifecycle, Phase, Goal

    Для того, чтобы не запутаться в работе maven’а нужно разобраться с базовыми понятиями.

    1. Жизненный цикл (lifecycle) :  default, clean, site.

    2. Фазы (phase). Жизненный цикл состоит из чередования различных фаз. Например жизненный цикл clean состоит из фаз : pre-clean, clean и post-clean. Порядок выполнения важен. Если мы запустим mvn package , то также будут выполняться все предыдущие фазы: validate,compile, test и т.д.

    3. Цели, задачи, голы (goal).  Фазы состоят из чередования голов, например: gwt:run, assembly:assembly, compiler:compile (т.е. голы они с двоеточием).  Для того, чтобы указать какие голы должны быть забиты в какой фазе нужно в pom.xml  отредактировать секцию plugin.  Так сделано потому, что голы создаются плагинами.

    Вот такая матрёшка.

    Жизненный цикл состоит из фаз, а фазы состоят из голов.

    То есть, когда выполняется mvn clean gwt:run, мы проходим жизненный цикл clean, а затем забиваем гол gwt:run


  • Desktop wallpaper в качестве инструмента проверки браузера под различным разрешением

    Используем обои для рабочего стола

    У моего монитора разрешение 1680×1050, а в работе иногда нужно время от времени смотреть как будет выглядеть содержимое браузер например под разрешением 1024×768 или 1280×800.

    Да, я знаю, есть множество способов решить эту задачу, но я сделал так – нарисовал три прямоугольника разных размеров и установил полученную картинку на рабочий стол.

    Инструмент готов к использованию. Конечно это не так радует глаз как какая-нибудь супрематическая конструкция, но зато вполне утилитарно. Теперь для того, чтобы быстро проверить верстку в 1024×768 — подгоняем размер браузера под нужный прямоугольник и смотрим.

    При желании можно поместить в свободное пространство какую-нибудь приятную вам картинку. Я поместил Дюка (жавный маскот с красным носом). Он сейчас стал опенсорснутым, то есть вы его можете свободно (т.е. на халяву и безболезненно) использовать в различных целях. Например выкладывать в блогах и на своих веб страничках. Подробнее можно прочитать в “Open Source Duke”.

    Сами картинки с Дюком можно взять здесь.

  • Звездочка (*) в шестёрке и хитрые bat-файлы

    Запуск java-программы из командной  строки.

    Представим такую ситуацию

    В результате вашей работы в качестве java программиста у вас получился один JAR-файл (для простоты назовем его mytools-1.0-SNAPSHOT.jar). Кроме него вы планируете использовать более десятка других jar-файлов.

    Ваша программа должна запускаться из командной строки, а не из супер-пупер IDE которую вы обычно используете в работе. Например Вашу программу нужно отправить другому человеку, у которого нет такой же как у вас среды разработки (Eclipse, NetBeans, IDEA и т.д.) или запустить на удаленном сервере доступ к которому осуществляется только через SSH. Таким образом, для запуска вашей программы вам нужно собрать все требуемые для работы jar-файлы, прописать их  в CLASSPATH и для удобства написать простой runme.bat файл или (runme.sh для линукса).

    Рецепт 1.

    Требуется: maven, maven-assymbly-plugin

    Если вы используете maven, то возможно Вам будет удобно воспользоваться  maven-assymbly-plugin. Найти информацию по нему можно здесь: http://maven.apache.org/plugins/maven-assembly-plugin/

    В результате вы можете собрать в один JAR-файл, который содержит всё необходимое для работы.

    Для этого:
    1. добавляем в pom.xml настройки для maven-assymbly-plugin.

    <project>
      [...]
      <build>
        [...]
        <plugins>
          <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2-beta-5</version>
            <configuration>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
            </configuration>
            [...]
    </project>

    2. Запускаем сборку

    mvn assembly:assembly

    3. Получаем jar файл со всеми зависимостями:

    target/mytools-1.0-SNAPSHOT-jar-with-dependencies.jar

    Подробную информацию как работать со сборками можно получить открыв ссылку приведенную выше.

    Дальше, я предпочитаю копировать jar-файл в отдельную папку lib. После этого остается только создать простой BAT-файл в котором будет содержаться строка:

    java -cp mytools-1.0-SNAPSHOT-jar-with-dependencies.jar com.programmisty.Main %*

    %* – означает что все аргументы командной строки будут переданы в main-класс.

    Минусы: Если необходимо заменить только одну зависимость, приходится распаковывать и перепаковывать весь этот монолитный jar-файл.

    Рецепт 2

    Собираем все необходимые jar-файлы в одну директорию. Например с помощью maven это можно сделать командой

    mvn dependency:copy-dependencies

    Если вы не используете maven, можно просто скопировать руками все необходимые вам файлы.
    Затем копируем наш mytools-1.0-SNAPSHOT-jar и все дополнительные jar-файлы в папку lib.

    Если у нас windows, создаем BAT-файл runme.bat. В итоге у нас получается что-то вроде этого:

    .
    |_lib
    | |_mytools-1.0-SNAPSHOT-jar
    | |_commons-lang-2.4.jar
    | |_commons-logging-1.1.1.jar
    | |_commons-httpclient-3.1.jar
    | |-...
    |_runme.bat

    Теперь, возможно старым java программистам будет интересно узнать, что в Java 6 наконец-то в classpath можно использовать звездочку (*).
    Раньше многие делали так:

    set CP=lib/mytools-1.0-SNAPSHOT-jar
    set CP=%CP%;lib/commons-lang-2.4.jar
    rem "и так до самого конца"
    java -cp %CP% com.programmisty.Main %*

    Те кто похитрее делал так:

    setlocal ENABLEDELAYEDEXPANSION
    set CP=
    for %%i in (lib/*.jar) do set CP=!CP!lib/%%i;
    java -cp %CP% com.programmisty.tools.Main %*

    Если вы работаете в Linux, то для настоящего линуксоида получить список jar-файлов в директории и присвоить значение переменной — задачка “школьного” уровня. По этой ссылке можно найти несколько способ ее решения http://www.sql.ru/Forum/actualthread.aspx?bid=38&tid=569498

    Но теперь, если у вас java 6 это вообще не проблема, файл runme.bat может выглядеть следующим образом:

    java -cp "lib/*" com.programmisty.tools.Main %*

    Под линуксом wildcard (то есть звездочка) также успешно работает. Подробнее можно прочитать здесь: http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html в разделе “Understanding class path wildcards”

  • Hibernate. Update. Популярные грабли

    hibernate
    Сейчас многие любят реализовывать Data Access Object (DAO) на базе Hibernate.
    Хотелось уделить особое внимание работе с объектами в различных состояниях.
    Пример из документации :

       DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );
       cat.setName("PK");
       sess.flush();  // changes to cat are automatically detected and persisted
    

    Некоторые думают, что нужно делать так:

       DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );
       cat.setName("PK");
       sess.update(cat); // НЕ НАДО, ОНО САМО СОХРАНИТСЯ !!!! REMOVE THIS LINE
       sess.flush();  // changes to cat are automatically detected and persisted
    

    (далее…)