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

Обновление времени в Java.

Заметка об обновлении времени, на которую у меня все никак не хватало времени. 1419292146_clock

Речь идёт о смене временных зон для Oracle JDK/JRE. Такие изменения могут быть вызваны например отменой летнего/зимнего времени, сокращением часовых поясов за счет их объединения и другими обстоятельствами.
Для этих целей можно использовать Timezone Updater Tool.

Чтобы выполнить обновление нужно выполнить следующие шаги:
1. Загрузить с сайта jar-ик (http://www.oracle.com/technetwork/java/javase/downloads/index.html).
tzupdater_download

2. Затем запустить из консоли как обычную java-программу с ключами -u -v:

java -jar tzupdater.jar -u -v
-u означает обновить (update)
-v для показа дополнительной детальной информации (verbose).

Естественно, если у вас несколько JVM, то сначала нужно разобраться, какую конкретно вы хотите пропатчить. Поэтому на всякий случай проверьте, что конкретно указано в bat- или sh-скриптах которыми вы запускаете сервер и какая именно java запускается.

PS: Перед запуском, еще раз прочтите внимательно инструкцию на официальном сайте, не забудьте проверить права доступа и наличие резервной копии (это общие правила, они касаются вообще любых сервисных работ проводимых на сервере).

Рубрики
Java UML

HTTPS авторизация по сертификату

Отправка простых HTTP запросов из Java уже хорошо описана в различных источниках, например в официальном туториале, поэтому пересказывать в очередной раз как работать с URL и выкладывать примеры кода не вижу смысла. В случае если приходится работать с защищенным HTTPS соединением, также особых осложнений у большинства программистов возникнуть не должно (возможно кроме случаев с самозаверенными сертификатами, но на эту тему также очень много учебного материала в интернете). Несколько больший интерес представляют собой случай, когда HTTPS подключение требует дополнительной авторизации по клиентскому сертификату. Вот об этом и пойдет речь в этой статье.

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

Более распространен такой способ авторизации не в клиент-серверных решениях, а скорее в межсерверном взаимодействии. Например при решения задач в сфере B2B, когда необходимо отправлять запросы к различным серверам контрагентов и внешним системам. Отчасти это связанно с тем, что одним из популярных способов создания таких коммуникаций является использование веб-служб, что в свою очередь означает программную отправку HTTP запросов. Поскольку внутренняя реализации JAX-WS, базируется на использовании стандартных классов (URL, HttpURLConnection и т.д.), решив задачу в общем виде (отправка https запросов с авторизацией по сертификату) автоматически решается задача для клиента веб-службы (речь идет о JAX-WS, в Axis2 задачу решать можно немного другим способом).

Самое простое что можно сделать для решения этой задачи — указать ключи и пароли в системных свойствах:

-Djavax.net.ssl.keyStore=privateKey.jks
-Djavax.net.ssl.keyStorePassword=myPrivateKeyPassword
-Djavax.net.ssl.trustStore=truststore.jks
-Djavax.net.ssl.trustStorePassword=myTrustStorePassword

В данном случае в файл privateKey.jks вы можете положить свой приватный (закрытый) ключ, с помощью которого будет проходить аутентификация на сервере и (при необходимости) в файл truststore.jks положить сертификат сервера, к которому идет обращение.

Хранилище ключей может иметь тип не только JKS (Java Key Store), но например быть в более распространенном формате PKCS12. В таком случае в настройках следует указать тип хранилища:

-Djavax.net.ssl.keyStoreType=pkcs12
-Djavax.net.ssl.keyStore=privateKey.p12                
-Djavax.net.ssl.keyStorePassword=myPrivateKeyPassword

Очень хорошо описаны отличия в использовании JKS и PKCS12 в статье Java 2-way TLS/SSL (Client Certificates) and PKCS12 vs JKS KeyStores.

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

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

Общая последовательность шагов будет выглядеть следующим образом.
1. Получить хранилище ключей.
2. Создать объект класса менеджера ключей.
3. Создать объект управляющий доверенными сертификатами.
4. Произвести инициализацию ssl-контекста.

Теперь нужно разобраться, кто это такой "менеджер ключей" и "управляющий доверенными сертификатами", а также с кем еще возможно придется столкнуться. Для этого приведу сильно упрощенную диаграмму классов:
sslcontext

Из диаграммы легко видеть как можно управлять поведением работы программы. Например, чтобы поменять логику выбора алиаса, можно сделать наследника класса менеджера ключей (KeyManager).
Для этого вначале нужно получить хранилище ключей (KeyStore), а дальше сделав своего наследника, который будет работать с ключами, передать его в метод для инициализации SSL контекста. Самый простой способ сделать такого наследника — получить менеджера ключей по-умолчанию, а затем обернуть его методы таким образом, чтобы основные методы "проксировались" и в то же время можно было перекрыть нужный метод со специфической логикой (выбор алиас, отслеживание какой ключ/принципал используется и тд).

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

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

 
/**
 *
 * @author Vit vit@programmisty.com
 */
public class Demo {
 
    public static void main(String[] args) throws Exception {
        SSLContext sc = SSLContext.getInstance("SSL");
 
        // Каким-то образом получили хранилище ключей. Это за рамками статьи.
        KeyStore keystore = ... ;
 
        String algorithm = KeyManagerFactory.getDefaultAlgorithm();
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
        // не забываем инициализировать менеджера ключей
        keyManagerFactory.init(keystore, password);
        // получаем список менеджером (при необходимости делаем наследника и/или оборачиваем keyManager)
        KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
        // если у нас свой список доверенных серверов
        TrustManager[] trustManagers = getTrustManagers("/trusted.jks", "trustedPassword".toCharArray());
        sc.init(keyManagers, trustManagers, null);
        // проставляем контекст
        SSLContext.setDefault(sc);
        // для проверки отправляем запрос
        String url = "https://my-secure-server.com";
        try (InputStream in = new URL(url).openStream()){
            System.out.println(IOUtils.toString(in));
        }
    }
 
    /**
     * если у нас какой-то свой файлик с доверенными сертификатами
     */
    private static TrustManager[] getTrustManagers(String path, char[] passwd) throws Exception {
        String algorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
        // Загружаем доверенных
        KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
        // Из ресурсов, так проще. 
        InputStream keystoreStream = Demo.class.getResourceAsStream(path);
        keystore.load(keystoreStream, passwd);
        trustManagerFactory.init(keystore);
        // 
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
        return trustManagers;
    }
}
Рубрики
Java

Заметки по Derby DB

Нельзя сказать, что к Derby DB у меня особо теплые отношения. Первое знакомство с ней произошло много лет назад, когда на работе возникла идея прикрутить Derby вместо полноценной базы данных, чтобы проще было готовить демку программы к выставке. Идея была в том, что если взять легковесную встраиваемую базу, то тогда развертывание демонстрационного дистрибутива сильно упростится — скопировал файлики и ничего настраивать не нужно (в отличие от Оракла). В случае если нам нужен всего-лишь выставочный демонстрационный образец ПО такое решение было вполне оправдано. Почему выбор пал в тот момент именно на дерби думаю сейчас мало уже кто вспомнит.
В итоге конечно всё прикрутить получилось, но скорость работы базы на тот момент оставляла желать лучшего. Возможно где-то я был не прав (был молодым и неопытным), а возможно и сама база была "юной" и не достаточно расторопной. derby_db_logo

С тех пор прошло много времени, Derby уже давно поставляется вместе с JDK под именем Java DB, поэтому думаю в жизни многих Java-программистов также возникали случаи совместной работы с этой удивительной базой данных. Собственно поэтому решил описать некоторые её капризы и особенности. Сразу хочу заметить, что эту БД использую в жизни не так часто и возможно именно поэтому ее поведение меня иногда удивляет.

1.Кидается исключениями при отключении.

Чтобы отключить БД в embedded режиме, нужно в JDBC-URL прописать "jdbc:derby:;shutdown=true". Если всё нормально, в вас обязательно при отключении кинут исключением SQLException с кодом XJ015. К этому нужно привыкнуть и не пугаться.

2.Режим использования RAM (In-memory).

У Derby есть не плохой экспериментальный режим, когда она работает в памяти.
Удобно использовать для создания временного окружения (чтобы не удалять созданные файлы и директории) или в различных jUnit-тестах.
Опять таки все делается через URL, например для создания пишем: "jdbc:derby:memory:myDB;create=true".

При этом если вы сделаете shutdown, но не потушите JVM, то ваша БД не почистится. Чтобы удалить данные из памяти нужно сделать сделать drop (jdbc:derby:memory:myDB;drop=true), который сам сделает shutdown:
You can shut down an in-memory database using the shutdown=true attribute before you drop the database, but this is optional. Dropping the database also performs the shutdown.

3.JRE7u51

В JRE7u51 поменялись ограничение в настройках безопасности. Поэтому при запуске дерби в сетевом режиме могут валиться исключения AccessControlException.
На официальной странице oracle предлагается решение, в котором необходимо настроить собственный security.policy файл, чтобы в нем был доступ к порту (по-умолчанию 1527). Например так:

grant {
    permission java.net.SocketPermission "localhost:1527", "listen";
};

Хорошая пошаговая инструкция на странице администрирования.

Рубрики
Java

Распараллеливание задач в Java через InvokeAll

Одно время у меня были некоторые сомнения имеет ли смысл публиковать эту статью, т.к. в целом мне нечего сказать такого, что нельзя было найти в официальной документации об invokeAll. Затем, при общении с другими программистами, стал время от времени замечать не совсем правильное (на мой взгляд) понимание его работы. Поэтому пока есть свободное время решил все-таки закончить эту заметку.

Сразу хочу заметить, что мне не очень хочется углубляться в описание всей мощи java concurrent API, а просто расставить некоторые акценты при работе над небольшой простой задачей. Она может возникнуть в жизни каждого программиста, он замечает некоторые независимые операции и у него появляется нестерпимое желание их распределить по нескольким потокам. Грубо говоря, у вас есть какой-то метод, который можно было бы безболезненно запихнуть в Runnable-ы, стартануть и подождать когда все закончат свою работу.

Понятно, что для этого может подойти invokeAll т.к. в описании про него явно сказано: "Executes the given tasks, returning a list of Futures holding their status and results when all complete."

Так вот, некоторые программисты не дочитывают последние слова и думают, что нужно самому контролировать процесс, ждать и "жать на тормоз", проверять все ли потоки завершились, периодически дергать в цикле future.get(), join-ить или делать другие различные телодвижения. Конечно так поступают не все, но тем не менее такое бывает. Для того, чтобы разобраться в том, что происходит на самом деле, достаточно взглянуть в базовую реализацию этого метода (AbstractExecutorService.java). Надо же пользоваться тем, что src.zip в JDK все еще продолжают подкладывать:

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

DCE VM + HotSwap

Горячая замена.

Исходной предпосылкой было как-то упростить процесс разработки/отладки. В некоторых ситуациях, например когда запуск-перезапуск приложения или теста занимает продолжительное время, очень удобно пользоваться возможностью подправить логику работы уже запущенной программы.
В поисках решения наткнулся на довольно занятное решение - Dynamic Code Evolution VM. Данная виртуальная машина является результатом работ проведенных в рамках исследовательского проекта Институтом системного программного обеспечения им. Иоганна Кеплера в г. Линце (Австрия).

Если грубо описать полученный результат - это специальная "пропатченная" Java VM, которая позволяет на лету править классы в работающей машине. Главная плюшка - если обычно при дебаге вы можете "на горячую" менять содержимое метода, то в DCE VM можно еще и добавлять/удалять методы и поля в классе.

К сожалению с установкой DCE VM у меня не заладилось с самого начала. Инсталлятор не сработал, в итоге пришлось просидеть полночи в попытках заполучить эту чудную VM. К решению этой задачи пробовал подступиться с разных сторон. Пытался собрать исходники. Собирать пришлось из под cygwin-а (в очередной раз пожалел, что сейчас у меня рабочая операционка не Linux). Потом возникли сложности с установкой "Microsoft SDKs Windows v7.1", который почему-то не хотел устанавливаться. В итоге, правдам и неправдами, перед самым рассветом, перерыв кучу ссылок в интернете различными кривыми путями мне удалось стать счастливым обладателям этой машинки. Конечно сейчас, оглядываясь назад, у меня создается впечатление, что на самом деле я сделал кучу лишних шагов и про установку DCE VM информации более чем достаточно, главное внимательно читать инструкцию.

Мои эксперименты.

После того как всё настроил Hot Swap заработал сразу на:

  • Простых Java SE проектах.
  • Java Web проектах под Apache Tomcat.

Схема работы простая. Запускаем под дебагом → Делаем изменения → Жмем Apply Changes.

apply_code_changes

Если речь идёт о более экзотических случаях, например разработка Rich приложений на Netbeans Platform - то горячая замена у меня не заработала. Чуть позже у меня появилась гипотеза, что возможно это связано с тем, что у Netbeans Platform свой ClassLoader. Возможно гипотеза неверна и дело в настройках, думаю в свободное время посмотреть более внимательно исходники проекта и утилит, которые идут вместе с ним.

Рубрики
Java

Про новые публикации на блоге и планы на ближайшее будущее

Ближе к концу марта запускаю крупный проект на Java SE/EE. Сейчас по нему ведутся предварительные работы (проработка архитектуры, подготовка проектной документации, переговоры с клиентом и т.д.).
В связи с этим буду не сильно задействован непосредственно в разработке и думаю появится чуть больше свободного времени. Поэтому хотел в блоге сделать пару объявлений.

1. Планирую разобрать скопившиеся на блоге черновики. Их скопилось довольно много и все они в разной степени готовности и хочется как-то выставить приоритеты.
Вопрос, который меня терзает: "по какой тематике интересней было бы прочитать статьи?".
Варианты:

  • Про Android
  • Обычная Java (Scala)
  • О программирование в целом (UML, архитектуры, шаблоны и т.д.)

Если есть какие-то пожелания и предпочтения – буду рад узнать о них в комментариях.

2. В связи с менее загруженным графиком работы у меня (и в большей степени у моей коллеги) появилась возможность сделать небольшую заказную мобильную разработку под Android (и не только).
Если будут конкретные предложения - буду рад пообщаться.

Исходные данные.

Рубрики
Java

Java и парсинг XML

Тема сегодняшней статьи будет касаться XML поскольку сегодня (10 февраля) XML-ю исполнилось 16 лет!
XML и Java дружат очень давно и в интернете можно найти множество учебных материалов посвященных парсингу XML-файлов, но не смотря на это, время от времени встречаю в коде разных программистов некоторые не совсем удачные решения при разборе XML.
Эта статья возможно не будет интересна тем, кто занимается подобными задачами из года в год и парсит XML-ки с закрытами глазами, но возможно для тех кто только начал вникать в задачу, эти пару прописных истин будут полезны.

Итак.

1. Поиск нужных элементов.

Метод Element.getElementsByTagName возвращает список всех подэлементов с указаным именем.

Всех значит прямо всех, не только непосредственных "детей" этого элементов, но и "внуков" (детей их детей) и "правнуков" и т.д.
Другими словами, если у нас есть следующий XML:

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

Java и десктоп приложения. Впечатления от Netbeans Platform.

Последнее время проектирую и разрабатываю десктоп приложение на Java. После нескольких лет разработки веб/мобильных решений было очень интересно вернуться к десктопу. Сейчас, в эпоху расцвета различных веб-фреймворков (только среди Java: Spring MVC, GWT, JSF, Tapestry, Wicket, Vaadin и т.д.), для разработки десктопных приложений на Java не такой уж большой выбор.
На мой взгляд, на данный момент есть всего три более-менее популярных подхода:

0. Чистый Swing/JavaFX
1. Использовать Eclipse RCP (Rich Client Platform)
2. Netbeans Platform

Поскольку с самого начало было понятно, что предстоит разработать сложную систему с несколько десятков различных формочек, множеством сложных таблиц с группировкой/сортировкой данных, а в перспективе графики, схемы и другие компоненты, то естественно у меня не было желание использовать чистый Swing/JavaFX, а воспользоваться какой-нибудь из платформ.

Первым делом были мысли использовать все-таки Eclipse (в прошлом у меня был опыт работы с ним). Конечно впечатления были не самые лучшие, но прошло больше 8 лет с тех пор как я имел с ним дело и многое могло измениться. Просмотрел изменения и одновременно начал опрашивать друзей, писал ли кто-нибудь в последнее время для Eclipse RCP. В итоге про Eclipse я услышал мало хорошего. Если резюмировать, главный вывод, который можно было сделать после бесед с друзьями — Eclipse RCP использовать можно, но скажем деликатно, без особого удовольствия. В конечном счете я решил переключиться на Netbeans, к которому присматривался уже давно.
Забегая вперед скажу, что в целом мне платформа пока нравится.

Рубрики
Java

Duke, Coworking, Widget.

За последнее время прошло несколько важных событий, о которых давно хотел написать.
Про одну новость я уже просто не имею права писать с ещё большей задержкой и опозданием...
Итак, во-первых, самое главное событие о котором я узнал в сентябре — команда российских программистов получила Duke Award 2013 в Сан-Франциско!
DukeAward2013
Ребята занимаются разработкой симулятора для Java Card Runtime Environment (jCardSim), пишут обфускатор и ПО для защиты Андроид приложений от реверса, а также ведут различные, по-настоящему сложные, Java-разработки. Другими словами занимаются не какими-то поделками вроде корпоративного веб-софта, клепание порталов и другими типовыми B2B/E-Commerce/Banking/Enterprise проектами, а работают над фундаментальными разработками и действительно непростыми вещами, в отличие от многих-многих Java программистов Москвы.

Друзья, еще раз мои поздравления!

Во-вторых, мы пытаемся возобновить наши встречи программистов или как сейчас модно говорить MeetUp-ы. Конечно сейчас уже будет не Scala, основы языка мы разобрали давным давно, у некоторых из нас использование Scala стало вполне будничным и хочется чего-то нового. Следующие встречи предполагаем посвятить процессингу, Arduino, малинке (raspberry pi). Всей нашей небольшой группе захотелось двинуться в сторону железок и интерактив арт. Думаю как всегда половина времени уйдет на общение с железками/компьютерами, а половина на распитие кофе и общение на общие темы.
Место встречи — на территории дизайн-завода Флакон или в кофейнях (как старые добрые времена).

В связи с этим еще одна небольшая новость. Сейчас обитаю в коворкинге StartHub-а, я о нем еще не рассказывал, он находится также во Флаконе, но немного в глубине территории, напротив летнего бассейна. Он расположен не так далеко от предыдущего коворкинга, в котором я арендовал себе рабочее место в прошлом году.
Для любопытствующих выкладываю фото комнаты где я сижу и ссылку на сам коворкинг.

Наконец последняя новость. Мы недавно с друзьями решили вместе сделать Halloween Widget для Android. Как всегда всё в последний момент, но мне кажется получилось намного круче чем я ожидал.
По сути это тот же робот, только сильно доработанный. Из функциональных вещей добавился фонарик (Бека - спасибо, за пример кода!). Включается нажатием на центральную кнопку. Поскольку фонарик по-сути использует вспышку от встроенной фотокамеры, то для работы потребуется разрешение для работы с камерой: android.permission.CAMERA.

Огромный респект нашему дизайнеру Грише за проделанную работу и Тане, за львиную доли работы по переделке-улучшению UI/UX!
Выкладываю пару картинок, сам виджет можно скачать с маркета и при желании по тестировать.


unnamed unnamed2

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

Apples and oranges. Сравнение веб-фреймворков.

Этим летом ко мне обратился старый знакомый, который хотел начать разработку нового веб-проекта. Он хотел пообщаться/посоветоваться на тему современных инструментов (фреймворков) для разработки веб-приложений. Дело в том, что у него скорее планировалась не разработка нового, а переделка старого проекта, сделанного на JSP и сервлетах, базовая архитектура которого ваялась еще в начале 2000-ных. В прошлом я немного участвовал в жизни этого программного продукта (доработки по Hibernate, прикручивал apache fop и т.д.), поэтому был немного в курсе внутренних особенностей системы.

В целом это было добротное веб-приложение на Spring-e и оракловой СУБД. Думаю многие из нас в былые времена делали подобные вещи. С тех пор многое поменялось, одни инструменты сильно развились, появились абсолютно новые, а некоторые безнадежно устарели и канули в Лету. В итоге мы решили встретиться, пообщаться, попить кофе и обсудить, кто с чем столкнулся на профессиональном поприще за последние несколько лет, а также поделиться впечатлениями об использовании тех или иных инструментов.
На мой взгляд к 2013 году человечество создало такое огромное количество библиотек, утилит, платформ и других полезных и бесполезных вещей для создания веб-приложения, что разобраться в них становится все сложнее и сложнее. Суть проблемы заключается в том, что обилие различных модных слов создают кашу в голове программистов.

Чтобы хоть в чем-то упростить себе (и другим программистам) жизнь, я решил после нашей беседы написать этот небольшой обзор различных веб инструментов (в контексте Java и JavaScript). Возможно многие вещи покажутся слишком простыми и очевидными, рассчитанные на совсем юных программистов, тем не менее думаю ошибочно считать, что "каша" возникает только у новичка. Наоборот, умудренные опытом программисты, опираясь на сформировавшиеся у себя в мозгу концепции, проецируют свои старые понятия на новые фреймворки, в итоге сложнее впитывают суть, смысл и назначение новых.

Ведь на самом деле, многие инструменты качественно отличаются друг от друга и сравнивать их порой не представляется возможным. Apple_and_Orange_-_they_do_not_compareВ английском языке существует выражение "сравнивать яблоки и апельсины", в русском языке ближайшим аналогом этого высказывания "путать теплое с мягким". Сравнивать разные по сути вещи. Например, все равно что сравнивать JSF и jQuery.

Поэтому, чтобы внести ясность, я решил раскидать "яблоки к яблокам, а апельсины к апельсинам". В итоге получился следующий текст.