Показаны сообщения с ярлыком Java. Показать все сообщения
Показаны сообщения с ярлыком Java. Показать все сообщения

среда, 13 марта 2013 г.

Как использовать Java

Класная статья, читать всем http://www.pvsm.ru/java/28001

среда, 10 октября 2012 г.

Java Collection Framework - part 2

Ниже приведен короткий список реализаций мап из пакета java.util. Выбрав наиболее подходящую реализацию не забывайте обратится к Java API заболее детальной информацией.

Интерфейсы:

  • Map - структура данных типа ключь-значение, где ключи не могут содержать дубликатов. Мапы не отслеживают изменение полей объектов которые в них содержатся! Этот интерфес содержит методы:
    • добавления/удаления новых значений в мапу
    • проверки присутствия елемента или ключа в мапе
    • возвращения сета ключей или пар ключь-значение, а также колекции значений. При этом последние возвращаются по ссылке, т.е. любое изменение в мепе отразится в сетах/колекциях которые были получены и наоборот.
    При помощи утилитного класса java.util.Collections вы можете произвести такие действия над вашей мапой:
    • synchronizedMap, synchronizedSortedMap - синхронизирует все методы (реализуя паттерн Decorator)
    • unmodifiableMap, unmodifiableSortedMap - возвращает колекцию при попытке модификации которой будет брошено исключение UnsupportedOperationException(реализация - паттерн Decorator)
    • checkedMap, checkedSortedMap - возвращает колекцию гарантированно содержащую заданый тип. При попытке вставить елемент другого типа будет брошено исключение ClassCastException(реализация - паттерн Decorator)
  • SortedMap - Map которая гарантирует сохранение ключей в отсортированом виде. Содержит методы:
    • для получения мин/max значения - firstKey/lastKey
    • для получения мап с ключами меньше/больше заданого ключа - headMap/tailMap
    • для получения мап с значениями в диапазоне между двумя ключами - subMap
  • NavigableMap - SortedMap оптимизированая для поиска по условиям сравнения. Cвойства:
    • содержит оптимизированые методы для получения ключей и их значений по условиям: <, <=,>, >=
    • методы NavigableMap параметризированы для включения/не включения граничных условий
    • Эти методы возвращаеют наборы ключей, значений, или мапу отсортированую в обратном порядке
  • ConcurrentMap - мапа предоставляющая atomic операции putIfAbsent, remove, replaсe. Возвращают true - если операция изменила данные, иначе false
  • ConcurentNavigableMap -расширяет NavigableMap возвращая результатом операций тип ConcurentNavigableMap вместо NavigableMap

