Thursday, January 27, 2011

100 лет IBM

16-го июня будет 100 лет со дня основания IBM, хотя тогда компания называлась Computing Tabulating Recording Corporation.

Краткий исторический экскурс:

IBM Centennial Film: They Were There - People who changed the way the world works

IBM Centennial Film: 100 X 100 - A century of achievements that have changed the world

Включение поддержки HTTPS для Tomcat (v6.0)

В принципе ничего сложно в этом, нет, но как всегда пришлось немного повозиться.
[шаг 1] Первым делом я предлагаю перевести логгинг в режим отладки. Для этого в файле logging.properties (находится в ${CATALINA_HOME}/conf или если его там нет, то нужно создать этот файл и поместить в classpath, или добавить, например, в WEB-INF/) нужно установить консольный логгинг в отладку:

java.util.logging.ConsoleHandler.level = DEBUG
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

[шаг 2] Далее нужно сгенерировать ключи, это делается с помощью keytool, которая обычно входит в JDK:

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA

По умолчанию файл ключей кладется в ${user.home} . Для того, чтобы сгенерировать ключи в заданный файл: \a\path\a\keystore, то это можно сделать так:

%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA \
-keystore \a\path\a\keystore

Keytool запросит пароль (пишут, что по умолчанию Tomcat использует changeit, но мне пришлось задавать его явно в описателе коннектора), запросит ФИО издателя ключей, отдел, компанию и т.д.
[шаг 3] Правим server.xml, который обычно находится в ${CATALINA_HOME}/conf. Нужно раскомментировать описание для SSL HTTP/1.1 Connector и добавить туда соотв. атрибуты:

<connector
port="8443"
maxthreads="150"
algorithm="SunX509"
scheme="https"
secure="true"
sslenabled="true"
keystorepass="changeit" clientauth="false"
keystorefile="${user.home}/.keystore"
sslprotocol="TLS">
</connector>

Расположение файла с ключами и пароль пришлось задавать явно. Алгоритм можно не задавать. Замечу, что для Oracle/Sun JVM алгоритм будет SunX509. Для IBM JVM значение скорее всего будет IbmX509. Как следствие, сгенерированные ключи могут быть не совместимы. Так ключи, сгенерированные с помощью Oracle/Sun JVM, у меня не сработали для IBM JVM.

Если все ок, то https://localhost:8443 должно привести к открытию страницы приветствия Tomcat. Если уже есть какие-то приложения, то ничего менять не надо. Они должны также запускаться под https по 8443 порту.

Примечание: если менять серверные настройки в eclipse, нужно убедиться, что файл настроек в рабочей области действительно синхронизирован с файлом на диске. Иначе все изменения в рабочей области никак не скажутся на работе сервера.

Подробнее можно посмотреть здесь и здесь.

Tuesday, January 18, 2011

Выбор ORM.

Так получилось, что рано или поздно нужно использовать persistence, что привело к необходимости искать подходящую ORM-технологию. PM предложил использовать openJPA. Но, думаю, будет полезно разместить здесь небольшой обзор существующих ORM-решений. Скорее всего буду возвращаться к этому посту и периодически обновлять его.

1. Чистый SQL. Есть люди, которые утверждают, что никакой ORM не нужен, что чистый SQL работает намного быстрее. На мой взгляд, утверждение весьма спорное в силу того, что:
a) не у всех есть достаточный опыт в SQL для разработки устойчивых, масштабируемых систем.
b) ряд ORM технологий допускают native - запросы к базам.
c) ряд ORM технологий инкапсулируют многочисленные native настройки, а также возможность эти самые native настройки менять напрямую.
d) в ряде случаев, опять-таки если не знать некоторые тонкие настройки производительность будет даже хуже, чем при использовании ORM-решения.

2. Hibernate: пишут, что это де-факто стандарт. Хорошая документация. Есть порт для .NET. Пока не проверял, но пишут, что Hibernate одно из наилучших в плане производительности решений. Опыт работы с Hibernate часто является ключевым требованием при приеме на работу. Распостраняется согласно LGPL.

