Архив

Powered by mod LCA

Разработка

ResourceBundle and UTF-8

При разработке приложения на JavaFX столкнулся с проблемой чтения ресурсов для локализации. Ну не хочет стандартный ResourceBundle читать property-файлы в UTF-8. Напрочь не хочет. Забравшись внутрь ResourceBundle, обнаружил, что за создание PropertyResourceBundle, который и занимается чтением ресурсов отвечает ResourceBundle.Control, который можно передать в конструктор ResourceBundle. Ну а дальше осталось только правильно реализовать наследника. После чего получилось вот такое решение:
public class EncodingResourceBundleControl extends ResourceBundle.Control {
    private final static Logger log =
            Logger.getLogger(EncodingResourceBundleControl.class.getName());


    private final String encoding;

    public EncodingResourceBundleControl(String encoding) {
        this.encoding = encoding;
    }

    @Override
    public ResourceBundle newBundle(String baseName, Locale locale,
                                    String format, ClassLoader loader,
                                    boolean reload)
            throws IllegalAccessException, InstantiationException, IOException {
        String bundleName = toBundleName(baseName, locale);
        String resourceName = toResourceName(bundleName, "properties");
        URL resourceURL = loader.getResource(resourceName);
        if (resourceURL != null) {
            try {
                return new PropertyResourceBundle(new InputStreamReader(resourceURL.openStream(), encoding));
            } catch (Exception z) {
                log.log(Level.FINE, "exception thrown during bundle initialization", z);
            }
        }

        return super.newBundle(baseName, locale, format, loader, reload);
    }
}
А сам ResourceBundle создаётся следующим образом
ResourceBundle.getBundle("clubManagementMessages", new Locale("ru", "RU"), new EncodingResourceBundleControl("UTF-8"))

Автообновление структуры БД при старте приложения.

В любом проекте, который развивается, время от времени требуется производить обновление структуры БД. На предыдущем месте работы я придумал относительно автоматизированный процесс обновления структуры БД.
Для этого использовались:
  • Hibernate
  • Maven
  • CI-сервер, в качестве которого использовался Jetbrains Teamcity
  • Сервер документации, в качестве которого использовался 

На первом этапе, когда программист добавляет новое поле в объект, при первой сборке Hibernate-tools в консоль пишет код, для изменения текущей структуры БД. Дальше разработчик формирует UPDATE-скрипт, который должен быть применён перед следующим обновлением тестового или промышленного сервера. Для этого во время следующей сборки сервер интеграции проверяет список UPDATE-скриптов, которые были созданы с предыдущей сборки и вносит эту информацию в Confluence. Для простоты последнего этапа пришлось использовать Gradle.
Ниже приведу код того, как информация об Update-скриптах попадала на сервер конфигурации

Подробнее: Автообновление структуры БД при старте приложения.

Update with Join in Oracle

Задача. Есть две таблицы в Oracle, которые связаны друг с другом по одному из полей. Необходимо подчинённую таблицу значениями из родительской таблицы. Для этого мы используем подзапрос с использованием конструкции inner join.
Родительская таблица PARENT_TABLE
ID COL_1 COL_2
 1 11  123 
12  13 
14  DFDS 

Подчинённая таблица SUB_TABLE
ID PARENT_ID COL_1 COL_2
56
1
57
2
58
3

Итоговый скрипт для обновления выглядит следующим образом:
 update (select PT.COL_1 SOURCE_COL_1, ST.COL_1 TARGET_COL_1, PT.COL_2 SOURCE_COL_2, ST.COL_2 TARGET_COL_2 from SUB_TABLE ST INNER JOIN PARENT_TABLE PT ON ST.PARENT_ID = PT.ID) set TARGET_COL_1=SOURCE_COL_1, TARGET_COL_2=SOURCE_COL_2 

Переход с Hibernate 3 на Hibernate 4

Как только начинается новый проект, всегда свербит в одном месте попробовать новые библиотеки. Так произошло на этот раз. Решил попробовать поставить проект на Hibernate 4.0. Но в таком случае есть проблема - наработки , которые есть в загажнике, все по старым версиям. При разработке пользуюсь JUnit, чтобы проверить работоспособность, как минимум, уровня бизнес-логики. Всё это обёрнуто Spring-ом и Maven

Подробнее: Переход с Hibernate 3 на Hibernate 4

Построение системы интеграционных тестов и проверки корректности исходников

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

Подробнее: Построение системы интеграционных тестов и проверки корректности исходников

ERROR: permission denied: "RI_ConstraintTrigger_68264" is a system trigger

Разрабатывая систему автоматического тестирования в компании, натолкнулся на необычную ошибку. Тестирование проводиться на БД Postgres. Перед каждым набором тестов (классом) выполняется скрипт очищающий все таблицы в БД, после чего происходит наполнение нужных таблиц новыми данными. Для упрощения был использован механизм отключения тригеров и очистки таблиц, после чего тригеры опять включаются.

alter table TABLENAME DISABLE TRIGGER ALL;
delete from TABLENAME;
alter table TABLENAME ENABLE TRIGGER ALL;

При выполнении этого скрипта 