Классы:

  • HashMap - мапа ключи которой размещаются в бакетах, согласно значению их hashcode. Cвойства:
    • методы не синхронизированы
    • может содержать нули
    • сложность операций извлечения/вставки (get/put/containsKey) - O(1)
    • сложность операции containsValue - O(capacity +size)
    • При итерировании порядок не гарантирован.
    • Сложность итерирования: O(capacity +size), где capacity - количество бакетов, size -размер мапыv
    • перестраивает хеши автоматически если: size > loadFactor* capacity. По умолчанию loadFactor = 0.75, capacity=16. При этом capacity увеличивается в двое.
  • LinkedHashMap - HashMap ключи которой связаны в LinkedList, это гарантирует порядок обхода ключей (в порядке добавления(insertion-order) или в порядке получения доступа(access-order).
    • свойства insertion-order - это дефолтный режим, если существующий ключ вставляется второй раз - порядок в LinkedList не изменится.
    • свойства access-order - включается специальным параметром в конструкторе, любая операция put или get изменяет порядок листа
    • cложность операции containsValue и итерирования: O(size)!
    • Остальные свойства аналогичны HashMap.

  • Hashtable - старая потокобезопасная реализация HashMap. Болееновая реализация - ConcurentHashMap. Аналогичен HashMap за исключением:
    • не может содержать нулей
    • все методы синхронизированы
  • Properties - представляет набор пропертейю обладает всеми свойствами Hashtable плюс:
    • все ключи типа String
    • содержит методы чтения/записи в поток
    • для каждого ключа может содержатся 2 значения: обычное и значение по умолчанию, которое задается на конструкторе.

  • TreeMap - реализация Red-Black treе -самобалансирующиеся BST Свойства:
    • сложность вставки, удаления, получения, проверки вхождения - O(log(n))
    • методы не синхронизированы
  • ConcurrentHashMap - более новая реализация Hashtable. Методы имеют туже сигнатуру, поэтому можно просто заменить Hashtable на ConcurentHashMap. Cвойства:
    • все операции потокобезопасны
    • операции извлечения данных не блокируют потоки выполнения, и возвращают согласованные данные (относительно завершившихся операций по изменению данных)
    • операции по изменению данных блокируют только часть таблицы (грубо говоря нельзя одновременно писать в один бакет, но можно в разные)
    • операции по изменнению набора данных типа putAll, clear будут в течении своей работы блокировать определенные сегменты но не всю таблицу
    • Операции для работы с набором данных putAll, clear не атомарны!
    • Один из параметров конструктора concurrencyLevel - число одновременно работающих потоков, таблица будет разбита на соответствующее число бакетов. (По умолчанию - 16)
  • ConcurrentSkipListMap - потокобезопасная реализация SkipList.
    • Сложность операций contains, get, put, remove - O(log(n))
    • Сложность операции size - O(n)!!!
    • Операции для работы с набором данных putAll, equals, и clear не атомарны!

  • EnumMap - мапа ключами которой могут быть только занчения Enum. Свойства:
    • Данные сохранняются в масивах, длина которого совпадает с количеством Enum.
    • ключи отсортированы в порядке возростания.
    • сложность операций извлечения/вставки (get/put/containsKey) - O(1)
    • сложность операции containsValue - O(Enum.size())
  • IdentityHashMap - хеш мапа с хитрым свойством: Ключи равны тогда и только тогда когда равны их ссылки (key1 == key2) Остальные свойства аналогичны обычной HashMap. Используется если вам нужно по какойто причине иметь список обектов, например при сериализации - когда хотите знать какие объекты уже сериализированы, или при отладке - если хотите иметь список объектов для которых включен дебаг и т.д.
  • WeakHashMap - Хеш мапа, в которой значения ключей не содержатся на прямую, а сохраняются как WeakReference. Иначе говоря, сборщик мусора может собирать ключи (если на них отсутствуют ссылки из других мест). Значения привязаные к таким собранным ключам будут удалятся из мапы автоматически. Внимание: значения сохраняются в Мапе как обычные ссылки

понедельник, 2 апреля 2012 г.

Java Collection Framework - part 1

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

Интерфейсы:

  • Collection: - описывает группу объектов (элементов). Определяет методы для получения итератора, добавления, удаления элементов, проверки на вхождение элемента в даную колекцию, преобразования колекции к масиву.
    При помощи утилитного класса java.util.Collections вы можете произвести такие действия над вашей колекцией:
    • synchronizedCollection - синхронизирует все методы (реализуя паттерн Decorator)
    • unmodifiableCollection - возвращает колекцию при попытке модификации которой будет брошено исключение UnsupportedOperationException(реализация - паттерн Decorator)
    • checkedCollection - возвращает колекцию гарантированно содержащую заданый тип. При попытке вставить елемент другого типа будет брошено исключение ClassCastException(реализация - паттерн Decorator)
    также он предоставляет методы для добавления нескольких елементов к колекции, например так: Collections.addAll(flavors, "Peaches 'n Plutonium", "Rocky Racoon"); проверки содержат ли колекции не одинаковые елементы disjoint, подсчет числа вхождения данного елемента в колекцию frequency, Нахождение max и min елемента колекции (сложность O(n)).
  • List: - список - упорядоченная последовательность объектов.
    Елементы упорядоченны - имеют свои индексы. Интерфейс описывает методы для добавления, замещения, удаления елементов по индексу. Также методы для получения индекса елемента и ListIterator - который кроме елементов может возвращать их индексы. Класс java.util.Collections кроме операций аналогичных операциям с колекцией описывает также операции:
    Поиска и сортировки
    • sort - стабильная сортировка модифицированым методом mergesort, сложность O(n log(n)))
    • binarySearch - поиск елемента в отсортированой колекции. Сложность для RandomAcсess листов O(log n), иначе O(n)
    создания, заполнения, вхождения
    • copy - копирует все елементы в доругой список
    • fill - заполняет лист одним и тем же елементом
    • indexOfSubList, lastIndexOfSubList - возвращает первый (последний) индекс вхождения одного списка в другой, или же -1, Использует "brute force" стратегию :)
    изменения порядка
    • shuffle - рандомно перемешывает список, сложность O(n)
    • swap - меняет два елемента списка местами
    • reverse - разворачивает список, сложность O(n)
    • rotate - сдвигает елементы списка, сложность O(n)
  • Queue: - очередь в которой елементы выстроены по принципу FIFO (first-in-first-out).
    Определяет методы добавления в конец очереди и извлечения первого елемента из очереди(offer(e), poll()). Также есть метод peek() - получить первый елемент в очереди без его удаления.
    Класс java.util.Collections определяет операции аналогичные операциям с колекциями.
  • Deque: - двунаправленная очередь, добавлять и извлекать елементы которой можно как с конца, так и сначала. Используется для реализации стратегий как LIFO(Stack), так и FIFO.
    Кроме методов Queue определяет методы для работы со стеком: push(e), pop() - добавление в начало и извлечение первого елемента, peek() - возвратит первый елемент без его удаления. Также есть метод для получения обратного итератора: descendingIterator()
    Вы можете преобразовать Deque в Queue при помощи java.util.Collections (реализация - паттерн Decorator).
  • BlockingQueue: - блокирующая очередь для передачи данных между потоками.
    Читающий поток будет остановлен пока не появится хотя бы одна запись в очереди. Пишущий поток будет остановлен если превышен предел елементов в очереди. если же елементов станет меньше он продолжит свою работу.
    remainingCapacity - возвращает число свободных слотов Существует 4 набора методов для вставки и получения елементов:
    • add(e), element(), remove() - добавить, достать, удалить, при запрете операции в данный момент (отсутствии елементов, или заполнености очереди) бросается исключение IllegalStateException
    • offer(e), poll() - добавить/извлечть елемент, без блокировки потока, при запрете операции будет возвращен результат false или null
    • offer(e, time, unit), poll(time, unit) - добавить/извлечь елемент, c блокировкой не дольше заданого интервала
    • put(e), take() - добавить/извлечть елемент c блокировкой потока до выполнения операции
    • drainTo(Collection) - извлечь все елементы из очереди и поместить в колекцию
  • BlockingDeque: - блокирующая двунаправленная очередь, для передачи данных между потоками.
    Аналогична BlockingQueue но позволяет добавлять и извлекать елементы с обоих концов.
    Методы имеют приставки к именам First - означает начало и Last - хвост очереди.
    Также есть методы removeFirstOccurrence(e)/removeLastOccurrence(e) - удаляющие первое или последнее вхождение данного елемента.