3. Apache openJPA. Открытая реализация JPA стандарта от Apache. На удивление хорошая и своевременная документация. Есть много примеров.

4. Apache iBatis. Вообще не имеет ничего общего со стандартом JPA. Хороший выбор для фанатов SQL.

5. Apache Cayenne. Еще одно JPA-решение. Пока не выяснил, в чем принципиальное отличие от openJPA.

Линки по теме:
1. Сравнение Hibernate, OpenJPA и EclipseLink.
2. Stackoverflow тред по теме.

Tuesday, November 2, 2010

Редактор UML-диаграмм

В плане соотношения простоты и удобства понравился редактор диаграмм Dia (http://live.gnome.org/Dia, LGPL), есть порты под Linux, Win, OSX. Проект активно развивается, пока UML поддерживается в довольно упрощенном варианте: но в целом можно изобразить диаграммы последовательностей (хотя время жизни объекта редактируется не оч. удобно: используются 2 параметра - частота точек привязки и расстояние между ними), диаграммы развертывания, static-диаграммы, диаграммы пакетов и т.д. Поддерживает скриптинг на python, что тоже делает редактор любопытным для меня, так как это возможно понадобится для написания различного рода reverse-инструментов. Dia использует свой переносимый формат (пока глюков при переносе обнаружено не было).

Sunday, August 29, 2010

Softncoffee goes mobile

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

Friday, August 27, 2010

Ликбез по Linux за август

Короткое резюме за август.

1. подключение общих папок под Oracle Virtual Box:

Win32 guest: net use x:\\vboxsvr\host_shared_dir

Linux guest: sudo mount -t vboxsf host_shared_dir guest_mount_point

2. монтирование IMG-файла:

sudo mount -o loop linux-0.2.img mount_point

3. ssh: для работы потребуется openssh-client и openssh-server. Соотв. на target-машине должен быть поднят openssh-server.

ssh user@11.22.33.44 - наиболее простой вариант залогиниться в target- машину.
sftp user@11.22.33.44 - удобный ftp-client поверх ssl.

4. быстрый способ получить данные по некоторому url с помощью python:

tim@epsilon:~$ python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> data = urllib.urlopen("http://google.com").read()
>>> print "Read data: %s"%(data)


Отличная книга по python, к тому же бесплатная - здесь.

5. получение софтовых пакетов установленных на машину:

RHEL: rpm -qa
Ubuntu: dpkg-query -l
AIX: lslpp -L all

6. grep - очень мощный инструмент для поиска и фильтрации нужной информации:

получить все строки файла somewhere, в которых содержится aword:
grep aword somewhere.txt

пример: получить все пакеты, которые имеют в названии слово python:
dpkg-query --show | grep python


У большинства менеджеров пакетов есть всякий stuff, который позволяет получить подробную информацию об установленных пакетах. А также можно задавать каталог с базами данных или root-каталог, что позволяет сканировать установленный софт на некоторых ОС, расположенных на других разделах или дисках. Полезная, на мой взгляд, шпора для админов по unix - здесь

7. общие команды:

получение справки по команде, например для rpm: man rpm
удаление каталога рекурсивно, без подтверждения: rm -r -f your_dir
создание нового каталога: mkdir your_dir
перемещение/переименование файлов: mv source target
соединение файлов с их послед. выводом в стандартный поток: cat file1 file2 file3, можно использовать для вывода одного файла, в частности: cat file1

Friday, August 6, 2010

Знакомьтесь, антипаттерн double-checked locking

На днях размышлял, как можно было бы ускорить следующую конструкцию:
Конструкция 1. Известная всем реализация ленивого синглтона.

public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static synchronized Singleton getInstance()
{
if (INSTANCE == null)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
return INSTANCE;
}
}