org.postgresql.util.PSQLException: ERROR: permission denied: "RI_ConstraintTrigger_68264" is a system trigger
Данная ошибка лечиться тем, что пользователю надо дать права суперпользователя. После этого ошибка исчезает.

Одинарная кавычка в HQL

Есть у меня старая библиотечка, которую я постоянно с собой таскаю, которая позволяет достаточно быстро организовать получение списков с фильтрацией и сортировкой, используя Hibernate. Т.к. она достаточна старая, то написана она на HQL. Всё бы ничего, да вот только возникала в ней ошибка, когда в значения фильтров попадала одинарная кавычка. Есть несколько вариантов решения: 1. Использовать параметризованный запрос, но в таком случае возникает проблема, что текстовой фильтр для поиска по подстроке перестаёт работать. И результат может реально долго получаться 2. Научиться эскепить кавычку. Решение оказалось очень неожиданным
String svalue = getFilterValue().replace("'", "''");
StringBuilder().append(alias).append(".").append(fieldName).append(" LIKE '" + svalue + "' ");
Другими словами один одинарный апостроф надо заменить на два одинарных апострофа, и это решит проблему.

Cross-domain ajax на Java сервере

Разрабатывали систему Виджетов для нашего сервиса, которые должны устанавливаться на "чужие" сервера, обращаться к нашему сервису, а потом строить графики, отчёты. После выпуска релиза оказалось, что мы при тестировании пропустили кросс-доменное (Cross-domain) тестирование. И у нас выскочила ошибка вида

 XMLHttpRequest Origin null is not allowed Access-Control-Allow-Origin for file: ...

Подробнее: Cross-domain ajax на Java сервере

Подключение библиотек при компилировании flex приложения через maven

Долго возился с решением этого вопроса. Даже поиск не помогал. Итак имеем задачу, при компиляции flex приложения с использованием maven (flexmojos-maven-plugin) необходимо использовать аналог параметра компиляции -compiler.include-libraries. В конфигурации самого плагина такого параметра не предусмотрено. Выход оказался очень прост: для этого в элемент зависимости надо вставить тег scope. Вот как это должно выглядеть:

Подробнее: Подключение библиотек при компилировании flex приложения через maven

Первый тест

В данном примере мы создадим простой проект в котором мы используем инструмент сборки проектов Maven 2, фреймоврк Spring, ORM Hibernante, и библиотеку для тестирования JUnit.

Подробнее: Первый тест

Как вычислить следующую дату по Cron-выражению

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

 (new CronTrigger("1", "2", "0 0 0/5 * * ?")).computeFirstFireTime(new BaseCalendar())

Данное решение корректно вычисляет следующую дату, когда должно сработать cron-выражение.

Maven Spring Hibernate JUnit DBunit

Некоторое время назад я задался вопросом, как организовать корректное тестирование серверной части своего приложения. Входные данные для решения этой задачи были следующими. Приложение работает на основе БД postgres 8.4, создания скелета приложения используется Spring 3, приложение собирается при помощи maven 2.1. Для тестирования была выбрана связка JUnit и DBUnit.

Подробнее: Maven Spring Hibernate JUnit DBunit

Водяные знаки

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

watersign_1

Решение оказалось не самым тривиальным:

Подробнее: Водяные знаки

Ошибка при установке AIR - Error #2032

При использовании Air инсталятора от Adobe у меня возникла неприличная ситуация. При начале процесса скачивания приложения, появляется следующее окно с ошибкой

Подробнее: Ошибка при установке AIR - Error #2032

Контекстное меню в AdvancedDataGrid

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

Подробнее: Контекстное меню в AdvancedDataGrid

Повышение производительности AS3 приложений

Данную статью я взял (без разрешения) из блога http://gorbatov.blogspot.com/2008/03/as3.htmlhttp://gorbatov.blogspot.com/2008/03/as3.html. Просто, чтобы не потерять для себя. От себя ни чего не добавлено и не исправлено.

Подробнее: Повышение производительности AS3 приложений

AdvancedDataGrid cортировка

Необходимо стало мне сделать автоматическую сортировку AdvancedDataGrid по одному из столбцов. Долго я ходил окольными путями пока не нашёл самый простой выход.

dataGrid.dataProvider.sort = new Sort();
var field:SortField = new SortField("priority");
dataGrid.dataProvider.sort.fields = [ field ];
dataGrid.dataProvider.refresh();

Создание Flex-приложений c использованием Parsley. Часть 3, MVC

Рассмотрев некоторые аспекты работы с применением Parsley можно сформулировать некоторые аспекты как данная библиотека поможет нам построить гибкое, масштабируемое и, самое главное, хорошо разделённое на модули приложение.

Подробнее: Создание Flex-приложений c использованием Parsley. Часть 3, MVC

Создание Flex-приложений c использованием Parsley. Часть 2, обмен данными

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

Подробнее: Создание Flex-приложений c использованием Parsley. Часть 2, обмен данными

Создание Flex-приложений c использованием Parsley. Часть 1, связывание

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

Подробнее: Создание Flex-приложений c использованием Parsley. Часть 1, связывание