Классы:

  • ArrayList: - представляет масив длинна которого меняется автоматически (динамический масив)
    Сойства:
    • методы не синхронизированы (нельзя использовать в нескольких потоках)
    • сложность операций size, isEmpty, get, set, iterator, listIterator, add - O(1)
    • add - работает медленнее чем в LinkedList
    • Если был получен iterator или listIterator, а затем была изменена структура списка, будет брошен ConcurrentModificationException. Но это поведение не гарантируется при изменении структуры несколькими потоками
  • Vector: - представляет масив длинну которого можно увеличивать
    Сойства:
    • методы синхронизированы (безопасно использовать в нескольких потоках, но меньшая производительность при работе с одним)
    • setSize - устанавливает новый размер масива
    • add(int index,E element) добавляет елемент в определенную позицию, или же бросает ArrayIndexOutOfBoundsException
    • Не рекомендуется завязывать логику программы на ConcurrentModificationException, несмотря на синхронизированость методов. Это исключение призвано только для выявления багов
  • Stack: - представляет старую реализацию стекаLIFO
    Сойства:
    • К методам Vector добавляет push(e), pop()
    • методы синхронизированы
    • Более согласованую абстракцию LIFO представляет интерфейс Deque и его реализация ArrayDeque
  • CopyOnWriteArrayList: - потоко-безопасный вариант ArrayList
    Сойства:
    • Все операции изменяющие структуру применяются к новой копии существующего масива данных. Для быстрого копирования используется нейтивные системные функции. Тоесть если один поток хочет читать масив - он получает снимок текущего масива и дальше читает его (возможно устаревшие данные), а другой в это время, может без боязненно его изменять.
    • Операции связанные с изменением структуры синхронизированны. Тоесть в любой момент временни только один поток может изменять структуру
    • Операции связанные с чтением не блокируют запись
    • Вы не сможете изменять структуру данного листа через итератор (так как итератор работает с более старым снимком данных). Операции итератора remove, set, add будут бросать UnsupportedOperationException
  • LinkedList: - Связаный список (двусвязный список)
    Сойства:
    • Методы не синхронизированы (нельзя использовать в нескольких потоках)
    • Сложность операций get, isEmpty, remove, insert - в конец и начало списка одинакова (O(1))
    • Сложность операций get(index) - O(n)
    • Если был получен iterator или listIterator, а затем была изменена структура списка, будет брошен ConcurrentModificationException. Но это поведение не гарантируется при изменении структуры несколькими потоками
  • PriorityQueue: - бесконечная очередь на базе структуры heap
    Сойства:
    • Методы не синхронизированы (нельзя использовать в нескольких потоках), многопоточная реализация PriorityBlockingQueue
    • Сложность операций получения елемнетовpeek, element, size - O(1)
    • Сложность операций вставки и извлеченияoffer, poll, remove(), add - O(log(n)
    • Сложность операций доступа к конкретному елементу remove(Object), contains(Object) - O(n)
    • iterator() - обходит очередь в произвольном порядке
    • Для обхода кучи в порядке убывания/возростания елементов используйте конструкцию Arrays.sort(pq.toArray()) - сложность O(n*log(n))
  • ConcurrentLinkedQueue: - бесконечная очередь потокобезопасная очередь
    Элементы хранятся в отдельных объектах (нодах), которые связываются посредством ссылок. Изменения структуры отслеживаются через AtomicReferenceFieldUpdater класс. Сойства:
    • Методы не синхронизированы, но структура этой очереди позволяет множеству потоков работать с одной и той же очередью безопасно
    • Сложность операции size - O(n)!
  • ArrayDeque: - реализация двусвязной очереди на базе динамического масива
    Сойства:
    • Методы не синхронизированы (нельзя использовать в нескольких потоках)
    • Сложность операций добавления и извлечения елементов в оба конца очереди - O(1)
    • Сложность операций для работы с конкретным елементом remove(Object), contains, iterator.remove() - O(n)
    • Если был получен iterator или descendingIterator, а затем была изменена структура очереди, будет брошен ConcurrentModificationException. Но это поведение не гарантируется при изменении структуры несколькими потоками
  • ArrayBlockingQueue: - блокирующая очередь на базе масива постоянной длинны
    Описывает класический буффер ограниченой длинны для обмена данными между потоками.
    Сойства:
    • После создания нельзя изменить размер буффера
  • LinkedBlockingQueue: - Блокирующая очередь на базе связаного списка
    Элементы хранятся в отдельных объектах (нодах), которые связываются посредством ссылок. Описывает буффер произвольной длинны для обмена данными между потоками. Сойства:
    • При создании можно задать размер буфера, по умолчанию он неограничен. После создания изменять размер буффера нельзя
    • Очередь не ограничена, но можно нарватся на OutOfMemoryError
    • Сложность добавления, извлечения елементов O(1) (не считая затраты на блокирову)
    • Сложность изменения, получения конкретного елемента O(n) (не считая затраты на блокирову)
  • PriorityBlockingQueue: - блокирующай вариант PriorityQueue
    Сойства:
    • При создании можно задать размер буфера, по умолчанию он неограничен. После создания изменять размер буффера нельзя
    • Очередь не ограничена, но можно нарватся на OutOfMemoryError
  • SynchronousQueue: - блокирующая очередь, для синхронизации двух потоков.
    Аналог ArrayBlockingQueue с размером буфера 1.
  • DelayQueue: - неограниченая очередь, елементы которой стают доступны другому потоку только по истечении заданого времени.
    Сойства:
    • Каждому елементу задается свое время после которого он станет доступен, для чтения в очереди
    • size() - возвращает общее число как доступных так и не доступных елементов
    • Очередь не ограничена, но можно нарватся на OutOfMemoryError
  • LinkedBlockingDeque: - Блокирующая двунаправленная очередь на базе связаного списка
    Элементы хранятся в отдельных объектах (нодах), которые связываются посредством ссылок. Описывает буффер произвольной длинны для обмена данными между потоками. Сойства:
    • При создании можно задать размер буфера, по умолчанию он неограничен. После создания изменять размер буффера нельзя
    • Очередь не ограничена, но можно нарватся на OutOfMemoryError
    • Сложность добавления, извлечения елементов с обоих концов очереди O(1) (не считая затраты на блокирову)
    • Сложность изменения, получения конкретного елемента (remove(Object), contains(Object), iterator.remove()) O(n) (не считая затраты на блокирову)

среда, 13 октября 2010 г.

jMagick installation

First step - install ImageMagick :
For installation download file from for your OS and simple run it.
(for Unbuntu OS run command: apt-get install imagemagick --fix-missing)

Second step - install jMagick :
For installation download files from and follow by instructions
(for Unbuntu OS run command: sudo apt-get install jmagick --fix-missing)

Make sure that jmagick binary files (jmagick*.so or jmagick*.dll for windows os) are accessible for jvm. This files mast be present in /usr/lib for linux os or in java_home/bin folders. If this files are absent simple copy it from jmagick installation package.

четверг, 30 сентября 2010 г.

среда, 23 июня 2010 г.

Java Parameters

For debugging many project use next too helpful java parameters:
-verbose:class - Display information about each class loaded.
-Dproperty=value - Set a system property value.
  for example:   -Djava.endorsed.dirs=C:/jboss-5.1.0.GA/lib/endorsed/ sets endorsed libon JBoss startup

For more information see http://java.sun.com/javase/6/docs/technotes/tools/solaris/java.html

четверг, 24 декабря 2009 г.

Spring and file uploading

There are many guide how to upload file in spring framework. For example you can use ref .
But when you use it remember:
  • Add multipartResolver bean to spring.xml file!
  • Add fileupload.jar and commons-io.jar from http://commons.apache.org/downloads/download_fileupload.cgi
  • You can use Yahoo uploader or something that. If you do it add parameter name to request.
    For example in yahoo widget use:
    uploader.upload(fileID, url, "post", {}, "file");
  • Remember! SWF can not support cookies. That meens you droped current session. For resolve it simple add ;jsessionid=valuees to upload url.
    Example:
    var url="/reports/uploadFile;jsessionid=F34C5040A029C61658E8CC7A73841CCC"
  • Don't forget return response 200 from controller.
    Example:
    1 @RequestMapping(value = "/reports/uploadFile", method = RequestMethod.POST)
    2 public void uploadFile(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws IOException {
    3
    4 reportStorageService.saveFile(file.getName(), file.getContentType(), file.getSize(), file.getBytes());
    5
    6 response.setStatus(HttpServletResponse.SC_OK);
    7
    8 }

пятница, 18 декабря 2009 г.

Debuging Hadoop applications in Eclipse (Linux & Windows)

  1. Install Java 1.6.x, ssh and download Haddop. For windows need also install Cygwin.
  2. Then configure environments for running haddop in standeloune mode. See Hadoop quick start guide for how to do it.
  3. Go to ${hadoop}/bin folder and create hdebug file using existing hadoop file (simple copy and rename).
  4. In the  hdebug file find strings:
    1 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.log.dir=$HADOOP_LOG_DIR"
    2 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.log.file=$HADOOP_LOGFILE"
    3 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.home.dir=$HADOOP_HOME"
    4 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.id.str=$HADOOP_IDENT_STRING"
    5 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.root.logger=${HADOOP_ROOT_LOGGER:-INFO,console}"
    6 if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then
    7 HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$JAVA_LIBRARY_PATH"
    8 fi
    and add new:
    1 HADOOP_OPTS="$HADOOP_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=y"
    you can get something like:
    1 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.log.dir=$HADOOP_LOG_DIR"
    2 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.log.file=$HADOOP_LOGFILE"
    3 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.home.dir=$HADOOP_HOME"
    4 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.id.str=$HADOOP_IDENT_STRING"
    5 HADOOP_OPTS="$HADOOP_OPTS -Dhadoop.root.logger=${HADOOP_ROOT_LOGGER:-INFO,console}"
    6 HADOOP_OPTS="$HADOOP_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=y"
    7 if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then
    8 HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$JAVA_LIBRARY_PATH"
    9 fi
  5. Run your application using hdebug file instead of hadoop. Example start command:
    1 ${hadoop}/bin/hdebug jar your-app.jar
    You can see log:
    [hadoop_log_1.GIF]
  6. Open Eclipse. Go to menu Run->Debug configurations... and create new Remoute Java Application configuration.
    On Connect tab: choice your project, select Standart connection type, set host (local), set Port: 8001.
    On Source tab: Add your project.
  7. Starts debug, and enjoy :)

среда, 4 февраля 2009 г.

Web Приложение на базе Spring MVC

Это статья заготовка для быстрого старта разработки простоги веб приложения основаного на Spring MVS.
для запуска понадобятся следующие библиотеки:
  1. Spring 2.5.5 (commons-collections.jar, commons-lang.jar, commons-logging.jar, spring.jar, spring-webmvc.jar, servlet-api.jar)
  2. spring validation (spring-modules-validation.jar из пакета pring Modules 0.9)
  3. standard jsp taglibs (jstl.jar, standard.jar)
  4. log4j-1.2.13.jar - для логирования.
Скопируйте их в папку {SpringWebTemplate}/webapp/WEB-INF/lib.

для построения метрики и явадоков с помощью анта понадобятся библиотеки jdepend-2.9.jar, statsvn.jar, которые необходимо поместить в папку {SpringWebTemplate}/compile-lib

В заготовке описан пример однога сервиса, которий используется контроллерами. В контроллере "MainController" показан пример передачи бина на страницу, а также примеры 2-х типов перенаправления запросов пользователя. В контроллере "CalculatorController" показан пример обработки формы (передача значений на форму, считывание введенных пользователем данных, их валидация, показ ошибок и результатов).
Пример состоит из двух страниц:
  • /main.htm - имеет стандартную разметку с относительными ссылками на файлы css и js. В качестве примера вывода динамического содержимого - выводится текущее время сервера
  • /calc.htm - страница с формой. Считывает 2 числа и выводит их сумму. Если пользователь введет некоректные данные показываются ошибки валидации. На странице есть 2 примера сообщений валидации: для первого поля сообщение задается в класе формы, для второго - на jsp странице
Скачать пример с библиотеками(7.7мб)
Скачать пример без библиотек
Доп. литература:
Отличная статья с примером о валидации в спринге

понедельник, 29 декабря 2008 г.

Тестирование Spring приложений

Эта статья - заготовка, для быстрой организации тестирования спринг приложений.
Рассмотрим типичную конфигурацию Spring + Hibernate. Для тестирования БЛ будет использоваться JUnit4. Заполнять БД тестовыми данными будем при помощи DBUnit. Для запуска тестов будет использоватся Ant(на билдсервере) и Eclipse (для дебага).
Полезная л-ра:
Класная статья о тестировании Spring-a в JUnit-е http://samolisov.blogspot.com/2008/07/spring-junit.html
Класная статья о JUnit4 http://www.ibm.com/developerworks/ru/edu/j-junit4/index.html
Итак нам понадобятся следующие библиотеки:
  1. драйвер БД (в моем примере mqsql-5.0.4)
  2. hibernate 3.3.1, hibernate-annotations 3.4
  3. spring-2.5.5
  4. для работы спринга: cglib 2.1, commons-lang 2.4, spring-modules 0.9
  5. для тестирования спринга в JUnit 4: spring-test (из spring-modules)
  6. junit 4.4
  7. логирование: commons-loging 1.0.4, commons-login-api 1.0.4, log4j 1.2.13
  8. заполнение тестовой БД-х: dbUnit 2.4.2
В заготовке используется схема из двух таблиц "bookcase" и "book", с типичной связью один ко многим. Бизнес модель состоит из трех модулей: млодуля сервисов, модели и DAO. Модель описывает сущности, DAO - описывает методы сохранения и выборки сущностей из БД используя Hibernate Criteria Queries (обекстную модель построения запросов), сервисы же предоставляют высокоуровневые бизнес методы. Для реализации бизнес методов сервисы используют DAO, но также они могут использовать и бизнес методы других сервисов. Так в заготовке "BookcaseService" использует методы другого сервиса "AnotherService".

Для тестирования сервиса "BookcaseService" используется класс "BookceseServiceTest". В нем есть пример:
  • использования dbunit при тестировании
  • создания сессии для использования в тестах обьектов использующих "hibernate lazy loading"
  • замещения сервиса ""AnotherService" сервисом "AnotherTestOverrideService" для тестов
Ant-ский билд скрипт содержит цели для создания БД, запуска юнит тестов и построения веб репортов их результатов, создания javadocs по проекту, построения веб представления метрики проекта (сколько пакетов, класов и т.д., для етого используется утилита jdepend), а также svn статистики (используется statsvn)

Скачать исходники проекта с библиотеками (14мб)
Скачать исходники без библиотек

среда, 24 декабря 2008 г.

Библиотека urlrewrite

Недавно столкнулся с очень приятной библиотекой http://tuckey.org/urlrewrite/. Она представляет собой обычный фильтр который позволяет задавать свои настройки в хмл файле. Прелесть этой вещицы во первых в простоте (от первого знакомства до использования не более 5 минут), а во вторых в функционале (сейчас я с трудом себе могу представить как мои веб приложения обходились без нее).

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

Инсталяция: на сайте проэкта все детально описано, состоит из 3-х шагов: бросьте в папку WEB-INF/lib саму библиотеку urlrewrite.jar, в папку WEB-INF файл urlrewrite.xml (в котором вы будете описывать правила работы фильтра), и добавьте магические строки в web.xml:
1 <filter>
2 <filter-name>UrlRewriteFilter</filter-name>
3 <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
4 <init-param>
5 <param-name>logLevel</param-name>
6 <param-value>DEBUG</param-value>
7 </init-param>
8 <init-param>
9 <param-name>confReloadCheckInterval</param-name>
10 <param-value>5</param-value>
11 </init-param>
12 </filter>
13 <filter-mapping>
14 <filter-name>UrlRewriteFilter</filter-name>
15 <url-pattern>/*</url-pattern>
16 </filter-mapping>
в строке 6 указывается необязательный параметр - уровень вывода логов, а в строке 10 - интервал перечитывания файла urlrewrite.xml (даная конфигурация позволяет изменять его на лету, очень полезно на этапе разработки).

Конфигурирование файла urlrewrite.xml:
  1. может содержать несколько тегов rule, при этом они будут выполнятся один за другим сверху в низ
  2. для задания адресов используется Java Regular Expression. Кратко о синтаксисе можно прочитать например тут http://htmlweb.ru/java/regexp.php
  3. тег from - задает адреса на которые будет срабатывать фильтр
  4. тег to - указывает адрес куда будет перенаправлен пользователь (если используете redirect может пригодится внутренняя переменная %{context-path} - содержащая контекст вашего приложения).
    Пример:
    Если ваше приложение находится по адресу localhost/myapp то
    1 <to type="redirect">%{context-path}/index.jsp</to>
    пренаправит пользователя по адресу localhost/myapp/index.jsp
  5. condition - позволяет добавить дополнительные параметры, для того чтоб ограничить запросы на которые будет срабатывать фильтр.
    Пример:
    1 <condition type="request-uri" operator="notequal">/manager</condition>
    указывает что фильтр не должен срабатывать на запросы в которых встречается комбинация "/manager"
  6. set - позволяет записать информацыю в сессию, запрос, куки и т.д.
    Пример:
    1 <set name="publisherDomain" type="session">myDomain</set>
    записывает строку "myDomain" в переменную publisherDomain.
Маленький экскурс в регулярные выражения:
  • ^ - начало строки (пример: ^hi - значит что строка должна начинатся фразой "hi"
  • $ - конец строки

  • . - любой символ
  • [abc] - любой символ из заключенных в квадратные скобки
  • [^abc] - любой символ кроме заключенных в квадратные скобки
    можно также указать диапазон или тип символов

  • * - повторение символа 0 или более раз. (пример: ^/.* - строка начинается с / за которым следует любая комбинация символов)
  • + - как и * но обязательное повторение 1 раз или более
  • ? - повторение 0 или 1 раз

  • () -запомнить найденное выражение
  • $1, $2, ... - использовать запомненное выражение
    Пример:
    1 <rule>
    2 <from>^/(.+)$</from>
    3 <to type="redirect">/$1/login.html</to>
    4 </rule>
    Фильтр будет срабатывать на все адреса начинающиеся с "/" за которым следует хотя бы один символ и запоминать символы после "/". Т.е. если пользователь введет адрес /test, то фильтр перенаправит его на страницу /test/login.html
Для закрепления пример файла urlrewrite.xml:

1 <?xml version="1.0" encoding="utf-8"?>
2 <!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN"
3
"http://tuckey.org/res/dtds/urlrewrite3.2.dtd">

4
5 <urlrewrite>
6
7 <rule>
8 <from>^/portal$</from>
9 <to type="redirect">%{context-path}/portal/index.jsp</to>
10 </rule>
11
12 <rule>
13 <condition type="request-uri" operator="notequal">/portal</condition>
14 <condition type="request-uri" operator="notequal">/css</condition>
15 <condition type="request-uri" operator="notequal">/js</condition>
16 <condition type="request-uri" operator="notequal">/img</condition>
17 <condition type="request-uri" operator="notequal">/html</condition>
18 <from>^.*/(.*)/(.*)$</from>
19 <set name="publisherDomain" type="session">$1</set>
20 <to type="redirect">%{context-path}/portal/$2</to>
21 </rule>
22
23 </urlrewrite>
здесь первое правило будет срабатывать на запросы типа /portal и перенаправлять их на страницу /portal/index.jsp
Второе правило будет срабатывать на все остальные урлы кроме обращений связаных с загруской стилей, стат. страниц, картинок и т.д., далее оно будет вырезать выражение находящееся между первым и последним знаком "/"? и помещать его в сесию, а пользователя перенаправлять по адресу /myapp/portal/выражение_стоящее_за_последним_знаком_/

вторник, 23 декабря 2008 г.

Конвертация java кода в html

Не нашел нормальных средств для вставки java, xml, html, текстов в стандартном блоговском редакторе сообщений. Пришлось искать доп. средства. Пока использую http://www.palfrader.org/code2html/code2html.html хотя страшно не нравится. Хотелось бы иметь конвертор который один раз генерит стили и затем цепляет их к тексту, да еще чтоб и работало сходу под виндой. Из чего то похожего нашлось только java-code-export/. Класная програма жаль только она стили для каждого явовского файла каждый раз по разному генерит :)

понедельник, 10 декабря 2007 г.

Использование properties файлов

Хорошей практикой загрузки properties файлов является использование метода getResourceAsStream() класса java.lang.ClassLoader.
Пример:
 ClassLoader cl = this.getClass().getClassLoader();
InputStream is = cl.getResourceAsStream();
Properties props = new Properties();
try {
props.load(is);
}...
при этом следует помнить что корневой каталог будет меняться в зависимости от типа контейнера.
Для сервлетов он будет начинаться с корня war файла. т.е. мы получим что-то типа:
...getResourceAsStream("/WEB-INF/propfile.props");
Для EJB он будет начинаться с корня jar файла. т.е. код будет иметь вид:
...getResourceAsStream("/somepackage/propfile.props");
Если же properties файл используется в jar который упакован в war файл, или же он вызывется из другого jar файла, то необходимо указывать относительный путь
...getResourceAsStream("somepackage/propfile.props");
. При этом следует убедится что properties файл находится в области видимости (для jar файлов ссылки на другие пакеты можно задать в файле MANIFEST.MF:
Manifest-Version: 1.0
Class-Path: lib1.jar lib2.jar lib3.jar
Created-By: Oracle JDeveloper 10.1.3.2.0
).При чтении (записи) данных в properties файлы используется кодировка ISO 8859-1. При использовании других кодировок необходимо произвести преобразование строк. Например так:
label = new String(label.getBytes("ISO-8859-1"), "UTF-8");
Оригинал статьи