Основным недостатком является наличие synchronized, которое по-хорошему нужно
только при инициализации экземпляра объекта singleton, а не при каждом доступе к нему.
Таким образом, сразу же напрашивается мысль, а что если попробовать использовать критическую секцию только при инициализации объекта:
Конструкция 2. Первая попытка сделать короче время доступа к INSTANCE.

public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static Singleton getInstance()
{
if (INSTANCE == null)
{
synchronized(Singleton.class)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
}
return INSTANCE;
}
}

Теперь инициализация объекта будет происходить при первом доступе к объекту, но, к сожалению, данная конструкция не спасает от конкурентного доступа. Так как может получиться так, что конкурирующие процессы после проверки INSTANCE на null последовательно войдут в критическую секцию и проинициализируют Singleton несколько раз. Тут же придумал workaround: поставить проверку на null после входа в критическую секцию, сказано - сделано:
Конструкция 3. Вторая попытка или double-checked locking антиппатерн.
public class Singleton
{
private Singleton(){}

private static Singleton INSTANCE;

public static Singleton getInstance()
{
if (INSTANCE == null)
{
synchronized(Singleton.class)
{
if (INSTANCE == null)
{
INSTANCE = new Singleton();
//
// ... perform an INSTANCE initialization
}
}
}
return INSTANCE;
}
}

Полученная конструкция в теории должна работать, но так ли это? Довольный своим открытием, я решил посмотреть, что пишут эксперты о такой конструкции, есть ли какие-то другие, более эффективные варианты ускорения реализации паттерна singleton. Очень быстро обнаружил, что такая конструкция действительно используется и называется она double-checked locking (в некоторых источниках такую конструкцию называют даже антипаттерном [2]). Действительно она применяется для ускорения singleton, но имеет ряд неочевидных недостатков для некоторых языков.

Недостаток первый. В некоторых языках, в т.ч. и в Java значение переменной INSTANCE может быть присвоено при выполнении конструктора до его завершения. Это связано с выделением памяти, как только выделяется память, то INSTANCE получает соотв. значение (в Java это ссылка, в других языках это, возможно, указатель на некоторую выделенную для объекта область памяти). Таким образом, есть вероятность, что пока один поток будет выполняться в критической секции, другой, выполнив проверку INSTANCE на null, в критиескую секцию уже не пойдет, а сразу вернет неинициализированную (но не равную null) переменную INSTANCE.

Недостаток второй. Запись и чтение значений переменных в многопоточных программах на некоторых языках могут зависеть от реализации конкретной исполняющей среды/компилятора. Например, в JAVA используется кеширование переменных: из соображений эффективности каждый поток может хранить свою собственную приватную копию переменной. Эта копия может синхронизироватся с основной памятью в различные моменты, например, при входе в критическую секцию и при выходе из нее [3]. Как вариант, в Java можно использовать модификатор volatile для переменной INSTANCE, которое действительно гарантирует атомарный доступ к переменной. В таком случае переменная никогда не кешируется потоками и доступ к ней осуществляется, как если бы это происходило внутри критической секции (synchronize над этой переменной). Но по сути это приводит к тому же от, чего уходили - к наличию критической секции при доступе к переменной.

Таким образом, рекомендуется использовать конструкцию 1 [2], либо использовать факт о ленивой загрузке классов [1]: т.е. что сам класс Singleton будет загружен лишь при первом обращении к нему, соотв. будут проинициализированны все static-поля и секции:
Конструкция 4. Если быть проще...
public class Singleton
{
private static Singleton INSTANCE = new Singleton();

static
{
// further INSTANCE initialization
}

private Singleton()
{
// Singleton initialization
}

public static Singleton getInstance()
{
return INSTANCE;
}
}


Материалы.

[1] http://www.ibm.com/developerworks/java/library/j-dcl.html
[2] http://www.javamex.com/tutorials/double_checked_locking_fixing.shtml
[3] http://www.javamex.com/tutorials/synchronization_concurrency_synchronized1.shtml