Метка: Java

  • Шаблонизатор mustache и Java.

    mustache

    В этом году решил изменить вековые традиции и в Java проектах начать использовать вместо велосити (анг. Apache Velocity) популярный хипстерский мусташ (анг. Mustache). Дело в том, что в обычной жизни я, как правило, обхожусь вообще без шаблонизаторов и в простых случаях использую регулярки (regexp-ы). Когда нужно использовать сложные шаблоны для генерации текстовых файлов, то подключаю велосити (просто потому, что “рука набита”).

    В этот раз нужно было что-то среднее. С одной стороны, не такое тяжеловесное, как велосити, а с другой стороны… не хотелось все делать руками. В итоге выбор пал на Mustache. В историческом обзоре на википедии написано, что изначально Mustache был сделан для рубистов. Тем не менее, позже он стал крайне популярен на фронтендэ у JavaScript-eров (и не только), и сейчас пользу от его использования сложно переоценить. Более того, если зайти на сайт Mustache, то можно узнать, что он реализован на 30+ языках программирования. Естественно Java также присутствует среди них. Если быть точным, то на сайте у них Java на десятом месте (между Objective-C и C#). Стоит отдать должное создателям java версии библиотеки. Хотя она занимает не первое место в списке, но находится, как и документация к ней, в весьма удовлетворительном состоянии. Установить библиотеку и начать с ней работу особого труда не составляет: jar-ик подключается через мавеновский репозиторий.

    В качестве отличительных особенностей самого шаблонизатора можно указать следующие:

    Во-первых, символами, обрамляющими метки-заполнители (placeholder-ы), являются фигурные скобки “{“. Визуально они чем-то напоминают усы (анг. mustache), повернутые на 90 градусов.
    Выглядит это так:

    Hello {{name}}
    You have just won {{value}} dollars!
    {{#in_ca}}
    Well, {{taxed_value}} dollars, after taxes.
    {{/in_ca}}
    

    Во-вторых, основная идея mustache состоит в logic-less подходе. Под этим авторы подразумевают отсутствие различных if-else конструкций, а также циклов. Другими словами, вот такие велоситивские штуки не пройдут:

    ## Пример для Veloctity
    #if( $foo < 10 )
        Go North
    #elseif( $foo == 10 )
        Go East
    #elseif( $bar == 6 )
        Go South
    #else
        Go West
    #end
    

    Процессинг шаблонов в таком случае становится очень простым.

    1. Берем шаблон.
    2. Передаем данные. В случае Java это обычный Map.
    3. Смотрим на ключ. Проверяем значение.
    3.1. Значение является строчкой? Показываем.
    3.2. Значение является пустым списком, false или отсутствует? Не показываем.
    3.3. Значение является список (точнее Iterable)? Проходим по каждому элементу списка и применяем для него правило.
    3.4. Значение является Callable? Получаем функциональщину.

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

    В ней детально изложены различные практические аспекты.
    Например:
    – Что делать, если вы хотите эскейптить HTML символы? Или не эскейпить?
    – Что делать, если вы хотите выводить что-то в случае отсутствия данных (Inverted section)?
    – Что делать, если вы хотите делать какую-то “предварительную” обработку данных, перед показом?
    и т.д.

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

  • Про FOP, SVG, PDF и значение дизайна.

    Коворкинг интересен тем, что в нем можно встретить интересных людей.
    Следующая история произошла после краткой беседы с Димой Гарником, арт-директором небольшой дизайн-студии.
    У Димы была идея создать простой сайт для автовизиток. Идея несложная, но интересная. Вы заходите на сайт, указываете номер телефона и сообщение (например: “Мешает машина? Звони!“). Затем вы получаете развертку, из которой можно собрать симпатичную машинку. Развертка – это PDF-файл, который можно распечатать на листе бумаги формата А4 и собрать. Самое главное: сборка идет как “оригами”, т.е. без ножниц и клея, нужны только “прямые” руки и время.
    В итоге получается такая штука:

    car_2
    Собственно, нужно было как-то реализовать генерацию этих разверток.

    Так совпало, что Дима подошел и рассказал про свою идею именно в тот момент, когда мы с соседом пили кофе и вели досужие разговоры на тему: “что бы такого сделать интересного и не сложного”. Димина идея показалась интересной и не очень трудоемкой.
    Генерацией PDF-файлов мне уже приходилось заниматься в прошлом (хотя это и была, в основном, генерация документов и отчетов с использованием различных выборок из БД – принципиальной разницы я не видел).

    В общем, я сделал эту штуку.

    Про FOP, SVG, PDF

    Приблизительный план, что и как нужно делать, в целом, был понятен сразу:

    1. Берем рисунок в векторе.
    2. Сохраняем его в SVG-формате.
    3. Поскольку SVG – это обычный XML, то менять в нем содержимое (номер, сообщение, цвет и т.д.) несложно.
    4. Прикручиваем преобразователь SVG → PDF.
    5. Проверяем, что все это работает, и делаем к этому “обвес”, который обрабатывает HTTP запросы и отдает пользователю PDF-файл.
    6. Прикручиваем дизайн или интегрируем с текущим сайтом.

    В целом, все прошло согласно плану. За исключением следующих моментов:

    1. Проблемы со шрифтами.
    Конечно, все зависит от SVG-файла, но, возможно, возникнут сложности с кириллическими шрифтами после развертывания на сервере (т.е. на Linux-е).
    Решение: поставить недостающие (зависит от того, какие нужны) шрифты.
    Например, как-то так:

    apt-get install ttf-mscorefonts-installer

    2. Еще раз проблемы со шрифтами.
    У того, кто раньше работал с Apache FOP, могут возникнуть сложности в более тонкой настройке конфигурации.
    Дело в том, что формат файла для настройки PDFTranscoder-а отличается от привычного fop.xconf!

    Если кратко:

    //Создает перекодировщик. Кроме PDF, если верить документации есть перевод в PostScript, EPS.
            Transcoder transcoder = new PDFTranscoder();
    
            // Если нужно "вшивать" свои шрифты, требуется дополнительная настройка
            try {
                DefaultConfigurationBuilder cfgBuilder = new DefaultConfigurationBuilder();
                Configuration cfg = cfgBuilder.buildFromFile(new File("pdf-renderer-cfg.xml"));
                ContainerUtil.configure(transcoder, cfg);
            } catch (Exception e) {
                throw new TranscoderException(e);
            }
    

    Где “pdf-renderer-cfg.xml”:

    
    
      
        
          
        
      
    
    

    Весь пример можно скачать с сайта Apache FOP.

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

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

    Про дизайн.

    Есть такая замечательная статья Learning to see (Учимся видеть)
    В ней приводится следующая диаграмма:
    chart

    Как правило, чем более “программистская” контора, тем сильнее доминирует принцип – делаем “not pretty but functional“, а затем дизайн (если остались деньги).
    Все бы хорошо, но бывают заказчики, которым потом жалко тратить деньги на нормальный дизайн: им главное, чтобы работало. Как правило, это касается разработки внутренних систем. В целом, это нормальная бизнес-ситуация: лишних денег на “красивости” часто нет. Правда в том, что в итоге сотрудникам некоторых компаний приходится годами пользоваться унылым корпоративным ПО.

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

    pod_steklom_bold
    Без дизайна

    Для сравнения, вот так он выглядит сейчас:

    pod_steklom_beauty
    С дизайном

    С другой стороны, если поставить дизайн во главу угла, может получиться ситуация, когда дизайн есть, а функциональности нет.

    Красиво выглядит? Да, бесспорно! Работает? К сожалению, нет. При этом могут пройти месяцы, пока из красивого получится работающее. Ситуация может усугубиться, если дизайнер “понапридумывает” разного, а это потом не будет работать или окажется невозможным реализовать.

    Многие скажут: “К чему эти банальности? Это и так понятно!”. Понятно, но хотел бы повторить: нормальный дизайн – это не опция, это неотъемлемая часть хорошего программного продукта. Такая же составляющая, как и его функциональность.

    PS: Может кто-то знает нормальные курсы дизайна по UI/UX? Не про “сферического коня в вакууме”, а про конкретные практики – как пользоваться инструментами. И не про общие принципы: что нужно выравнивать, что какие-то цвета плохо сочетаются и т.д., – про это многое уже известно.
    Проблема в том, что иногда по мелочи нужно что-то сделать (например, у меня бывают вопросы, как в фотошопе кнопку перекрасить из серого в красный) и это вызывает определенные сложности. Спасибо соседям по коворкингу, что выручают (Николай, Надежда – это я про вас ;).
    В общем, если кто-то из программистов, читающих мой блог, бывал на таких курсах – был бы рад услышать про них отзыв: стоит или нет.

    PPS: Если, вдруг, какой-то дизайнер забредет на мой программистский блог – буду рад возможности сотрудничества. Пишите в комментариях ;).

  • Обновление времени в 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: Перед запуском, еще раз прочтите внимательно инструкцию на официальном сайте, не забудьте проверить права доступа и наличие резервной копии (это общие правила, они касаются вообще любых сервисных работ проводимых на сервере).

  • 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;
        }
    }
    
    
  • Заметки по 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 через 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 все еще продолжают подкладывать: (далее…)

  • 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 и парсинг XML

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

    Итак.

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

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

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

  • 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, к которому присматривался уже давно.
    Забегая вперед скажу, что в целом мне платформа пока нравится. (далее…)

  • 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