<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1477191244885294571</id><updated>2024-09-05T19:40:22.506-07:00</updated><category term="java core"/><category term="Linux"/><category term="Spring"/><category term="Design Patterns"/><category term="Maven"/><category term="multi-threading"/><category term="primefaces"/><category term="reflect"/><category term="scala"/><category term="AMQP"/><category term="Algorithms"/><category term="AspectJ"/><category term="IntelliJ IDEA"/><category term="Jax-RS"/><category term="Jersey"/><category term="ORM"/><category term="RESTful"/><category term="RabbitMQ"/><category term="Relational DB"/><category term="Tomcat"/><category term="etherpad"/><title type='text'>Java developer&#39;s issues</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>20</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-7978024585286147693</id><published>2011-12-15T03:08:00.000-08:00</published><updated>2011-12-15T09:11:44.377-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><title type='text'>Quartz + Spring</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;В больших проекта часто бывает необходимо выполнять какой-то участок кода по расписанию. Для этого подойдет популярная библиотека &lt;a href=&quot;http://quartz-scheduler.org/&quot;&gt;Quarz&lt;/a&gt;.&lt;br /&gt;
Рассмотрим, как можно интегрировать Quartz (1.x) в Spring.&lt;br /&gt;
&lt;br /&gt;
Для начала подхватим зависимость в maven:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;dependency&gt;
    &lt;groupid&gt;org.quartz-scheduler&lt;/groupid&gt;
    &lt;artifactid&gt;quartz&lt;/artifactid&gt;
    &lt;version&gt;1.8.5&lt;/version&gt;   
&lt;/dependency&gt;
&lt;/pre&gt;&lt;br /&gt;
Создадим бин, отвечающий за выполнение задачи:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Component
public class SomeWorkBean implements InitializingBean, DisposableBean {
    @Override
    public void afterPropertiesSet() {
    }

    public void doWork() {
        System.out.println(&quot;doing some work&quot;);
    }

    @Override
    public void destroy() throws Exception {
    }
}
&lt;/pre&gt;&lt;br /&gt;
теперь можно конфигурировать Spring:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;!--for autowiring beans, like bean someWorkBean--&gt;   
&lt;context:annotation-config&gt;&lt;/context:annotation-config&gt;
&lt;context:component-scan base-package=&quot;org.mypackage&quot;&gt;&lt;/context:component-scan base-package=&quot;org.mypackage&quot;&gt;

&lt;!--shedule refresh cache--&gt;

&lt;bean id=&quot;workJob&quot; class=&quot;org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean&quot;&gt;    &lt;property name=&quot;targetObject&quot; ref=&quot;someWorkBean&quot;&gt;&lt;/property&gt;
    &lt;property name=&quot;targetMethod&quot; value=&quot;doWork&quot;&gt;&lt;/property&gt;
&lt;/bean&gt;

&lt;bean id=&quot;simpleTrigger&quot; class=&quot;org.springframework.scheduling.quartz.SimpleTriggerBean&quot;&gt;
    &lt;property name=&quot;jobDetail&quot; ref=&quot;workJob&quot;&gt;&lt;/property&gt;
    &lt;property name=&quot;repeatInterval&quot; value=&quot;60000&quot;&gt;&lt;/property&gt;   &lt;!--60 seconds--&gt;
    &lt;property name=&quot;startDelay&quot; value=&quot;10000&quot;&gt;&lt;/property&gt;  &lt;!--10 seconds--&gt;
&lt;/bean&gt;

&lt;bean class=&quot;org.springframework.scheduling.quartz.SchedulerFactoryBean&quot;&gt;
    &lt;property name=&quot;jobDetails&quot;&gt;
        &lt;list&gt;
            &lt;ref bean=&quot;workJob&quot; /&gt;
        &lt;/list&gt;
    &lt;/property&gt;
    &lt;property name=&quot;triggers&quot;&gt;
        &lt;list&gt;
            &lt;ref bean=&quot;simpleTrigger&quot; /&gt;
        &lt;/list&gt;
    &lt;/property&gt;
&lt;/bean&gt;
&lt;/pre&gt;&lt;br /&gt;
где workJob - обьявление JobDetailBean,&lt;br /&gt;
simpleTrigger - триггер, обьявляющий критерии выполнения кода в SomeWorkBean,&lt;br /&gt;
schedulerFactoryBean - фабрика для создания шедьюлера&lt;br /&gt;
&lt;br /&gt;
Все, теперь метод SomeWorkBean.doWork() будет выполняться каждую минуту. Для более гибкого задание расписания, можно использовать другие триггеры, например CronTrigger&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/7978024585286147693/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/12/quartz-spring.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/7978024585286147693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/7978024585286147693'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/12/quartz-spring.html' title='Quartz + Spring'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-6056871191730970783</id><published>2011-12-01T02:05:00.000-08:00</published><updated>2012-04-04T05:45:51.182-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Algorithms"/><title type='text'>Алгоритмы сортировки</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;&lt;h3&gt;&lt;b&gt;Сортировки сравнением (Comparison sorts)&lt;/b&gt;&lt;/h3&gt;&lt;br /&gt;
Сортировки сравнением имеют минимальную сложность O(n*lg n).&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Сортировка вставками (Insert sort)&lt;/h2&gt;&lt;br /&gt;
Сложность: O(n&lt;sup&gt;2&lt;/sup&gt;)&lt;br /&gt;
&lt;br /&gt;
На каждом шаге алгоритма выбираем очередной элемент входных данных и сдвигаем его влево до тех пор, пока слева от него не останутся элементы, меньшие чем он. Метод выбора очередного элемента из исходного массива произволен; может использоваться практически любой алгоритм выбора. Обычно (и с целью получения устойчивого алгоритма сортировки), элементы выбираются по порядку их появления во входном массиве.&lt;br /&gt;
&lt;br /&gt;
Преимущества: практически не требует выделения памяти (всего O(1)); алгоритм эффективен при малом размере входного массива.&lt;br /&gt;
&lt;br /&gt;
Недостатки: неэффективен на большом размере входного массива (более 100).&lt;br /&gt;
&lt;br /&gt;
Алгоритм: &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;Вход: массив A, состоящий из элементов A[1], A[2], ..., A[n]

for i = 2, 3, ..., n:  
    key = A[i]
    j = i - 1
    while j &amp;gt; 0 and A[j] &amp;gt; key:
        A[j + 1] = A[j]
        j = j - 1
    A[j + 1] = key
&lt;/pre&gt;&lt;br /&gt;
Реализация на Java:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;//insertion sort
public static void insertionSort(int[] arr) {
    int i, j, tmp;
    //двигаемся вперед по массиву
    for (i = 1; i &amp;lt; arr.length; i++) {
        j = i;
        //двигаем элемент назад, пока он больше предыдущих
        while (j &amp;gt; 0 &amp;amp;&amp;amp; arr[j - 1] &amp;gt; arr[j]) {
            tmp = arr[j];
            arr[j] = arr[j - 1];
            arr[j - 1] = tmp;
            j--;
        }
    }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;h2&gt;Сортировка слиянием (Merge sort)&lt;/h2&gt;&lt;br /&gt;
Сложность: O(n*lg n)&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм использует парадигму &quot;Разделяй и властвуй&quot;. Сортируемая последовательность, состоящая из n элементов, разбивается на две меньшие последовательности. Рекурсивно сортируем каждую из полученных последовательностей тем же способом. Когда две меньшие последовательности отсортированы, производится слияние, поочередно выбирая из них наименьший член.&lt;br /&gt;
&lt;br /&gt;
Преимущества: алгоритм эффективен при большом размере входного массива (более 1000).&lt;br /&gt;
&lt;br /&gt;
Недостатки: требует выделения O(n) памяти&lt;br /&gt;
&lt;br /&gt;
Алгоритм:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;function mergesort(m)
    var list left, right, result
    if length(m) ≤ 1
        return m
    else
        middle = length(m) / 2
        for each x in m up to middle
            add x to left
        for each x in m after middle
            add x to right
        left = mergesort(left)
        right = mergesort(right)
        result = merge(left, right)
        return result
    end if

function merge(left,right)
    var list result
    while length(left) &amp;gt; 0 and length(right) &amp;gt; 0
        if first(left) ≤ first(right)
            append first(left) to result
            left = rest(left)
        else
            append first(right) to result
            right = rest(right)
        end if
    if length(left) &amp;gt; 0 
        append left to result
    if length(right) &amp;gt; 0 
        append right to result
    return result
&lt;/pre&gt;&lt;br /&gt;
Реализация на Java:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;//merge sort
public static int[] mergeSort(int[] arr) {
    if (arr.length &amp;lt;= 1)  return arr;

    int mid = arr.length / 2;
    int[] left = new int[mid];
    int[] right = new int[mid + arr.length%2];

    int j = 0;
    for (int i = 0; i &amp;lt; arr.length; i++) {
        if (i &amp;lt; arr.length / 2) {
            left[i] = arr[i];
        } else {
            right[j++] = arr[i];
        }
    }
    return Merge(mergeSort(left), mergeSort(right));
}

public static int[] Merge(int[] left, int[] right) {
    int a = 0, b = 0;
    int[] merged = new int[left.length + right.length];
    //забиваем отсортированный массив из левой и правой частей
    for (int i = 0; i &amp;lt; left.length + right.length; i++) {
        //поочередно берем меньший член из крайних левого и правого
        if (b &amp;lt; right.length &amp;amp;&amp;amp; a &amp;lt; left.length)
            if (left[a] &amp;gt; right[b] &amp;amp;&amp;amp; b &amp;lt; right.length)
                merged[i] = right[b++];
            else
                merged[i] = left[a++];
        else
            if (b &amp;lt; right.length)
                merged[i] = right[b++];
            else
                merged[i] = left[a++];
    }
    return merged;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Пирамидальная сортировка (Heap sort)&lt;/h2&gt;&lt;br /&gt;
Сложность: O(n*lg n)&lt;br /&gt;
&lt;br /&gt;
Сортировка пирамидой использует сортирующее дерево. Алгоритм заключается в выстраивании элементов массива в сортирующее дерево. Итерационно удаляем элементы из корня под одному за раз и перестраиваем дерево. То есть на первом шаге обмениваем Array[1] и Array[n], преобразовываем Array[1], Array[2], … , Array[n-1] в сортирующее дерево. Затем переставляем Array[1] и Array[n-1], преобразовываем Array[1], Array[2], … , Array[n-2] в сортирующее дерево. Процесс продолжается до тех пор, пока в сортирующем дереве не останется один элемент. Тогда Array[1], Array[2], … , Array[n] — упорядоченная последовательность.&lt;br /&gt;
&lt;br /&gt;
Преимущества: практически не требует выделения памяти (всего O(1))&lt;br /&gt;
&lt;br /&gt;
Недостатки: Из-за сложности алгоритма выигрыш получается только на больших n (более 1000)&lt;br /&gt;
&lt;br /&gt;
Алгоритм: &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;function build_max_heap(A)
  for i = length(A) downto 2
    do Обменять A[1] на A[i]
      heap_size[A] = heap_size[A] - 1
      max_heapify(A,1)

function max_heapify(A,i)
  l = left(i)
  r = right(i)
  if l &amp;lt;= heap_size(A) and A[l] &amp;gt; A[i]
    then largest = l
    else largest = i
  if r &amp;lt;= heap_size(A) and A[r] &amp;gt; A[largest]
    then largest = r
  if largest != i
    then Обменять A[i] на A[largest]
      max_heapify(A, largest)
&lt;/pre&gt;&lt;br /&gt;
Реализация на Java:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public static void heapSort(int[] arr) {
    for(int i = arr.length; i &amp;gt; 1; i--){
        buildMaxHeap(arr, i - 1);
    }
}

public static void buildMaxHeap(int[] arr, int max_index){
    int i, o;
    int leftChild, rightChild, maxChild, root, temp;
    root = (max_index -1)/2;

    //обходим дерево в поисках максимального члена (ранее отсортированные максимальные игнорируем)
    for(i = root; i &amp;gt;= 0; i--){
        leftChild = (2*i) + 1;
        rightChild = (2*i) + 2;

        if((leftChild &amp;lt;= max_index) &amp;amp;&amp;amp; (rightChild &amp;lt;= max_index)){
            if(arr[rightChild] &amp;gt;= arr[leftChild])
                maxChild = rightChild;
            else
                maxChild = leftChild;
        } else{
            if(rightChild &amp;gt; max_index)
                maxChild = leftChild;
            else
                maxChild = rightChild;
        }

        //передвигаем  максимальный член вверх по пирамиде (начало массива)
        if(arr[i] &amp;lt; arr[maxChild]){
            temp = arr[i];
            arr[i] = arr[maxChild];
            arr[maxChild] = temp;
        }
    }

    //убираем максимальный член в конец массива
    temp = arr[0];
    arr[0] = arr[max_index];
    arr[max_index] = temp;
}
&lt;/pre&gt;&lt;br /&gt;
&lt;h2&gt;Быстрая сортировка (Quick sort)&lt;/h2&gt;&lt;br /&gt;
Сложность: средняя O(n*lg n), максимальная O(n&lt;sup&gt;2&lt;/sup&gt;)&lt;br /&gt;
&lt;br /&gt;
Еще одна сортировка, основанная на парадигме &quot;Разделяй и властвуй&quot;. Массив A[p..r] разбивается (путем переупорядочивания его элементов) на два подмассива A[p..q-1] и A[q+1..r]. Каждый элемент первого подмассива не превышает каждый елемент второго. Индекс q вычисляется в ходе процедуры разбиения и называется опорным элементом. Подмассивы сортируются путем рекурсивного вызова процедуры быстрой сортировки. После этого весь массив оказывается отсортированным.&lt;br /&gt;
&lt;br /&gt;
Преимущества: при качественной реализации один из самых быстродействующих алгоритмов на практике; требует лишь O(lg n) дополнительной памяти&lt;br /&gt;
&lt;br /&gt;
Недостатки: при неудачном выборе опорного элемента время вычисления деградирует к O(n&lt;sup&gt;2&lt;/sup&gt;).&lt;br /&gt;
&lt;br /&gt;
Алгоритм:  &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;для сортировки всего списка вызов выглядит quick_sort(A,1,length[A])

function quick_sort(A,p,r)
  if p &amp;lt; r 
    then q = partition(A,p,r)
      quick_sort(A,p,q-1)
      quick_sort(A,q+1,r)

function partition(A,p,r)
  x = A[r]
  i = p - 1
  for i = p to r - 1
    do if A[j] &amp;lt;= x
      then i = i + 1
        Обменять A[i] на A[j]
  Обменять A[i + 1] на A[r]
  return i + 1 
&lt;/pre&gt;Реализация на Java: &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;//quick sort
public static void quickSort(int[] arr, int low, int high) {
    int i = low;
    int j = high;
    //выбираем середину в качестве опорного элемента
    int mid = arr[(low + high)/2];
    //сдвигаем меньшие члены влево от опорного, а большие вправо
    do {
        while (arr[i] &amp;lt; mid)
            ++i;
        while (mid &amp;lt; arr[j])
            --j;
        if ( i &amp;lt;= j ) {
            if( i &amp;lt; j ) {
                int t = arr[i];
                arr[i] = arr[j];
                arr[j] = t;
            }
            ++i;
            --j;
        }
    } while (i &amp;lt;= j);

    //теперь также сортируем левую и правую часть
    if (low &amp;lt; j)
        quickSort(arr, low, j);
    if (i &amp;lt; high)
        quickSort(arr, i, high);
}
&lt;/pre&gt;&lt;h3&gt;Сортировки за линейное время&lt;/h3&gt;&lt;br /&gt;
Как видно из названия, сложность следующих сортировок O(n)    &lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;Сортировка подсчетом (Counting sort)&lt;/h2&gt;&lt;br /&gt;
Идея алгоритма заключается в том, чтобы для каждого входного элемента определить количество элементов, которые меньше него. С помощью этой информации элемент можно разместить на соответствующей позиции выходного массива.  &lt;br /&gt;
&lt;br /&gt;
Достоинства: достаточно быстр  &lt;br /&gt;
&lt;br /&gt;
Недостатки: элементы входного массива должны быть в интервале от 0 до k, где k - натуральное число; требует выделения памяти  &lt;br /&gt;
&lt;br /&gt;
Алгоритм:  &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;function counting_sort
    for i = 0 to k - 1
        C[i] = 0
    for i = 0 to n - 1
        C[A[i]] = C[A[i]] + 1
    b = 0
    for j = 0 to k - 1
        for i = 0 to C[j] - 1
            A[b] = j
            b = b + 1
&lt;/pre&gt;&lt;br /&gt;
Реализация на Java:  &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;//counting sort
public static void countingSort(int[] arr, int max) {
int i, j, b = 0;
int[] c = new int[max];

//забьем вспомогательный массив нулями (его индексы соответствуют исходным значениям)
for (i = 0; i &amp;lt; max; i++)  c[i] = 0;

    //забьем вспомогательный массив значениями, равными количеству элементов, меньших данного значения индекса
    for (i = 0; i &amp;lt; arr.length; i++) {
       c[arr[i]] = c[arr[i]] + 1;
       b = 0;
    }

    //забьем на основе данных из вспомогательного массива выходной массив
    for (j = 0; j &amp;lt; max; j++) {
       for (i = 0; i &amp;lt; c[j]; i++) {
           arr[b] = j;
           b = b + 1;
       }
    }
}
&lt;/pre&gt;&lt;h2&gt;Поразрядная сортировка (Radix sort)&lt;/h2&gt;&lt;br /&gt;
Вариант сортировки с младших разрядов least significant digit (LSD). Сначала производится сортировка по младшему разряду, потом по следующему, и так далее, пока дело не дойдет до старшего разряда. Но существует и второй вариант - сортировка по старшему разряду (most significant digit (MSD)).   &lt;br /&gt;
&lt;br /&gt;
Недостатки: хотя для этой сортировки нужно меньшее количество итераций прохода по элементам, чем для сортировок сравнения, каждая итерация может длиться значительно дольше.  &lt;br /&gt;
&lt;br /&gt;
Алгоритм:  &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;function radix_sort
  for i = 1 to d 
    do Устойчивая сортировка массива A по i-ой цифре
&lt;/pre&gt;&lt;br /&gt;
Реализация на Java:     &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;//radix sort
public static void radixSort(int[] arr) {
int cnt[][] = new int[4][];
int b[];
int i, j;
int a_len = arr.length;

if (a_len &amp;lt; 2) {
        // массив длиной 1 элемент не нужно сортировать :)
        return;
    }

    // инициализируем счетчик [cnt]
    for (j = 0; j &amp;lt; 4; j++) {
        cnt[j] = new int[257];
        for (i = 0; i &amp;lt; 257; i++) cnt[j][i] = 0;
    }

    // выделяем память под копию сортируемого массива
    b = new int[a_len];

    // подсчитываем количество элементов для каждого значения j-го разряда
    for (i = 0; i &amp;lt; a_len; i++) {
        for (j = 0; j &amp;lt; 4; j++) {
            cnt[j][1 + ((arr[i] &amp;gt;&amp;gt;&amp;gt; (8 * j)) &amp;amp; 0xff)]++;
}
}

for (j = 0; j &amp;lt; 4; j++) {
        /*
            вычисляем позиции cnt[i], начиная с которых будут располаться элементы
            с соответствующим значением j-го разряда
        */
        for (i = 1; i &amp;lt; 256; i++) cnt[j][i] += cnt[j][i - 1];
        // расставляем элементы из массива a в массив b в указанном порядке
        for (i = 0; i &amp;lt; a_len; i++) {
            b[cnt[j][(arr[i] &amp;gt;&amp;gt;&amp;gt; (8 * j)) &amp;amp; 0xff]++] = arr[i];
}
// копируем массив b на место массива a
for (i = 0; i &amp;lt; a_len; i++) arr[i] = b[i];
    }
}
&lt;/pre&gt;&lt;h2&gt;Блочная (карманная) сортировка (Bucket sort)&lt;/h2&gt;&lt;br /&gt;
Идея, лежащая в основе алгоритма заключается в том, чтобы разбить интервал [0,1) на n одинаковых интервалов, а затем распределить по этим интервалам n входных величин. Поскольку входные элементы равномерно распределены, можно предположить, что в каждый интервал попадет не много элементов. Для получения выходной последовательности, надо провести сортировку в каждом интервале, а затем последовательно перечислить элементы в каждом из них.  &lt;br /&gt;
&lt;br /&gt;
Недостатки: ожидаемое время работы алгоритма линейно зависит от количества входных данных только при равномерном распределении входных элементов на отрезке.  &lt;br /&gt;
&lt;br /&gt;
Алгоритм:  &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;function bucket-sort(A, n) is
  buckets ← новый массив из n пустых элементов
  for i = 0 to (length(A)-1) do
    вставить A[i] в конец массива buckets[nA[i]]
  for i = 0 to n - 1 do
    next-sort(buckets[i])
  return Конкатенация массивов buckets[0], ..., buckets[n-1]
&lt;/pre&gt;&lt;br /&gt;
Реализация на Java: &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;//bucket sort
public static void bucketSort(int[] arr) {

    //поиск максимального элемента массива
    int maxValue = arr[0];
 
    for (int k = 1; k &lt; arr.length; k++) {
       if (arr[k] &gt; maxValue)
           maxValue = arr[k];
    }

    int i, j;
    //создадим вспомогательный массив
    int[] bucket = new int[maxValue + 1];
    //распределим числа по карманам
    for(i = 0; i &amp;lt; arr.length; i++ ) {
        bucket[arr[i]]++;
    }

    //отсортируем числа в карманах используя сортировку подсчетом
    for(i = 0, j = 0; i &amp;lt; bucket.length; i++) {
        for(; bucket[i]&amp;gt;0; (bucket[i])--) {
            arr[j++] = i;
        }
    }
}
&lt;/pre&gt;ну и напоследок выложу код для запуска всех вышеперечисленных сортировок, может кому-то он пригодится:  &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class Sorting {

    public static void main(String[] args) {
        String[] types = {&quot;insertion&quot;,&quot;merge&quot;,&quot;heap&quot;,&quot;quick&quot;, &quot;counting&quot;, &quot;radix&quot;, &quot;bucket&quot;};
        sort(types);
    }

    private static void sort(String[] types) {
        for (String type: types) {
            int[] arr = {8,4,7,2,7,0,32,17,45,43,32,4,38,4,89,3,6,7,86,3,545,6,7,2,54};
            int[] arr2 = {8,24,7,2,7,0,22,17,15,13,12,4,18,4,19,3,6,7,16,3,15,6,7,2,14};
            if (type.equals(&quot;insertion&quot;)) {
                insertionSort(arr);
            } else if (type.equals(&quot;merge&quot;)) {
                arr = mergeSort(arr);
            } else if (type.equals(&quot;heap&quot;)) {
                heapSort(arr);
            } else if (type.equals(&quot;quick&quot;)) {
                quickSort(arr, 0, arr.length -1);
            } else if (type.equals(&quot;counting&quot;)) {
                countingSort(arr, 1000);
            } else if (type.equals(&quot;radix&quot;)) {
                radixSort(arr);
            } else if (type.equals(&quot;bucket&quot;)) {
                bucketSort(arr2);
            }
    
            System.out.println(&quot;\n&quot;+ type + &quot;Sorted: &quot;);
            if (!type.equals(&quot;bucket&quot;)) {
                for (int i: arr)  System.out.print(i + &quot;,&quot;);
            } else {
                for (int i: arr2)  System.out.print(i + &quot;,&quot;);
            }
        }
    }


   ... //here is the code of sorts
}
&lt;/pre&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/6056871191730970783/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/12/blog-post.html#comment-form' title='Комментарии: 6'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6056871191730970783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6056871191730970783'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/12/blog-post.html' title='Алгоритмы сортировки'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-8520084749875506227</id><published>2011-11-12T12:04:00.000-08:00</published><updated>2011-11-14T00:07:10.853-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="etherpad"/><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="scala"/><title type='text'>Установка Etherpad на Ubuntu со Scala 2.8.1</title><content type='html'>Для работы Etherpad 1.x требуется Sun JDK, Scala 2.8.1&lt;br /&gt;
&lt;br /&gt;
Сборку Etherpad под scala 2.8.1 можно скачать &lt;a href=&quot;https://github.com/ether/pad/pull/179&quot;&gt;здесь&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Установка Sun JDK&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo add-apt-repository &quot;deb http://archive.canonical.com/ lucid partner&quot;
sudo apt-get update   
sudo apt-get install sun-java6-jdk
sudo update-alternatives --config java
&lt;/pre&gt;&lt;br /&gt;
установка mysql&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;mysql -u root -p
create database etherpad;
grant all privileges on etherpad.* to &#39;etherpad&#39;@&#39;localhost&#39; identified by &#39;passwd&#39;;
quit
&lt;/pre&gt;&lt;br /&gt;
установка scala&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo apt-get install scala
wget http://www.scala-lang.org/downloads/distrib/files/scala-2.8.1.final.tgz
sudo tar -C /opt/ -xvzf scala-2.8.1.final.tgz
PATH=&quot;$PATH:/opt/scala-2.8.1.final/bin&quot;
&lt;/pre&gt;&lt;br /&gt;
Скачанный Эзер кладем в /usr/local/etherpad&lt;br /&gt;
&lt;br /&gt;
не забудем добавить переменные среды&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;export JAVA_HOME=&quot;/usr/lib/jvm/java-6-sun&quot;
export SCALA_HOME=&quot;/opt/scala-2.8.1.final&quot;
export SCALA_LIBRARY_JAR=&quot;/opt/scala-2.8.1.final/lib/scala-library.jar&quot;
export MYSQL_CONNECTOR_JAR=&quot;/usr/share/java/mysql-connector-java-5.1.10.jar&quot;
export JAVA=&quot;$JAVA_HOME/bin/java&quot;
export SCALA=&quot;/opt/scala-2.8.1.final/bin/scala&quot;
export PATH=&quot;$JAVA_HOME/bin:$PATH&quot;
&lt;/pre&gt;&lt;br /&gt;
после всех приготовлений можно собирать Эзер&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;bin/rebuildjar.sh clearcache
&lt;/pre&gt;&lt;br /&gt;
перед запуском подправить etheprad/etherpad/etc/etherpad.localdev-default.properties&lt;br /&gt;
мои настройки:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;alwaysHttps = false
ajstdlibHome = ../infrastructure/framework-src/modules
appjetHome = ./data/appjet
devMode = true
#etherpad.SSOScript = /usr/local/structures/bin/etherpad.validator
etherpad.adminPass = ethe4RiveriBUYTDEFbzriutb7BIoxboyd7U
etherpad.fakeProduction = false
etherpad.isProduction = false
etherpad.proAccounts = true
etherpad.SQL_JDBC_DRIVER = com.mysql.jdbc.Driver
etherpad.SQL_JDBC_URL = jdbc:mysql://localhost:3306/etherpad
etherpad.SQL_PASSWORD = passwd
etherpad.SQL_USERNAME = etherpad
hidePorts = true
listen = 9000
#listenSecure = 9001
#sslKeyPassword = KEYPASS_CHANGEME
#sslKeyStore = ./data/appjet/keystore
#sslStorePassword = KEYPASS_CHANGEME
logDir = ./data/logs
modulePath = ./src
motdPage = /ep/pad/view/ro.3PfHCD0ApLc/latest?fullScreen=1&amp;slider=0&amp;sidebar=0
topdomains = mydomain.ru, localhost
transportPrefix = /comet
transportUseWildcardSubdomains = true
useHttpsUrls = false
useVirtualFileRoot = ./src
theme = default
etherpad.soffice = /usr/bin/soffice
customBrandingName = etherpad
customEmailAddress = etherpad@etherpad.com
showLinkandLicense = false
smtpServer = 192.168.0.1:25
&lt;/pre&gt;&lt;br /&gt;
запуск&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;bin/run-local.sh&amp;
&lt;/pre&gt;&lt;br /&gt;
в дальнейшем можно добавить скрипт в init.d для автоматического запуска Эзера и экспорта переменых среды</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/8520084749875506227/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/11/etherpad-ubuntu-scala-281.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/8520084749875506227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/8520084749875506227'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/11/etherpad-ubuntu-scala-281.html' title='Установка Etherpad на Ubuntu со Scala 2.8.1'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-6407472856936208615</id><published>2011-11-11T11:11:00.000-08:00</published><updated>2013-08-28T03:09:44.544-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java core"/><category scheme="http://www.blogger.com/atom/ns#" term="reflect"/><title type='text'>Чтение и запись Tab Separated Values файлов</title><content type='html'>Что же представляют из себя файлы в формате TSV? Это текстовые файлы, представляющие собой набор строк. В каждой строке одинаковое количество &quot;полей&quot; определенного формата, разделенные символом табуляции (&quot;\t&quot;). Похоже на некое подобие таблицы.&lt;br /&gt;
&lt;br /&gt;
Итак, приступим к написанию reader-а:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;/**
 * @author vie
 *
 * TSVReader.java
 * Class for read tab separated values files
 */
public class TSVReader&amp;lt;T&gt; {

    private final String filePath;

    public TSVReader(String filePath) {
        this.filePath = filePath;
    }

    /**
     * This method reads tab separated values file
     * into object of the arbitrary class
     *
     * @param clazz type of transmitted class
     * @return List
     * @throws com.site.tsv.exceptions.TSVException
     */
    public List&amp;lt;T&gt; read(Class&amp;lt;T&gt; clazz) throws TSVException {
        List&amp;lt;T&gt; result = new LinkedList&amp;lt;T&gt;();

        try {
            BufferedReader bReader = new BufferedReader(new FileReader(filePath));
            String line;

            //recieving all lines
            int i = 1;
            while ((line = bReader.readLine()) != null) {
                //recieving all line members
                String datavalue[] = line.split(&quot;\t&quot;);

                //create instance of line entity
                Constructor constructor = clazz.getConstructor(null);
                Object somethingInstance = constructor.newInstance(null);

                //parsing line entity members
                Field[] fields = clazz.getDeclaredFields();

                //recieve map of line entity member types
                Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; mapFields = defineFields(clazz);

                //for each line entity field
                if (fields != null &amp;&amp; datavalue != null &amp;&amp; fields.length == datavalue.length) {
                    for (int j = 0; j &lt; fields.length; j++) {
                        //for each line entity field
                        String s = fields[j].getName();
                        s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

                        //exec line entity setter methods
                        Method method = clazz.getMethod(&quot;set&quot; + s, mapFields.get(j));
                        method.invoke(somethingInstance, getDeterminatedValue(datavalue[j], fields[j].getType()));
                    }
                } else if (fields != null &amp;&amp; datavalue != null &amp;&amp; fields.length != datavalue.length) {
                    throw new TSVInvalidFileException(&quot;Count of formatted file fields on line &quot; + i + &quot; not equal count of entity fields&quot;);
                }

                i++;
                result.add((T) somethingInstance);
            }
            bReader.close();
        } catch (FileNotFoundException e) {
            throw new TSVException(e);
        } catch (IOException e) {
            throw new TSVException(e);
        } catch (ParseException e) {
            throw new TSVInvalidFileException(e);
        } catch (NumberFormatException e) {
            throw new TSVInvalidFileException(e);
        } catch (NoSuchMethodException e) { //reflect
            throw new TSVException(e);
        } catch (InstantiationException e) {
            throw new TSVException(e);
        } catch (IllegalAccessException e) {
            throw new TSVException(e);
        } catch (InvocationTargetException e) {
            throw new TSVException(e);
        }
        return result;
    }

    /**
     * Returns field names and types
     *
     * @param clazz type of transmitted class
     * @return Map&amp;lt;string,integer&gt;.
     * @throws com.site.tsv.exceptions.TSVIncorrectAnnotatedFieldsException
     */
    private Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; defineFields(Class&amp;lt;?&gt; clazz) throws TSVIncorrectAnnotatedFieldsException {
        Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; map = new HashMap&amp;lt;Integer, Class&amp;lt;?&gt;&gt;();

        Field[] fields = clazz.getDeclaredFields();
        int i = 0;
        for (Field field : fields) {
            if (field.isAnnotationPresent(TSVInteger.class)) {
                map.put(i++, Integer.class);
            } else if (field.isAnnotationPresent(TSVDouble.class)) {
                map.put(i++, Double.class);
            } else if (field.isAnnotationPresent(TSVString.class)) {
                map.put(i++, String.class);
            } else if (field.isAnnotationPresent(TSVDate.class)) {
                map.put(i++, Date.class);
            }
        }

        if (fields.length == 0 || fields.length != map.size()) {
            throw new TSVIncorrectAnnotatedFieldsException(&quot;Some field not annotated or count of fields = 0!&quot;);
        }

        return map;
    }

    /**
     * Returns converted to the native type field
     *
     * @param original value of obtained field
     * @param needType type of transmitted class
     * @return Object
     * @throws java.text.ParseException
     */
    private Object getDeterminatedValue(String original, Class&amp;lt;?&gt; needType) throws ParseException {
        if (needType.getName().equals(&quot;java.lang.Integer&quot;)) {
            return Integer.parseInt(original);
        } else if (needType.getName().equals(&quot;java.lang.Double&quot;)) {
            return Double.parseDouble(original);
        } else if (needType.getName().equals(&quot;java.lang.String&quot;)) {
            return original;
        } else if (needType.getName().equals(&quot;java.util.Date&quot;)) {
            SimpleDateFormat formatter = new SimpleDateFormat(&quot;dd.MM.yyyy&quot;);
            return formatter.parse(original);
        } else {
            return null;
        }
    }
}
&lt;/pre&gt;В классе я использовал generics, чтобы проверять заданного типы entity на этапе компиляции. В преобразовании строк с различными типами данных в entity объект мне помог reflection. Для разбора с его помощью entity, написаны приведенные ниже аннотации. Также я создал несколько исключений, чтобы в при выпадении ошибок можно было быстро понять что свалилось, будь то reflection, IO или преобразование чисел и дат.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
теперь Writer:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;/**
 * @author vie
 *
 * TSVWriter.java
 * Class for write tab separated values files
 */
public class TSVWriter&amp;lt;T&gt; {

    private final static String tab = &quot;\t&quot;;

    private final String filePath;

    public TSVWriter(String filePath) {
        this.filePath = filePath;
    }

    /**
     * This method writes tab separated values file
     * from entity object
     *
     * @param list list of line entity objects
     * @param clazz type of transmitted class
     * @throws com.site.tsv.exceptions.TSVException
     */
    public void write(List&amp;lt;T&gt; list, Class&amp;lt;T&gt; clazz) throws TSVException {
        try {
            BufferedWriter bufferWriter = new BufferedWriter(new FileWriter(filePath));
            //getting all line object fields
            Field[] fields = clazz.getDeclaredFields();

            //for each line
            if (fields != null) {
                for (T lineObject: list) {
                    StringBuilder line = new StringBuilder();

                    //for each line entity field
                    for (Field field : fields) {
                        String s = field.getName();
                        s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

                        //exec line entity setter methods
                        Method method = clazz.getMethod(&quot;get&quot; + s);
                        String val = method.invoke(lineObject) + &quot;&quot;;

                        line.append(val).append(tab);
                    }
                    bufferWriter.write(line.substring(0, line.length() - 1));
                    bufferWriter.newLine();
                }
            }
            bufferWriter.close();
        } catch (FileNotFoundException e) {
            throw new TSVException(e);
        } catch (IOException e) {
            throw new TSVException(e);
        } catch (NoSuchMethodException e) {
            throw new TSVException(e);
        } catch (IllegalAccessException e) {
            throw new TSVException(e);
        } catch (InvocationTargetException e) {
            throw new TSVException(e);
        }
    }
}
&lt;/pre&gt;&lt;br /&gt;
Аннотации:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;/**
 * @author vie
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface TSVInteger {
}

/**
 * @author vie
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface TSVDouble {
}

/**
 * @author vie
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface TSVString {
}

/**
 * @author vie
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface TSVDate {
}
&lt;/pre&gt;&lt;br /&gt;
Исключения:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;/**
 * @author vie
 */
public class TSVException extends Exception {

    public TSVException() {
       super();
    }

    public TSVException(String message) {
       super(message);
    }

    public TSVException(String message, Throwable cause) {
        super(message, cause);
    }

    public TSVException(Throwable cause) {
        super(cause);
    }
}

/**
 * @author vie
 */
public class TSVInvalidFileException extends TSVException {

    public TSVInvalidFileException() {
       super();
    }

    public TSVInvalidFileException(String message) {
       super(message);
    }

    public TSVInvalidFileException(String message, Throwable cause) {
        super(message, cause);
    }

    public TSVInvalidFileException(Throwable cause) {
        super(cause);
    }
}

/**
 * @author vie
 */
public class TSVIncorrectAnnotatedFieldsException extends TSVException {

    public TSVIncorrectAnnotatedFieldsException() {
       super();
    }

    public TSVIncorrectAnnotatedFieldsException(String message) {
       super(message);
    }

    public TSVIncorrectAnnotatedFieldsException(String message, Throwable cause) {
        super(message, cause);
    }

    public TSVIncorrectAnnotatedFieldsException(Throwable cause) {
        super(cause);
    }
}
&lt;/pre&gt;&lt;br /&gt;
Все, теперь можно попробовать загрузить и записать в другой файл. Для этого создадим entity, аналогичный структуре файла:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;test1 55 01.01.2010 rw
test2 daswqrg 56 31.01.2011 comment1
test3 dds 57 30.11.2011 comment32
&lt;/pre&gt;&lt;br /&gt;
entity: &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;/**
 * @author vie
 */
public class TestLineEntity {

    @TSVString
    protected String value;

    @TSVInteger
    protected Integer id;

    @TSVDate
    protected Date date;

    @TSVString
    protected String comment;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
    /*other getters and setters*/
}
&lt;/pre&gt;&lt;br /&gt;
сам код считывания и записи данных:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;TSVReader&amp;lt;TestLineEntity&gt; tsvReader = new TSVReader&amp;lt;TestLineEntity&gt;(&quot;test.tsv&quot;);
List&amp;lt;TestLineEntity&gt; test = tsvReader.read(TestLineEntity.class);

TSVWriter&amp;lt;TestLineEntity&gt; tsvWriter = new TSVWriter&amp;lt;TestLineEntity&gt;(&quot;new_test.tsv&quot;);
tsvWriter.write(forum, TestLineEntity.class);
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/6407472856936208615/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/11/tab-separated-values.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6407472856936208615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6407472856936208615'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/11/tab-separated-values.html' title='Чтение и запись Tab Separated Values файлов'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-6130237043764997843</id><published>2011-11-09T01:17:00.000-08:00</published><updated>2012-04-03T14:42:37.950-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java core"/><category scheme="http://www.blogger.com/atom/ns#" term="multi-threading"/><title type='text'>Разделение выполнения задачи на n потоков</title><content type='html'>Бывает при решении некоторых задач, таких как загрузка данных с FTP приходится разделять ход выполнения задачи на несколько потоков. &lt;br /&gt;
Казалось бы, все просто. Создаем n-е количество потоков (каждый из которых делает часть общей работы) и запускаем их:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class MainClass {
  public static void main(String[] args) {
    WorkClass work = new WorkClass();
    work.doSomeWork();
  }
}

public class WorkClass {

  public void doSomeWork() {             
    for (int i = 0; i &lt; 5; i++) { 
      Worker worker = new Worker(&quot;directory&quot; + i);
      Thread thread = new Thread(worker);
      thread.start();
    }
    
    //here we must wait for execution of all threads

    //doing work on    
  }

  public class Worker implements Runnable {

    private String dir;

    public Worker(String dir) {
      this.dir = dir;
    }
  
    @Override
    public void run() {
      doPieceOfWork();
    }

    private void doPieceOfWork() {
      //doing loading from FTP, depending on the name of directory ...
    }
  }
}
&lt;/pre&gt;
Здесь в качестве примера разделения выполняемой работы на 5 потоков приводится загрузка по FTP. Каждый поток грузит свою папку. Но может возникнуть проблема. Надо подождать, пока выполнятся все запущенные потоки, и только после этого продолжать работу основного потока. Для этого обернем вызов потоков в блок синхронизации.
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public void doSomeWork() {
  synchronized (this) {             
    for (int i = 0; i &lt; 5; i++) { 
      Worker worker = new Worker(&quot;directory&quot; + i);
      Thread thread = new Thread(worker);
      thread.start();
    }
  }
}
&lt;/pre&gt;
Далее остановим главный поток после запуска второстепенных потоков до тех пор, пока не получим ответ о завершении работы каждого из них. Для этого сделаем цикл, в котором получаем уведомление от одного из потоков и, если количество завершенных второстепенных потоков меньше количества запущенных, продолжаем ожидать ответа от оставшихся:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public void doSomeWork() {
  synchronized (this) { 
    Vector events = new Vector();
            
    for (int i = 0; i &lt; 5; i++) {       
      Worker worker = new Worker(this, &quot;directory&quot; + i, events);
      Thread thread = new Thread(worker);
      thread.start();
    }

    //if all threads are dead, go ahead
    while (true) {
      try {
        this.wait();
      } catch (InterruptedException e) {
        errorLogger.error(e.getMessage(), e);
      }
      if (events.size() == 5) {
        break;
      }
    }        
  }

  //doing work on
}
&lt;/pre&gt;
теперь надо добавить во второстепенные потоки уведомления, которые будет получать основной поток:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class Worker implements Runnable {

  private String dir;

  private Vector events;

  public Worker(WorkClass monitor, String dir, Vector events) {
    this.dir = dir;
    this.events = events;
  }
  
  @Override
  public void run() {
    doPieceOfWork();
  }

  private void doPieceOfWork() {
    //doing loading from FTP, depending on the name of directory ...
    
    synchronized (monitor) {
      events.add(new Object());
      monitor.notify();      
    }
  }
}
&lt;/pre&gt;Cледует обратить внимание, что блоки синхронизации во второстепенных потоках и в главном создаются по монитору work класса WorkClass. Также в класс Worker добавлена коллекция events, которая выполняет роль счетчика завершенных потоков. Класс Vector выбран не случайно, тк его методы синхронизированы. В качестве его альтернативы можно воспользоваться Collections.synchronizedList(new ArrayList()). Хотя в данном случае синхронизация методов коллекции и не будет играть никакой роли, тк работа с ней происходит в блоке синхронизации.


Все, теперь метод doSomeWork() разделит загрузку по FTP на 5 потоков и продолжит свою работу после завершения всех запущенных потоков.

Общий результат выглядит так:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class MainClass {
  public static void main(String[] args) {
    WorkClass work = new WorkClass();
    work.doSomeWork();
  }
}

public class WorkClass {
  protected static final Logger errorLogger = LoggerFactory.getLogger(&quot;errorLogger&quot;);

  public void doSomeWork() {
    synchronized (this) {     
      Vector events = new Vector();
        
      for (int i = 0; i &lt; 5; i++) { 
        Worker worker = new Worker(this, &quot;directory&quot; + i, events);
        Thread thread = new Thread(worker);
        thread.start();
      }
      
      //if all threads are dead, go ahead
      while (true) {
        try {
          this.wait();
        } catch (InterruptedException e) {
          errorLogger.error(e.getMessage(), e);
        }
        if (events.size() == 5) {
          break;
        }
      }
    }
    
    //doing work on 
  }

  public class Worker implements Runnable {

    private String dir;

    private Vector events;

    public Worker(WorkClass monitor, String dir, Vector events) {
      this.dir = dir;
      this.events = events;
    }
  
    @Override
    public void run() {
      doPieceOfWork();
    }

    private void doPieceOfWork() {
      //doing loading from FTP, depending on the name of directory ...
    
      synchronized (monitor) {
        events.add(new Object());
        monitor.notify();        
      }
    }
  }
}
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/6130237043764997843/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/11/n.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6130237043764997843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6130237043764997843'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/11/n.html' title='Разделение выполнения задачи на n потоков'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-6724158242534482050</id><published>2011-10-31T01:17:00.000-07:00</published><updated>2011-11-01T01:23:02.562-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Maven"/><title type='text'>Maven Shade Plugin</title><content type='html'>Shade плагин как альтернатива Assembly.&lt;br /&gt;
&lt;br /&gt;
На днях используя Assembly, столкнулся со следующей проблемой. Приложение со Spring собрал в jar. При запуске валилась ошибка:&lt;br /&gt;
&lt;font color=&quot;red&quot;&gt;&lt;blockquote&gt;Exception in thread &quot;main&quot; org.springframework.beans.factory.parsing.BeanDefinitionParsingException:&lt;br /&gt;
Configuration problem: Unable to locate Spring NamespaceHandler&lt;br /&gt;
for XML schema namespace [http://www.springframework.org/schema/context]&lt;br /&gt;
at org.springframework.beans.factory.parsing.FailFastProblemReporter.&lt;br /&gt;
error(FailFastProblemReporter.java:68)&lt;br /&gt;
at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)&lt;br /&gt;
...&lt;/blockquote&gt;&lt;/FONT&gt;&lt;br /&gt;
Это означает что при копировании в META-INF спринговых файлов spring.schemas и spring.handlers, они перезатираются для каждой spring библиотеки.&lt;br /&gt;
&lt;br /&gt;
Assebly плагин выглядел так:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;plugin&gt;
    &lt;artifactid&gt;maven-assembly-plugin&lt;/artifactId&gt;
    &lt;version&gt;2.2.1&lt;/version&gt;
    &lt;configuration&gt;
        &lt;appendassemblyid&gt;false&lt;/appendAssemblyId&gt;
        &lt;descriptorrefs&gt;
            &lt;descriptorref&gt;jar-with-dependencies&lt;/descriptorRef&gt;
        &lt;/descriptorRefs&gt;
        &lt;archive&gt;
            &lt;manifest&gt;
                &lt;mainclass&gt;com.mypackage.MainClass&lt;/mainClass&gt;
            &lt;/manifest&gt;
        &lt;/archive&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;
&lt;/pre&gt;&lt;br /&gt;
Немного погуглив, нашел вариант с обьявлением своего assembly дескриптора, или со скачиванем all-in-one Spring библиотеки. Но на stackoverflow посоветовали использовать плагин Shade.&lt;br /&gt;
&lt;br /&gt;
Обьявление Shade:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;plugin&gt;
    &lt;groupid&gt;org.apache.maven.plugins&lt;/groupId&gt;
    &lt;artifactid&gt;maven-shade-plugin&lt;/artifactId&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;phase&gt;package&lt;/phase&gt;
            &lt;goals&gt;
                &lt;goal&gt;shade&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
                &lt;transformers&gt;
                    &lt;transformer implementation=&quot;org.apache.maven.plugins.shade.resource.ManifestResourceTransformer&quot;&gt;
                        &lt;mainclass&gt;com.mypackage.MainClass&lt;/mainClass&gt;
                    &lt;/transformer&gt;
                    &lt;transformer implementation=&quot;org.apache.maven.plugins.shade.resource.AppendingTransformer&quot;&gt;
                        &lt;resource&gt;META-INF/spring.handlers&lt;/resource&gt;
                    &lt;/transformer&gt;
                    &lt;transformer implementation=&quot;org.apache.maven.plugins.shade.resource.AppendingTransformer&quot;&gt;
                        &lt;resource&gt;META-INF/spring.schemas&lt;/resource&gt;
                    &lt;/transformer&gt;
                &lt;/transformers&gt;
                &lt;filters&gt;
                    &lt;filter&gt;
                        &lt;artifact&gt;*:*&lt;/artifact&gt;
                        &lt;excludes&gt;
                            &lt;exclude&gt;META-INF/*.SF&lt;/exclude&gt;
                            &lt;exclude&gt;META-INF/*.DSA&lt;/exclude&gt;
                            &lt;exclude&gt;META-INF/*.RSA&lt;/exclude&gt;
                        &lt;/excludes&gt;
                    &lt;/filter&gt;
                &lt;/filters&gt;
            &lt;/configuration&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;
&lt;/pre&gt;&lt;br /&gt;
Все. После этого спокойно собираем jar командой package и никаких проблем.</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/6724158242534482050/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/11/maven-shade-plugin.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6724158242534482050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6724158242534482050'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/11/maven-shade-plugin.html' title='Maven Shade Plugin'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-1792789222924925523</id><published>2011-09-28T07:50:00.000-07:00</published><updated>2012-02-09T02:39:58.953-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Jax-RS"/><category scheme="http://www.blogger.com/atom/ns#" term="Jersey"/><category scheme="http://www.blogger.com/atom/ns#" term="RESTful"/><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><title type='text'>RESTful веб-сервис на Jersey + Spring 3</title><content type='html'>Пишем простой REST веб-сервис.&lt;br /&gt;
&lt;br /&gt;
Как известно, начиная с третьей версии у Spring появилась возможность легко создавать REST веб сервис с помощью Spring MVC (на аннотациях @RequestMapping). Но я хочу рассмотреть классический Jax-RS с помощью Jersey. Итак, начнем.&lt;br /&gt;
&lt;br /&gt;
Для начала определим maven зависимости:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;!-- here is Spring dependencies version 3.x--&gt;

&lt;dependency&gt;
    &lt;groupid&gt;com.sun.jersey&lt;/groupId&gt;
    &lt;artifactid&gt;jersey-server&lt;/artifactId&gt;
    &lt;version&gt;1.9.1&lt;/version&gt;
&lt;/dependency&gt;

&lt;!-- Jersey + Spring --&gt;
&lt;dependency&gt;
    &lt;groupid&gt;com.sun.jersey.contribs&lt;/groupId&gt;
    &lt;artifactid&gt;jersey-spring&lt;/artifactId&gt;
    &lt;version&gt;1.9.1&lt;/version&gt;
    &lt;exclusions&gt;
        &lt;exclusion&gt;
            &lt;groupid&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactid&gt;spring&lt;/artifactId&gt;
        &lt;/exclusion&gt;
        &lt;exclusion&gt;
            &lt;groupid&gt;org.springframework&lt;/groupId&gt;
            &lt;artifactid&gt;spring-core&lt;/artifactId&gt;
        &lt;/exclusion&gt;
        &lt;!-- here is other Spring dependencies --&gt;
    &lt;/exclusions&gt;
&lt;/dependency&gt;

&lt;dependency&gt;
    &lt;groupid&gt;com.sun.xml.bind&lt;/groupId&gt;
    &lt;artifactid&gt;jaxb-impl&lt;/artifactId&gt;
    &lt;version&gt;2.1.9&lt;/version&gt;
&lt;/dependency&gt;
&lt;/pre&gt;exclusions в зависимости jersey+spring необходимы потому, что библиотека требует зависимости спринга версий 2 или 2.5. А мы ей их дать не можем, тк используем третью версию. В исключениях требуется указать все библиотеки Spring, которые у нас есть в проекте.&lt;br /&gt;
&lt;br /&gt;
Теперь можно писать сам сервис. Будем доставать продукты по их id:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Path(&quot;/product/{id}&quot;)
@Component
@Scope(&quot;prototype&quot;)
public class ProductRSController {

    @Autowired
    private ProductService srv;

    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Product getDescription(@PathParam(&quot;id&quot;) String productId) {
        Product product = srv.getProduct(productId);
        return product;
    }
}
&lt;/pre&gt;Пометив метод с помощью аннотаций @GET и @Produces(MediaType.APPLICATION_XML), мы указали, что url вида http://myserver.com/myapp/rs/product/123 (где myserver.com - наш сервер, myapp - имя развернутого приложения), будет возвращать в ответ сериализованный обьект Product в xml.&lt;br /&gt;
&lt;br /&gt;
Класс ProductService представляет собой сервис бин, с методом Product getProduct(String productId) {...}&lt;br /&gt;
&lt;br /&gt;
Не забудем настроить web.xml:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;context-param&gt;
    &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;&lt;param-value&gt;/WEB-INF/spring-context.xml&lt;/param-value&gt;&lt;/context-param&gt;

&lt;listener&gt;
    &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
&lt;/listener&gt;

&lt;servlet&gt;
    &lt;servlet-name&gt;Jersey Web Application&lt;/servlet-name&gt;
    &lt;servlet-class&gt;com.sun.jersey.spi.spring.container.servlet.SpringServlet&lt;/servlet-class&gt;
    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;

&lt;servlet-mapping&gt;
    &lt;servlet-name&gt;Jersey Web Application&lt;/servlet-name&gt;
    &lt;url-pattern&gt;/rs/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
&lt;/pre&gt;и spring-context.xml:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;context:annotation-config&gt;&lt;/context:annotation-config&gt;
&lt;context:component-scan base-package=&quot;com.mypackage&quot;&gt;&lt;/context:component-scan/&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Теперь можно разворачивать приложение и зайти по URL http://myserver.com/myapp/rs/product/123. В случае успеха мы увидим полученный XML, если конечно у нас есть Product с id = 123.&lt;br /&gt;
&lt;br /&gt;
Теперь можно создавать клиент веб-сервиса. Для удобства работы, возьмем клиент от Jersey.&lt;br /&gt;
&lt;br /&gt;
зависимости:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;dependency&gt;
    &lt;groupid&gt;com.sun.xml.bind&lt;/groupId&gt;
    &lt;artifactid&gt;jaxb-impl&lt;/artifactId&gt;
    &lt;version&gt;2.1.9&lt;/version&gt;
&lt;/dependency&gt;

&lt;dependency&gt;
    &lt;groupid&gt;com.sun.jersey&lt;/groupId&gt;
    &lt;artifactid&gt;jersey-client&lt;/artifactId&gt;
    &lt;version&gt;1.9.1&lt;/version&gt;
&lt;/dependency&gt;
&lt;/pre&gt;&lt;br /&gt;
сам клиент будет выглядеть так:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class RESTClient {

    public Product recieveObject() {
        Client c = Client.create();
        WebResource r = client.resource(&quot;http://myserver.com/myapp/rs/&quot;);
        Product product = response = r.path(&quot;product/123&quot;).
                accept(MediaType.APPLICATION_XML_TYPE).
                get(Product.class);

        return product;
    }
    
    public String recieveXML() {
        Client c = Client.create();
        WebResource r = client.resource(&quot;http://myserver.com/myapp/rs/&quot;);
        String product = response = r.path(&quot;product/123&quot;).
                accept(MediaType.APPLICATION_XML_TYPE).
                get(String.class);

        return product;
    }
}
&lt;/pre&gt;метод recieveObject() возвращает десериализованный обьект Product, а метод recieveXML() возвращает XML.&lt;br /&gt;
&lt;br /&gt;
С помощью Generics можно сделать клиент универсальным:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class RESTClient {

    private static final Client client;

    private String resource = &quot;http://myserver.com/myapp/rs/&quot;;

    static {
        client = Client.create();
    }

    public RESTClient() {
    }

    public RESTClient(String resource) {
        this.resource = resource;
    }

    public void recieve() {

        //object
        Product product = recieve(Product.class, &quot;product/&quot;, &quot;123&quot;);
        System.out.println(&quot;response.getProductId: &quot; + product.getProductId());
        
        //string 
        String xml = recieve(String.class, &quot;product/&quot;, &quot;123&quot;);
        System.out.println(&quot;response: &quot; + xml);
    }

    private &amp;lt;T&gt; T recieve(Class&amp;lt;T&gt; type, String URI, String id) {
        WebResource r = client.resource(resource);

        T response = r.path(URI + id).
                accept(MediaType.APPLICATION_XML_TYPE).
                get(type);

        return response;
    }
}
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Для настройки вывода данных в формате JSON необходимо проделать следующее:&lt;br /&gt;
&lt;br /&gt;
Добавить зависимость:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;dependency&gt;
            &lt;groupid&gt;com.sun.jersey&lt;/groupId&gt;
            &lt;artifactid&gt;jersey-json&lt;/artifactId&gt;
            &lt;version&gt;1.10&lt;/version&gt;
        &lt;/dependency&gt;
&lt;/pre&gt;&lt;br /&gt;
Создать класс JAXBContextResolver в том же package, где лежит контроллер&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Provider
public final class JAXBContextResolver implements ContextResolver&amp;lt;jaxbcontext&gt; {

    private final JAXBContext context;

    private final Set&amp;lt;class&gt; types;

    private final Class[] cTypes = {MyEntity1.class, MyEntity1.class};

    public JAXBContextResolver() throws Exception {
        this.types = new HashSet(Arrays.asList(cTypes));
        this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), cTypes);
    }

    @Override
    public JAXBContext getContext(Class&amp;lt;?&gt; objectType) {
        return (types.contains(objectType)) ? context : null;
    }
}
&lt;/pre&gt;где MyEntity1, MyEntity2 - отображаемые в JSON обьекты&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
и в контроллере указывать формат данных @Produces(&quot;application/json; charset=utf-8&quot;)&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/1792789222924925523/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/09/restful-jersey-spring-3.html#comment-form' title='Комментарии: 1'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/1792789222924925523'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/1792789222924925523'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/09/restful-jersey-spring-3.html' title='RESTful веб-сервис на Jersey + Spring 3'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-6033034836497507883</id><published>2011-09-07T14:31:00.000-07:00</published><updated>2011-09-15T00:38:54.574-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="scala"/><title type='text'>Scala под windows 7. ошибка при запуске компилятора.</title><content type='html'>После установки Scala 2.9.0 на win 7 столкнулся с проблемой. (С предыдущими версиям scala все нормально)&lt;br /&gt;
&lt;br /&gt;
при запуске команды scalac -version неожиданно вываливается Эксепшн:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;Exception in thread &quot;main&quot; java.lang.NoClassDefFoundError: scala/tools/nsc/MainGenericRunner
Caused by: java.lang.ClassNotFoundException: scala.tools.nsc.MainGenericRunner
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: scala.tools.nsc.MainGenericRunner.  Program will exit.&lt;/pre&gt;&lt;br /&gt;
Начал разбираться в чем проблема. Оказалось, что при запуске scala.bat тоже самое.&lt;br /&gt;
&lt;br /&gt;
Путем трейса файлов scalac.bat и scala.bat установил переменная _SCALA_HOME &lt;br /&gt;
в них неверная:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;_SCALA_HOME c:\Program Files\Files\scala\bin\..&lt;/pre&gt;&lt;br /&gt;
Хотя Переменная среды проставлена правильно:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;c:\Program Files\scala\bin\..&lt;/pre&gt;&lt;br /&gt;
В итоге пришлось в файлах scala.bat и scala.sh исправить строчки:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;:set_home
  set _BIN_DIR=
  rem for %%i in (%~sf0) do set _BIN_DIR=%_BIN_DIR%%%~dpsi
  rem set _SCALA_HOME=%_BIN_DIR%..
  set _SCALA_HOME=%~dps0..
goto :eof&lt;/pre&gt;&lt;br /&gt;
здесь заккоментировал:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;for %%i in (%~sf0) do set _BIN_DIR=%_BIN_DIR%%%~dpsi
set _SCALA_HOME=%_BIN_DIR%..&lt;/pre&gt;&lt;br /&gt;
и добавил &lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;set _SCALA_HOME=%~dps0..&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/6033034836497507883/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/09/scala.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6033034836497507883'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6033034836497507883'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/09/scala.html' title='Scala под windows 7. ошибка при запуске компилятора.'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-7104976363527462945</id><published>2011-08-27T03:25:00.000-07:00</published><updated>2011-10-27T03:43:54.611-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AspectJ"/><category scheme="http://www.blogger.com/atom/ns#" term="IntelliJ IDEA"/><category scheme="http://www.blogger.com/atom/ns#" term="Maven"/><title type='text'>AspectJ + Maven + Spring + IDEA</title><content type='html'>Как заставить работать AspectJ с Maven и Spring.&lt;br /&gt;
&lt;br /&gt;
Подцепим зависимости maven:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;dependency&gt;
    &lt;groupid&gt;org.springframework&lt;/groupId&gt;
    &lt;artifactid&gt;spring-aop&lt;/artifactId&gt;
    &lt;version&gt;${spring.version}&lt;/version&gt;
    &lt;exclusions&gt;
        &lt;exclusion&gt;
            &lt;groupid&gt;org.aspectj&lt;/groupId&gt;
            &lt;artifactid&gt;aspectjweaver&lt;/artifactId&gt;
        &lt;/exclusion&gt;
    &lt;/exclusions&gt;
&lt;/dependency&gt;

&lt;dependency&gt;
    &lt;groupid&gt;org.springframework&lt;/groupId&gt;
    &lt;artifactid&gt;spring-aspects&lt;/artifactId&gt;
    &lt;version&gt;${spring.version}&lt;/version&gt;
    &lt;exclusions&gt;
        &lt;exclusion&gt;
            &lt;groupid&gt;org.aspectj&lt;/groupId&gt;
            &lt;artifactid&gt;aspectjweaver&lt;/artifactId&gt;
        &lt;/exclusion&gt;
    &lt;/exclusions&gt;
&lt;/dependency&gt;

&lt;!-- AspectJ--&gt;

&lt;dependency&gt;
    &lt;groupid&gt;org.aspectj&lt;/groupId&gt;
    &lt;artifactid&gt;aspectjrt&lt;/artifactId&gt;
    &lt;version&gt;${aspectj.version}&lt;/version&gt;
&lt;/dependency&gt;
&lt;/pre&gt;&lt;br /&gt;
Для выполнения aspectj компиляции добавим плагин в maven:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;plugin&gt;
    &lt;groupid&gt;org.codehaus.mojo&lt;/groupId&gt;
    &lt;artifactid&gt;aspectj-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;1.1&lt;/version&gt;
    &lt;configuration&gt;
        &lt;source&gt;1.6&lt;/source&gt;
        &lt;target&gt;1.6&lt;/target&gt;
        &lt;xnoinline&gt;true&lt;/XnoInline&gt;
        &lt;xlint&gt;ignore&lt;/Xlint&gt;
        &lt;aspectlibraries&gt;
            &lt;aspectlibrary&gt;
                &lt;groupid&gt;org.springframework&lt;/groupId&gt;
                &lt;artifactid&gt;spring-aspects&lt;/artifactId&gt;
            &lt;/aspectLibrary&gt;
        &lt;/aspectLibraries&gt;
        &lt;showweaveinfo&gt;false&lt;/showWeaveInfo&gt;
    &lt;/configuration&gt;
    &lt;executions&gt;
        &lt;execution&gt;
            &lt;goals&gt;
                &lt;goal&gt;compile&lt;/goal&gt;
                &lt;goal&gt;test-compile&lt;/goal&gt;
            &lt;/goals&gt;
        &lt;/execution&gt;
    &lt;/executions&gt;
&lt;/plugin&gt;
&lt;/pre&gt;&lt;br /&gt;
Все, проект можно собирать.&lt;br /&gt;
Для выполнения приложения прямо из IDEA надо поставить галку &quot;Run Maven Goal&quot; в Run -&gt; Edit Configurations -&gt; Before Launch и выбрать в ней плагин aspectj:compile</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/7104976363527462945/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/08/aspectj-maven-spring-idea.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/7104976363527462945'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/7104976363527462945'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/08/aspectj-maven-spring-idea.html' title='AspectJ + Maven + Spring + IDEA'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-7211808394428928747</id><published>2011-07-09T05:25:00.000-07:00</published><updated>2011-12-26T07:06:59.115-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Spring"/><title type='text'>Singleton и Prototype scope в Spring</title><content type='html'>Singleton scope означает что экземпляр бина создается один раз, при инициализации контекста. Не стоит сравнивать этот scope со stateless bean в EJB. EJB контейнер при каждом обращении выдает новый экземпляр бина. Поэтому в stateless бине состояние не сохраняется. Таким образом Singleton scope в Spring - тоже statefull. В случае со scope Prototype, можно создавать его новые экземпляры, когда это надо, с помощью фабрики. (statefull)&lt;br /&gt;
&lt;br /&gt;
В обьявлении этих бинов нет ничего сложного:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;bean id=&quot;prototypeBean&quot; class=&quot;com.foo.PrototypeBean&quot; scope=&quot;prototype&quot;&gt;&lt;/bean&gt;
&lt;bean id=&quot;singletonBean&quot; class=&quot;com.foo.SingletonBean&quot; scope=&quot;singleton&quot;/&gt;&lt;/bean&gt;
&lt;/pre&gt;&lt;br /&gt;
Но проблема появляется, когда нужна зависимость SingletonBean от PrototypeBean. В этом случае можно поступить несколькими способами:&lt;br /&gt;
ApplicationContextAware или BeanNameAware method injection; Lookup method injection; Arbitrary method replacement. &lt;br /&gt;
Расскажу о самом простом (по крайней мере для меня) из них - аналоге BeanNameAware.&lt;br /&gt;
&lt;br /&gt;
PrototypeBean может представлять из себя что угодно. В данном контексте нам это не важно, так что будем рассматривать его просто как POJO класс:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class PrototypeBean {
...
}
&lt;/pre&gt;&lt;br /&gt;
а в SingletonBean используем фабрику org.springframework.beans.factory.ObjectFactory:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class SingletonBean {

  private ObjectFactory factory;

  public void createPrototypeBean() {
     //здесь можем получить сколько угодно экземпляров PrototypeBean
     PrototypeBean bean = factory.getObject();
  }

  ...

  public void setFactory(ObjectFactory beanFactory) throws BeansException {
     this.factory = beanFactory;
  }
}
&lt;/pre&gt;&lt;br /&gt;
Чтобы явно указать ObjectFactory экземпляр какого бина создавать, в конфигурации пропишем ObjectFactory как property Singleton-бина:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;bean id=&quot;prototypeBean&quot; class=&quot;com.foo.PrototypeBean&quot; scope=&quot;prototype&quot;&gt;&lt;/bean&gt;

&lt;bean id=&quot;singletonBean&quot; class=&quot;com.foo.SingletonBean&quot;&gt;
  &lt;property name=&quot;factory&quot;&gt;
    &lt;bean class=   &quot;org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean&quot;&gt;
      &lt;property name=&quot;targetBeanName&quot;&gt;
        &lt;idref local=&quot;prototypeBean&quot; /&gt;
      &lt;/property&gt;
    &lt;/bean&gt;
  &lt;/property&gt;
&lt;/bean&gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/7211808394428928747/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/07/singleton-prototype-scope-spring.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/7211808394428928747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/7211808394428928747'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/07/singleton-prototype-scope-spring.html' title='Singleton и Prototype scope в Spring'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total><georss:featurename>город Видное, Московская область, Россия</georss:featurename><georss:point>55.547669289580419 37.708167654785143</georss:point><georss:box>55.52722028958042 37.641665654785143 55.568118289580418 37.774669654785143</georss:box></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-70427793814265526</id><published>2011-06-25T05:59:00.000-07:00</published><updated>2012-04-03T13:01:53.994-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="Tomcat"/><title type='text'>Установка Tomcat под Ubuntu</title><content type='html'>Для начала установливаем openjdk вместе с пакетом ubuntu-restricted-extras:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo apt-get install ubuntu-restricted-extras&lt;/pre&gt;установленная версия: 1.06_22&lt;br /&gt;
&lt;br /&gt;
качаем томкат:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;wget http://apache.cyberuse.com/tomcat/tomcat-7/v7.0.16/bin/apache-tomcat-7.0.16.tar.gz&lt;/pre&gt;&lt;br /&gt;
распаковываем: &lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;tar xvzf apache-tomcat-7.0.16.tar.gz&lt;/pre&gt;&lt;br /&gt;
копируем в нужную папку: &lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo mv apache-tomcat-7.0.16 /usr/local/tomcat&lt;/pre&gt;&lt;br /&gt;
также необходимо прописать переменные окружения JAVA_HOME и JDK_HOME. Для этого добавляем в файле /etc/environment:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;JDK_HOME=&quot;/usr/lib/jvm/java-6-openjdk&quot;
JAVA_HOME=&quot;/usr/lib/jvm/java-6-openjdk&quot;&lt;/pre&gt;&lt;br /&gt;
запускаем томкат: &lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo /usr/local/tomcat/bin/catalina.sh start&lt;/pre&gt;&lt;br /&gt;
редактируем server.xml: &lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo nano /usr/local/tomcat/conf/server.xml&lt;/pre&gt;&lt;br /&gt;
ищем следующий текст:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;connector port=&quot;8080&quot; 
protocol=&quot;HTTP/1.1&quot; connectiontimeout=&quot;20000&quot; redirectport=&quot;8443&quot;&gt;&lt;/connector&gt;&lt;/pre&gt;&lt;br /&gt;
меняем порт на стандартный для http - 80, и указываем кодировку для URI:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;connector port=&quot;80&quot; 
protocol=&quot;HTTP/1.1&quot; connectiontimeout=&quot;20000&quot; redirectport=&quot;8443&quot; URIEncoding=&quot;UTF-8&quot;&gt;&lt;/connector&gt;&lt;/pre&gt;&lt;br /&gt;
создаем файл автозагрузки&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo nano /etc/init.d/tomcat&lt;/pre&gt;&lt;br /&gt;
и вставляем следующее:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;# Tomcat auto-start
#
# description: Auto-starts tomcat
# processname: tomcat
# pidfile: /var/run/tomcat.pid

export JAVA_HOME=/usr/lib/jvm/java-6-openjdk

case $1 in
start)
       sh /usr/local/tomcat/bin/startup.sh
       ;;
stop)  
       sh /usr/local/tomcat/bin/shutdown.sh
       ;;
restart)
       sh /usr/local/tomcat/bin/shutdown.sh
       sh /usr/local/tomcat/bin/startup.sh
       ;;
esac   
exit 0
&lt;/pre&gt;&lt;br /&gt;
далее сделаем этот скрипт запускаемым:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo chmod 755 /etc/init.d/tomcat&lt;/pre&gt;&lt;br /&gt;
для проверки работы запустим tomcat:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo /etc/init.d/tomcat start&lt;/pre&gt;&lt;br /&gt;
сервер должен запуститься на 80 порту. Для остановки используем следующую команду:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo /etc/init.d/tomcat stop&lt;/pre&gt;&lt;br /&gt;
создадим ссылки на скрипт для автоматического запуска и останова:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo update-rc.d tomcat defaults&lt;/pre&gt;&lt;br /&gt;
перезагружаем сервер:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo shutdown -r now&lt;/pre&gt;&lt;br /&gt;
в конце надо не забыть создать пользователя tomcat с ролями admin-gui и manager-gui в conf\tomcat-users.xml:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;role rolename=&quot;manager-gui&quot;&gt;&lt;/role&gt;
&lt;role rolename=&quot;admin-gui&quot;&gt;&lt;/role&gt;
&lt;user username=&quot;tomcat&quot; password=&quot;wwwww&quot; roles=&quot;manager-gui,admin-gui&quot;&gt;&lt;/user&gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/70427793814265526/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/06/tomcat-ubuntu.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/70427793814265526'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/70427793814265526'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/06/tomcat-ubuntu.html' title='Установка Tomcat под Ubuntu'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-6648091618576846413</id><published>2011-06-09T05:10:00.001-07:00</published><updated>2011-09-07T15:22:38.093-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java core"/><category scheme="http://www.blogger.com/atom/ns#" term="multi-threading"/><title type='text'>Double checked locking</title><content type='html'>Шаблон проектирования &quot;Блокировка с двойной проверкой&quot; используется в многопоточном программировании. Это один из излюбленных вопросов на собеседованиях. Звучит он обычно как просьба написать синглетон, корректно работающий в многопоточном режиме.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим принцип паттерна на примере Синглетона.&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;// Не работает в Java 1.4 и более ранних версиях из-за семантики volatile
class Foo {
  private volatile Helper helper = null;  

  public Helper getHelper() {
    if (helper == null) {          //блок проверки, для ускорения производительности
      synchronized(this) {         //блок синхронизации
        if (helper == null)        //если обьект еще не создан, то создаем его
          helper = new Helper();
      }
    }
    return helper;
  }
}
&lt;/pre&gt;&lt;br /&gt;
Первый блок проверки нужен для того, чтобы при инициализированной переменной не блокировать участок кода, тем самым ускорить процесс выполнения программы. Внутренняя проверка служит для проверки, инициализирована ли переменная, чтобы в последуюущих случаях обращения к ней после инициализации выдавался уже созданный ее экземпляр. Блок синхронизации разделяет доступ потоков к коду, инициализирующему переменную.&lt;br /&gt;
&lt;br /&gt;
Модификатор volatile появился начиная с версии Java 1.5. Он позволяет корректно обработать запись в переменную в многопоточном режиме.</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/6648091618576846413/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/06/double-checked-locking.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6648091618576846413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6648091618576846413'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/06/double-checked-locking.html' title='Double checked locking'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-3221840868535786274</id><published>2011-05-11T05:05:00.000-07:00</published><updated>2011-09-07T15:28:15.319-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design Patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="java core"/><title type='text'>Typesafe Enum pattern или как обойтись без Enum-ов.</title><content type='html'>Часто нужда в использовании Enum возникает в случае, если необходимо передать в метод одно из значений, например &quot;green&quot;, &quot;red&quot; или &quot;blue&quot;. Первое что приходит в голову - это принимать String:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public void method(String param) {...}
&lt;/pre&gt;&lt;br /&gt;
Но в таком случае в качестве параметра может быть принята любая строка. В соответствии с принципом, что все потенциальные ошибки по возможности надо переносить на момент компиляции, такой вариант неприемлем. Тут и приходит на помощь Enum:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public enum TypesafeEnum {GREEN, RED, BLUE};
&lt;/pre&gt;&lt;br /&gt;
А можно ли обойтись без него? Конечно можно, ведь Enum появились только с java 1.5. Тут нам может помочь паттерн Typesafe Enum:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class TypesafeEnum {

  private final String name;

  private TypesafeEnum(String name) {
    this.name = name;
  }

  public static final TypesafeEnum GREEN = new TypesafeEnum(&quot;green&quot;);
  public static final TypesafeEnum RED = new TypesafeEnum(&quot;red&quot;);
  public static final TypesafeEnum BLUE = new TypesafeEnum(&quot;blue&quot;);

  public String toString() {
    return name;
  }
}
&lt;/pre&gt;Теперь можно обьявить наш метод таким образом:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public void method(TypesafeEnum param) {...}
&lt;/pre&gt;соответственно его вызов: &lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;someObject.method(TypesafeEnum.RED);
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://java.sun.com/developer/technicalArticles/releases/j2se15langfeat/index.html&quot;&gt;Подробнее о паттерне здесь&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/3221840868535786274/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/05/typesafe-enum-pattern-enum.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/3221840868535786274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/3221840868535786274'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/05/typesafe-enum-pattern-enum.html' title='Typesafe Enum pattern или как обойтись без Enum-ов.'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-2944840689698280050</id><published>2011-04-15T06:21:00.000-07:00</published><updated>2011-09-07T15:30:13.591-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design Patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="Relational DB"/><title type='text'>Паттерн Entity-Attribute-Value (EAV)</title><content type='html'>Паттерн &quot;Entity-Attribute-Value&quot; может пригодиться при проектировании базы данных товаров. Рассмотрим пример на СУБД Oracle.&lt;br /&gt;
&lt;br /&gt;
В простейшем случае структура базы данных будет выглядеть следующим образом:&lt;br /&gt;
&lt;pre class=&quot;sql&quot; name=&quot;code&quot;&gt;-- Create table
create table entity
(
  entity_id number,
  name      varchar2(50)
);
-- Create/Recreate primary, unique and foreign key constraints 
alter table entity
  add constraint xpk_entity_id primary key (ENTITY_ID);
&lt;/pre&gt;Таблица Entity хранит сами сущности - товары. В качестве полей указываем общие свойства сущностей, таких как Название товара&lt;br /&gt;
&lt;pre class=&quot;sql&quot; name=&quot;code&quot;&gt;-- Create table
create table attribute
(
  attribute_id   number,
  attribute_name varchar2(50),
  attribute_type varchar2(10),
  decriptions    clob
);
-- Create/Recreate primary, unique and foreign key constraints 
alter table attribute
  add constraint xpk_attribute_id primary key (ATTRIBUTE_ID);
&lt;/pre&gt;Таблица Attribute хранит различные свойства товаров - атрибуты. В качестве полей указываем название атрибута, тип.&lt;br /&gt;
&lt;pre class=&quot;sql&quot; name=&quot;code&quot;&gt;-- Create table
create table value
(
  attribute_id   number,
  entity_id      number,
  string_value   varchar2(100),
  number_value   number
);
&lt;/pre&gt;таблица value - для хранения значений атрибутов, а также для связи многие ко многим между товарами и их атрибутами.&lt;br /&gt;
&lt;br /&gt;
Реализация разных типов данных может быть реализована различными способами. Например вместо одного поля value можно создать разные поля под разные типы данных: string_value, number_value и использовать нужное исходя из типа атрибута из таблицы attribute.&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Entity-Attribute-Value_model&quot;&gt;Более подробная информация по паттерну&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/2944840689698280050/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/04/entity-attribute-value-eav.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/2944840689698280050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/2944840689698280050'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/04/entity-attribute-value-eav.html' title='Паттерн Entity-Attribute-Value (EAV)'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-8743472178486630987</id><published>2011-04-09T08:13:00.000-07:00</published><updated>2011-11-20T23:26:09.760-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java core"/><category scheme="http://www.blogger.com/atom/ns#" term="ORM"/><category scheme="http://www.blogger.com/atom/ns#" term="reflect"/><title type='text'>Simple ORM</title><content type='html'>Наверное многие начинающие java программисты задумывались над тем, как неудобно писать слой взаимодейстия с базой данных на чистом JDBC. Ctrl+c, Ctrl+v и изменение названия таблиц и параметров. Все это приводит к излишнему дублированию кода. Конечно можно сразу взять тот же Hibernate или любую другую реализацию JPA. Но для небольших и простых проектов, имхо это как &quot;из пушки по воробьям&quot;. К тому же считаю что надо один раз написать ORM самому, чтобы понять основы его работы.&lt;br /&gt;
&lt;br /&gt;
В этой статье рассмотрим создание своего простого ORM на примере работы с СУБД Oracle.&lt;br /&gt;
&lt;br /&gt;
Создадим интерфейс Persistence и реализующий его класс PersistenceOraImpl - собственно сам персистенс Api для работы с БД. &lt;br /&gt;
&lt;br /&gt;
Список методов в Persistence:&lt;br /&gt;
&lt;br /&gt;
1. selectAll - выбирает все записи из таблицы;&lt;br /&gt;
2. select - выбирает записи по заданным параметрам;&lt;br /&gt;
3. selectRow - выбирает одну запись по заданным параметрам;&lt;br /&gt;
4. insert - вставляет запись;&lt;br /&gt;
5. update - обновляет запись;&lt;br /&gt;
6. delete - удаляет запись.&lt;br /&gt;
&lt;br /&gt;
Сам интерфейс выглядит так:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public interface Persistence {

 public List selectAll(Class&amp;lt;?&gt; clazz);

 public List select(Class&amp;lt;?&gt; clazz, Map&amp;lt;String, Object&gt; params);

 public Object selectRow(Class&amp;lt;?&gt; clazz, Map&amp;lt;String, Object&gt; params);

 public void insert(Object obj);

 public void update(Object obj);

 public void delete(Class&amp;lt;?&gt; clazz, Map&amp;lt;String, Object&gt; params);

 public Connection getConnection();

 public void setConnection(Connection conn);
}
&lt;/pre&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Имплементим методы в классе PersistenceOraImpl.&lt;br /&gt;
&lt;br /&gt;
selectAll:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Override
@Override
public List selectAll(Class&amp;lt;?&gt; clazz) {

 try {

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    &quot;select t.* from &quot; + PersistenceHelper.defineTable(clazz) + &quot; t&quot;);

  OracleResultSet orset = (OracleResultSet) stmt.executeQuery();
  List treeList = new ArrayList();

  while (orset.next()) {

   Constructor constructor = clazz.getConstructor(null);
   Object somethingInstance = constructor.newInstance(null);
   Field[] fields = clazz.getDeclaredFields();

   Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; mapFields = PersistenceHelper.defineFields(clazz);

   /*выполняем методы set...()*/
   for (Integer i = 1; i &lt;= mapFields.size(); i++) {
    String s = fields[i - 1].getName();
    s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

    Method method = clazz.getMethod(&quot;set&quot; + s, mapFields.get(i));
    method.invoke(somethingInstance, PersistenceHelper.getSqlValue(orset, mapFields.get(i), i));
   }

   treeList.add(somethingInstance);
  }
  orset.close();
  stmt.close();

  return treeList;

 } catch (Exception ex) {
  ex.printStackTrace();
  return nullArray;
 }
}
&lt;/pre&gt;
select:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Override
public List select(Class&amp;lt;?&gt; clazz, Map&amp;lt;String, Object&gt; params) {
 try {

  String sSql = &quot;select t.* from &quot; + PersistenceHelper.defineTable(clazz) + &quot; t &quot;;
  String sSql1 = &quot;where &quot;;

  Integer j = 1;
  for (String key : params.keySet()) {
   if (key.equals(&quot;period&quot;)) {
    sSql1 += &quot; to_char(t.period,&#39;MM.yyyy&#39;) = to_char(?,&#39;MM.yyyy&#39;) &quot;;
   } else if (key.substring(key.length() - 1).equals(&quot;&gt;&quot;)) {
    sSql1 += key + &quot;= ?&quot;;
   } else if (key.substring(key.length() - 1).equals(&quot;&lt;&quot;)) {
    sSql1 += key + &quot;= ?&quot;;
   } else {
    sSql1 += key + &quot; = ?&quot;;
   }

   if (j++ &lt; params.size()) {
    sSql1 += &quot; and &quot;;
   }
  }

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1);

  System.out.println(&quot;select: &quot; + sSql + sSql1);

  j = 1;
  for (String key : params.keySet()) {
   PersistenceHelper.setSqlValue(stmt, params.get(key).getClass(), j++, params.get(key));
  }

  OracleResultSet orset = (OracleResultSet) stmt.executeQuery();
  List treeList = new ArrayList();

  while (orset.next()) {

   Constructor constructor = clazz.getConstructor(null);
   Object somethingInstance = constructor.newInstance(null);
   Field[] fields = clazz.getDeclaredFields();

   Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; mapFields = PersistenceHelper.defineFields(clazz);

   /*выполняем методы set...()*/
   for (Integer i = 1; i &amp;lt;= mapFields.size(); i++) {
    String s = fields[i - 1].getName();
    s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

    Method method = clazz.getMethod(&quot;set&quot; + s, mapFields.get(i));
    method.invoke(somethingInstance, PersistenceHelper.getSqlValue(orset, mapFields.get(i), i));
   }

   treeList.add(somethingInstance);
  }
  orset.close();
  stmt.close();

  return treeList;

 } catch (Exception ex) {
  ex.printStackTrace();
  return nullArray;
 }
}
&lt;/pre&gt;selectRow:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Override
public Object selectRow(Class&amp;lt;?&gt; clazz, Map&amp;lt;String, Object&gt; params) {

 try {

  String sSql = &quot;select t.* from &quot; + PersistenceHelper.defineTable(clazz) + &quot; t &quot;;
  String sSql1 = &quot; where &quot;;

  Integer j = 1;
  for (String key : params.keySet()) {
   if (key.equals(&quot;period&quot;)) {
    sSql1 += &quot; to_char(t.period,&#39;MM&#39;) = to_char(?,&#39;MM&#39;) &quot;;
   } else {
    sSql1 += key + &quot; = ? &quot;;
   }

   if (j++ &amp;lt; params.size()) {
    sSql1 += &quot; and &quot;;
   }
  }

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1);

  System.out.println(&quot;selectRow: &quot; + sSql + sSql1);
  j = 1;
  for (String key : params.keySet()) {
   PersistenceHelper.setSqlValue(stmt, params.get(key).getClass(), j++, params.get(key));
  }

  OracleResultSet orset = (OracleResultSet) stmt.executeQuery();
  List treeList = new ArrayList();

  while (orset.next()) {
   Constructor constructor = clazz.getConstructor(null);
   Object somethingInstance = constructor.newInstance(null);
   Field[] fields = clazz.getDeclaredFields();

   Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; mapFields = PersistenceHelper.defineFields(clazz);

   /*выполняем методы set...()*/
   for (Integer i = 1; i &lt;= mapFields.size(); i++) {
    String s = fields[i - 1].getName();
    s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

    Method method = clazz.getMethod(&quot;set&quot; + s, mapFields.get(i));
    method.invoke(somethingInstance, PersistenceHelper.getSqlValue(orset, mapFields.get(i), i));
   }

   treeList.add(somethingInstance);
  }

  orset.close();
  stmt.close();

  if (treeList.size() &gt; 0) {
   return treeList.get(0);
  } else {
   Constructor constructor = clazz.getConstructor(null);
   return constructor.newInstance(null);
  }

 } catch (Exception ex) {
  ex.printStackTrace();
  return new Object();
 }
}
&lt;/pre&gt;insert:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Override
public void insert(Object obj) {

 try {

  Class&amp;lt;?&gt; clazz = obj.getClass();

  Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; mapFields = PersistenceHelper.defineFields(clazz);
  Map&amp;lt;Integer, String&gt; mapFieldNames = PersistenceHelper.defineFieldNames(clazz);
  Field[] fields = clazz.getDeclaredFields();

  String sSql = &quot;insert into &quot; + PersistenceHelper.defineTable(clazz) + &quot; t &quot;;
  String sSql1 = &quot;(&quot;;
  String sSql2 = &quot;) values (&quot;;

  for (int i = 1; i &amp;lt;= mapFieldNames.size(); i++) {
   if (i &amp;lt; mapFieldNames.size()) {
    sSql1 += mapFieldNames.get(i) + &quot;,&quot;;
    sSql2 += &quot;?,&quot;;
   } else {
    sSql1 += mapFieldNames.get(i);
    sSql2 += &quot;?&quot;;
   }
  }

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1 + sSql2 + &quot;)&quot;);

  /*выполняем методы get...()*/
  for (Integer i = 1; i &amp;lt;= mapFields.size(); i++) {
   String s = fields[i - 1].getName();
   s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());

   Method method = clazz.getMethod(&quot;get&quot; + s);
   Object o = method.invoke(obj);
   PersistenceHelper.setSqlValue(stmt, mapFields.get(i), i, o);
  }

  stmt.executeUpdate();

  stmt.close();

 } catch (Exception ex) {
  ex.printStackTrace();
 }

}
&lt;/pre&gt;update:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Override
public void update(Object obj) {

 try {

  Class&amp;lt;?&gt; clazz = obj.getClass();

  Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; mapFields = PersistenceHelper.defineFields(clazz);
  Map&amp;lt;Integer, String&gt; mapFieldNames = PersistenceHelper.defineFieldNames(clazz);
  Field[] fields = clazz.getDeclaredFields();

  String sSql = &quot;update &quot; + PersistenceHelper.defineTable(clazz) + &quot; t set &quot;;
  String sSql1 = &quot;&quot;;

  for (int i = 1; i &amp;lt;= mapFieldNames.size(); i++) {
   if (i &amp;lt; mapFieldNames.size()) {
    sSql1 += mapFieldNames.get(i) + &quot; = ? , &quot;;
   } else {
    sSql1 += mapFieldNames.get(i) + &quot; = ? &quot;;
   }
  }

  /*привяжем условие по первому полю. обычно это id*/
  sSql1 += &quot; where &quot; + mapFieldNames.get(1) + &quot; = ?&quot;;

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1);

  /*выполняем методы get...()*/
  for (Integer i = 1; i &amp;lt;= mapFields.size(); i++) {
   String s = fields[i - 1].getName();
   s = s.substring(0, 1).toUpperCase() + s.substring(1, s.length());


   Method method = clazz.getMethod(&quot;get&quot; + s);
   Object o = method.invoke(obj);

   PersistenceHelper.setSqlValue(stmt, mapFields.get(i), i, o);

   /*привяжем переменную where*/
   if (i == 1) {
    PersistenceHelper.setSqlValue(stmt, mapFields.get(i), mapFields.size() + 1, o);
   }
  }


  stmt.executeUpdate();
  stmt.close();

 } catch (Exception ex) {
  ex.printStackTrace();
 }
}
&lt;/pre&gt;delete:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;@Override
public void delete(Class&amp;lt;?&gt; clazz, Map&amp;lt;String, Object&gt; params) {
 try {

  String sSql = &quot;delete from &quot; + PersistenceHelper.defineTable(clazz) + &quot; t &quot;;
  String sSql1 = &quot; where &quot;;

  Integer j = 1;
  for (String key : params.keySet()) {
   if (key.equals(&quot;period&quot;)) {
    sSql1 += &quot; to_char(t.period,&#39;MM&#39;) = to_char(?,&#39;MM&#39;) &quot;;
   } else {
    sSql1 += key + &quot; = ? &quot;;
   }

   if (j++ &amp;lt; params.size()) {
    sSql1 += &quot; and &quot;;
   }
  }

  OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(
    sSql + sSql1);

  j = 1;
  for (String key : params.keySet()) {
   PersistenceHelper.setSqlValue(stmt, params.get(key).getClass(), j++, params.get(key));
  }

  stmt.executeUpdate();
  stmt.close();

 } catch (Exception ex) {
  ex.printStackTrace();
 }
}
&lt;/pre&gt;Остальная часть класса:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class PersistenceOraImpl implements Persistence {

 private static final List nullArray = new ArrayList();

 private OracleConnection conn;

 public PersistenceOraImpl(OracleConnection conn) {
  setConnection(conn);
 }
 
 /* методы CRUD 
  ...
 */
 
 @Override
 public OracleConnection getConnection() {
  return conn;
 }

 @Override
 public void setConnection(Connection conn) {
  this.conn = (OracleConnection) conn;
 }
 
&lt;/pre&gt;В методах используется вспомогательный класс PersistenceHelper:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;public class PersistenceHelper {


 /**
  * Возвращает название таблицы из аннотации
  *
  * @param clazz тип передаваемого класса
  * @return oracle String.
  */
 public static String defineTable(Class&lt;?&gt; clazz) {
  String table;

  if (clazz.isAnnotationPresent(OraDataTable.class)) {
   table = clazz.getAnnotation(OraDataTable.class).value();
  } else {
   throw new IllegalStateException(clazz.getName() + &quot; must be @OraDataTable&quot;);
  }
  return table.toUpperCase();
 }

 /**
  * Возвращает названия и типы полей
  *
  * @param clazz тип передаваемого класса
  * @return oracle Map&lt;String,Integer&gt;.
  */
 public static Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; defineFields(Class&amp;lt;?&gt; clazz) {
  Map&amp;lt;Integer, Class&amp;lt;?&gt;&gt; map = new HashMap&amp;lt;Integer, Class&amp;lt;?&gt;&gt;();

  Field[] fields = clazz.getDeclaredFields();
  for (Field field : fields) {
   if (field.isAnnotationPresent(OraInteger.class)) {
    map.put(field.getAnnotation(OraInteger.class).value(), Integer.class);
   } else if (field.isAnnotationPresent(OraString.class)) {
    map.put(field.getAnnotation(OraString.class).value(), String.class);
   } else if (field.isAnnotationPresent(OraDate.class)) {
    map.put(field.getAnnotation(OraDate.class).value(), Date.class);
   } else if (field.isAnnotationPresent(OraTimestamp.class)) {
    map.put(field.getAnnotation(OraTimestamp.class).value(), Timestamp.class);
   } else if (field.isAnnotationPresent(OraBigDecimal.class)) {
    map.put(field.getAnnotation(OraBigDecimal.class).value(), BigDecimal.class);
   } else if (field.isAnnotationPresent(OraClob.class)) {
    map.put(field.getAnnotation(OraClob.class).value(), Clob.class);
   } else if (field.isAnnotationPresent(OraBlob.class)) {
    map.put(field.getAnnotation(OraBlob.class).value(), Blob.class);
   }
  }

  return map;
 }

 public static Map&amp;lt;Integer, String&gt; defineFieldNames(Class&amp;lt;?&gt; clazz) {
  Map&amp;lt;Integer, String&gt; map = new HashMap&amp;lt;Integer, String&gt;();

  Field[] fields = clazz.getDeclaredFields();
  for (Field field : fields) {
   if (field.isAnnotationPresent(OraInteger.class)) {
    map.put(field.getAnnotation(OraInteger.class).value(),
      field.getAnnotation(OraInteger.class).field());
   } else if (field.isAnnotationPresent(OraString.class)) {
    map.put(field.getAnnotation(OraString.class).value(),
      field.getAnnotation(OraString.class).field());
   } else if (field.isAnnotationPresent(OraDate.class)) {
    map.put(field.getAnnotation(OraDate.class).value(),
      field.getAnnotation(OraDate.class).field());
   } else if (field.isAnnotationPresent(OraTimestamp.class)) {
    map.put(field.getAnnotation(OraTimestamp.class).value(),
      field.getAnnotation(OraTimestamp.class).field());
   } else if (field.isAnnotationPresent(OraBigDecimal.class)) {
    map.put(field.getAnnotation(OraBigDecimal.class).value(),
      field.getAnnotation(OraBigDecimal.class).field());
   } else if (field.isAnnotationPresent(OraClob.class)) {
    map.put(field.getAnnotation(OraClob.class).value(),
      field.getAnnotation(OraClob.class).field());
   } else if (field.isAnnotationPresent(OraBlob.class)) {
    map.put(field.getAnnotation(OraBlob.class).value(),
      field.getAnnotation(OraBlob.class).field());
   }
  }

  return map;
 }

 public static Object getSqlValue(OracleResultSet orset, Class&amp;lt;?&gt; oraType, Integer i) throws SQLException {
  if (oraType.getName().equals(&quot;java.lang.Integer&quot;)) {
   return orset.getInt(i);
  } else if (oraType.getName().equals(&quot;java.lang.String&quot;)) {
   return orset.getString(i);
  } else if (oraType.getName().equals(&quot;java.sql.Date&quot;)) {
   return orset.getDate(i);
  } else if (oraType.getName().equals(&quot;java.sql.Timestamp&quot;)) {
   return orset.getTimestamp(i);
  } else if (oraType.getName().equals(&quot;java.math.BigDecimal&quot;)) {
   return orset.getBigDecimal(i);
  } else if (oraType.getName().equals(&quot;java.sql.Clob&quot;)) {
   return orset.getClob(i);
  } else if (oraType.getName().equals(&quot;java.sql.Blob&quot;)) {
   return orset.getBlob(i);
  } else {
   return null;
  }
 }

 public static void setSqlValue(OraclePreparedStatement stmt, Class&amp;lt;?&gt; oraType, Integer i, Object val) throws SQLException, Exception {
  if (oraType.getName().equals(&quot;java.lang.Integer&quot;)) {
   stmt.setInt(i, (Integer) (val == null ? 0 : val));
  } else if (oraType.getName().equals(&quot;java.lang.String&quot;)) {
   stmt.setString(i, (String) val);
  } else if (oraType.getName().equals(&quot;java.sql.Date&quot;)) {
   stmt.setDate(i, (Date) val);
  } else if (oraType.getName().equals(&quot;java.sql.Timestamp&quot;)) {
   stmt.setTimestamp(i, (Timestamp) val);
  } else if (oraType.getName().equals(&quot;java.math.BigDecimal&quot;)) {
   stmt.setBigDecimal(i, (BigDecimal) val);
  } else if (oraType.getName().equals(&quot;java.sql.Clob&quot;)) {
   stmt.setClob(i, (Clob) val);
  } else if (oraType.getName().equals(&quot;java.sql.Blob&quot;)) {
   stmt.setBlob(i, (Blob) val);
  } else {
   throw new Exception(&quot;error in setSqlValue. Unknown type: &quot; + oraType.getName());
  }
 }

 public static void setStatementValue(OracleCallableStatement ocs, String key, Class&amp;lt;?&gt; oraType, Integer i, Object val) throws SQLException, Exception {
  if (key.equals(&quot;out&quot;)) {
   if (oraType.getName().equals(&quot;java.lang.Integer&quot;)) {
    ocs.registerOutParameter(1, OracleTypes.INTEGER);
   } else if (oraType.getName().equals(&quot;java.lang.String&quot;)) {
    ocs.registerOutParameter(1, OracleTypes.VARCHAR);
   } else if (oraType.getName().equals(&quot;java.sql.Date&quot;)) {
    ocs.registerOutParameter(1, OracleTypes.DATE);
   } else if (oraType.getName().equals(&quot;java.sql.Timestamp&quot;)) {
    ocs.registerOutParameter(1, OracleTypes.TIMESTAMP);
   } else if (oraType.getName().equals(&quot;java.math.BigDecimal&quot;)) {
    ocs.registerOutParameter(1, OracleTypes.NUMBER);
   } else if (oraType.getName().equals(&quot;java.sql.Clob&quot;)) {
    ocs.registerOutParameter(1, OracleTypes.CLOB);
   } else if (oraType.getName().equals(&quot;java.sql.Blob&quot;)) {
    ocs.registerOutParameter(1, OracleTypes.BLOB);
   } else if (oraType.getName().equals(&quot;java.sql.Array&quot;)) {
    ocs.registerOutParameter(1, OracleTypes.ARRAY);
   } else {
    throw new Exception(&quot;error in setStatementValue. Unknown out type: &quot; + oraType.getName());
   }
  } else {
   if (oraType.getName().equals(&quot;java.lang.Integer&quot;)) {
    ocs.setInt(i, (Integer) val);
   } else if (oraType.getName().equals(&quot;java.lang.String&quot;)) {
    ocs.setString(i, (String) val);
   } else if (oraType.getName().equals(&quot;java.sql.Date&quot;)) {
    ocs.setDate(i, (Date) val);
   } else if (oraType.getName().equals(&quot;java.sql.Timestamp&quot;)) {
    ocs.setTimestamp(i, (Timestamp) val);
   } else if (oraType.getName().equals(&quot;java.math.BigDecimal&quot;)) {
    ocs.setBigDecimal(i, (BigDecimal) val);
   } else if (oraType.getName().equals(&quot;java.sql.Clob&quot;)) {
    ocs.setClob(i, (Clob) val);
   } else if (oraType.getName().equals(&quot;java.sql.Blob&quot;)) {
    ocs.setBlob(i, (Blob) val);
   } else if (oraType.getName().equals(&quot;java.sql.Array&quot;)) {
    ocs.setArray(i, (Array) val);
   } else {
    throw new Exception(&quot;error in setStatementValue. Unknown type: &quot; + oraType.getName());
   }
  }
 }

 public static Object getStatementValue(OracleCallableStatement ocs, Class&amp;lt;?&gt; oraType, Integer i) throws SQLException, Exception {
  if (oraType.getName().equals(&quot;java.lang.Integer&quot;)) {
   return ocs.getInt(1);
  } else if (oraType.getName().equals(&quot;java.lang.String&quot;)) {
   return ocs.getString(i);
  } else if (oraType.getName().equals(&quot;java.util.Date&quot;)) {
   return ocs.getDate(1);
  } else if (oraType.getName().equals(&quot;java.sql.Timestamp&quot;)) {
   return ocs.getTimestamp(1);
  } else if (oraType.getName().equals(&quot;java.math.BigDecimal&quot;)) {
   return ocs.getBigDecimal(1);
  } else if (oraType.getName().equals(&quot;java.sql.Clob&quot;)) {
   return ocs.getClob(1);
  } else if (oraType.getName().equals(&quot;java.sql.Blob&quot;)) {
   return ocs.getBlob(1);
  } else if (oraType.getName().equals(&quot;java.sql.Array&quot;)) {
   return ocs.getArray(1);
  } else {
   throw new Exception(&quot;error in setStatementValue. Unknown out type: &quot; + oraType.getName());
  }
 }
}
&lt;/pre&gt;Аннотации для обработки entity с помощью reflection:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;/**
 * Аннотация класса.
 */
@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraDataTable {
 /**
  * @return oracle table.
  */
 String value();
}

/**
 * Аннотация аттрибута класса.
 * для конвертации oracle.sql.Int в объект Integer.
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraInteger {
 /**
  * @return oracle Integer.
  */
 int value();

 String field();

}

/**
 * Аннотация аттрибута класса.
 * для конвертации oracle.sql.String в объект String.
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraString {
 /**
  * @return oracle String.
  */
 int value();

 String field();

}

/**
 * Аннотация аттрибута класса.
 * для конвертации oracle.sql.Int в объект Integer.
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraBigDecimal {
 /**
  * @return oracle Integer.
  */
 int value();

 String field();
}

/**
 * Аннотация аттрибута класса.
 * для конвертации oracle.sql.Int в объект Integer.
 */
@Target(value = ElementType.FIELD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface OraDate {
 /**
  * @return oracle Integer.
  */
 int value();

 String field();
}
&lt;/pre&gt;С другими типами аннотации аналогичны.

Теперь с помощью созданных аннотаций можно создать обьект-сущность. Из определения ORM (Object-relational mapping) следует что это отображение Java-обьектов в реляционный вид.
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;/**
 *  Обьект-сущность
 */
@OraDataTable(&quot;my_table&quot;)
public class MyTable {

 @OraInteger(value = 1, field = &quot;id&quot;)
 private Integer id;

 @OraString(value = 2, field = &quot;name&quot;)
 private Integer periodType;
 
 /* и т.д. */
 
 public String getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }
 
 /* и т.д. */

}
&lt;/pre&gt;после этого можно проводить операции с этой сущностью в базе данных:
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;/*достанем все записи из таблицы my_table*/
public List&amp;lt;MyTable&gt; getAllRecords() {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();  
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
  
  List&amp;lt;MyTable&gt; resultList = persistence.selectAll(CalcPeriod.class);
  
  conn.close();
  return resultList;
 } catch (SQLException e) {
  e.printStackTrace();
  return nullArray;
 }
}

/*достанем несколько записей из таблицы my_table по условию*/
public List&amp;lt;MyTable&gt; getListRecords(MyTable entity) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
  
  Map&amp;lt;String, Object&gt; params = new HashMap&amp;lt;String, Object&gt;();
  if (entity.getId() != null) params.put(&quot;id&quot;, entity.getId());
  
  List&amp;lt;MyTable&gt; resultList = persistence.select(entity.getClass(), params);
  
  conn.close();
  return resultList;
 } catch (SQLException e) {
  e.printStackTrace();
  return nullArray;
 }
}

/*достанем одну запись из таблицы my_table по условию*/
public MyTable getRecordById(Integer inId) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
  
  Map&amp;lt;String, Object&gt; params = new HashMap&amp;lt;String, Object&gt;();
  if (inId != null) params.put(&quot;id&quot;, inId);
  
  MyTable result = (MyTable) persistence.selectRow(MyTable.class, params);
  
  conn.close();
  return result;
 } catch (SQLException e) {
  e.printStackTrace();
  return null;
 }
}

/*создадим запись в таблице my_table*/
public void insertRecord(MyTable entity) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
     
  persistence.insert(entity);
  
  conn.close();
 } catch (SQLException e) {
  e.printStackTrace();
 }
}

/*обновим запись в таблице my_table*/
public void updateRecord(MyTable entity) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
     
  persistence.update(entity);
  
  conn.close();
 } catch (SQLException e) {
  e.printStackTrace();
 }
}

/*удалим запись в таблице my_table*/
public void deleteRecord(MyTable entity) {
 try {
  OracleConnection conn = (OracleConnection) dataSource.getConnection();
  Persistence persistence = new PersistenceOraImpl((OracleConnection) conn);
     
  Map&amp;lt;String, Object&gt; params = new HashMap&amp;lt;String, Object&gt;();
  if (entity.getId() != null) params.put(&quot;id&quot;, entity.getId());

  persistence.delete(entity.getClass(), params);
  
  conn.close();
 } catch (SQLException e) {
  e.printStackTrace();
 }
}
&lt;/pre&gt;Замечу что в данном примере я беру connection к БД из готового dataSource.&lt;br /&gt;
&lt;br /&gt;
Конечно данный ORM покажется излишне простым, нельзя работать с join-ами, транзакции придется писать самому и еще нельзя много чего другого. Думаю в нашем случае это и не надо.
&lt;br /&gt;
Ну и напоследок стоит упомянуть, что серьезные ORM, например Hibernate, написаны с использованием FastMethod из cglib, и тем самым работают на порядок быстрее, чем с использованием reflection.</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/8743472178486630987/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/04/simple-orm.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/8743472178486630987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/8743472178486630987'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/04/simple-orm.html' title='Simple ORM'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-7236531747528619790</id><published>2011-04-05T07:27:00.000-07:00</published><updated>2011-09-07T15:33:37.158-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="java core"/><title type='text'>Сериализация обьекта</title><content type='html'>отправка обьекта:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;Message message = new Message();
 ByteArrayOutputStream fos = new ByteArrayOutputStream();
 ObjectOutputStream oos = new ObjectOutputStream(fos);
 oos.writeObject(message);
 oos.flush();
 oos.close();

 byte[] messageBodyBytes = fos.toByteArray();
&lt;/pre&gt;где Message - POJO обьект.&lt;br /&gt;
&lt;br /&gt;
Далее обьект можно записать в файл или отправить в сообщении.&lt;br /&gt;
&lt;br /&gt;
прием обьекта:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;ByteArrayInputStream fis = new ByteArrayInputStream(messageBodyBytes);
 ObjectInputStream oin = new ObjectInputStream(fis);
 Message mess = (Message) oin.readObject();
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/7236531747528619790/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/04/blog-post.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/7236531747528619790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/7236531747528619790'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/04/blog-post.html' title='Сериализация обьекта'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-5021023975190485414</id><published>2011-03-30T05:09:00.000-07:00</published><updated>2011-09-07T15:34:39.744-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><title type='text'>Настраиваем поддержку русского языка в Linux Ubuntu</title><content type='html'>Открываем шелл: ALT+F2.&lt;br /&gt;
&lt;br /&gt;
Обновляем репозиторий: &lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo apt-get update&lt;/pre&gt;Качаем саппорт языка, заодно всякие медиа и эмулятор windows:&lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo apt-get install language-support-ru ubuntu-restricted-extras wine&lt;/pre&gt;&lt;br /&gt;
При установке шрифтов windows выскакивает лицензионное соглашение. Соглашаемся с ним TAB+ENTER. &lt;br /&gt;
&lt;br /&gt;
После установки, для настройки переключения раскладки на клавиатуре редактируем файл: &lt;br /&gt;
&lt;pre class=&quot;bash&quot; name=&quot;code&quot;&gt;sudo nano /etc/default/console-setup&lt;/pre&gt;Для переключения по CTRL+SHIFT зменяем строки:&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;XKBLAYOUT=&quot;us,ru&quot;&lt;br /&gt;
XKBVARIANT=&quot;,winkeys&quot;&lt;br /&gt;
XKBOPTIONS=&quot;grp:ctrl_shift_toggle&quot;&lt;/b&gt;&lt;/blockquote&gt;Для переключения по ALT+SHIFT, устанавливаем параметр &lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;XKBOPTIONS=&quot;grp:alt_shift_toggle&quot;&lt;/b&gt;&lt;/blockquote&gt;перезагружаемся.</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/5021023975190485414/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/03/linux-ubuntu.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/5021023975190485414'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/5021023975190485414'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/03/linux-ubuntu.html' title='Настраиваем поддержку русского языка в Linux Ubuntu'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-635662758874306157</id><published>2011-03-18T02:13:00.000-07:00</published><updated>2011-09-07T15:35:10.806-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="primefaces"/><title type='text'>Огромные шрифты в темах PrimeFaces 2.2.x</title><content type='html'>Чтобы избавиться от огромных шрифтов в PrimeFaces 2.2 надо переопределить стиль ui-widget.&lt;br /&gt;
&lt;br /&gt;
Для этого создаем css следующего вида:&lt;br /&gt;
&lt;pre class=&quot;css&quot; name=&quot;code&quot;&gt;.ui-widget {
   font-size: 12px !important;
}
&lt;/pre&gt;&lt;br /&gt;
и подтягиваем ее на странице:&lt;br /&gt;
&lt;pre class=&quot;xml&quot; name=&quot;code&quot;&gt;&lt;h:head&gt;
   &amp;lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;mystyle.css&quot;/&gt;
&lt;/h:head&gt;
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/635662758874306157/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/03/primefaces-22x.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/635662758874306157'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/635662758874306157'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/03/primefaces-22x.html' title='Огромные шрифты в темах PrimeFaces 2.2.x'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-5829086363426997055</id><published>2011-02-10T01:07:00.000-08:00</published><updated>2011-09-07T15:36:02.732-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AMQP"/><category scheme="http://www.blogger.com/atom/ns#" term="RabbitMQ"/><title type='text'>Реализуем обмен сообщениями AMQP с помощью RabbitMQ</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;Для начала установим и настроим RabbitMQ.&lt;br /&gt;
&lt;br /&gt;
Тут все просто, скачиваем с основного сайта &lt;a href=&quot;http://www.erlang.org/download.html&quot;&gt;Erlang&lt;/a&gt;, проставляем ERLANG_HOME. Далее качаем и ставим сам &lt;a href=&quot;http://www.rabbitmq.com/server.html&quot;&gt;RabbitMQ&lt;/a&gt;. Запускаем Rabbit через командную строку: &lt;span class=&quot;code &quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;&lt;span class=&quot;code &quot;&gt;%RABBITMQ_SERVER%/sbin/&lt;/span&gt;rabbitmq-server.bat &lt;/b&gt;&lt;br /&gt;
&lt;/blockquote&gt;Если появилось сообщение broking running то все ок, наш сервер работает.&lt;br /&gt;
&lt;br /&gt;
Теперь надо настроить пользователя и виртуальный хост сервера. &lt;span class=&quot;code &quot;&gt;Запускаем с командной строки: &lt;/span&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;&lt;span class=&quot;code &quot;&gt;%RABBITMQ_SERVER%/sbin/&lt;/span&gt;rabbitmqctl.bat add_user admin admin&lt;/b&gt;&lt;br /&gt;
&lt;/blockquote&gt;Пользователь admin с паролем admin создан. Теперь создадим виртуальный хост:&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;rabbitmqctl.bat add_vhost ru.vie2004.vhost&lt;/b&gt;&lt;br /&gt;
&lt;/blockquote&gt;после чего надо дать права на пользование им нашим пользователем:&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt;rabbitmqctl.bat set_permissions -p ru.vie2004.vhost admin .* .* .*&lt;/b&gt;&lt;/blockquote&gt;&lt;br /&gt;
Все, сервер настроен на работу. Более тонкие настройки можно найти на &lt;a href=&quot;http://www.rabbitmq.com/admin-guide.html&quot;&gt;RabbitMQ&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Теперь напишем простенькие Sender и Consumer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sender:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;ConnectionFactory factory = new ConnectionFactory();

factory.setUsername(&quot;admin&quot;);
factory.setPassword(&quot;admin&quot;);
factory.setVirtualHost(&quot;ru.vie2004.vhost&quot;);
factory.setHost(&quot;localhost&quot;);
factory.setPort(5672);

Connection conn = factory.newConnection();
Channel channel = conn.createChannel();
String exchangeName = &quot;myNewExchange&quot;;
String routingKey = &quot;myNewRoute&quot;;

byte[] messageBodyBytes = &quot;Наше сообщение&quot;.getBytes();

channel.basicPublish(exchangeName, routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN, messageBodyBytes);
&lt;/pre&gt;Если надо передать не текст, а обьект, то необходимо сериализовать его в byte[].&lt;br /&gt;
&lt;br /&gt;
Consumer:&lt;br /&gt;
&lt;pre class=&quot;java&quot; name=&quot;code&quot;&gt;ConnectionFactory factory = new ConnectionFactory(); 

factory.setUsername(&quot;admin&quot;);
factory.setPassword(&quot;admin&quot;);
factory.setVirtualHost(&quot;ru.vie2004.vhost&quot;);
factory.setHost(&quot;localhost&quot;);
factory.setPort(5672);
Connection conn = factory.newConnection();
Channel channel = conn.createChannel();
boolean durable = true;

channel.exchangeDeclare(&quot;myNewExchange&quot;, &quot;direct&quot;, durable);
channel.queueDeclare(&quot;myNewQueue&quot;, durable, false, false, null);
channel.queueBind(&quot;myNewQueue&quot;, &quot;myNewExchange&quot;, &quot;myNewRoute&quot;);

boolean noAck = false;
QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(queueName, noAck, consumer);

while (true) {
  QueueingConsumer.Delivery delivery;
  try {
    delivery = consumer.nextDelivery();
  } catch (InterruptedException ie) {
    continue;
  }
  System.out.println(&quot;Получено сообщение: &quot; + new String(delivery.getBody()));
}
&lt;/pre&gt;Все, запускаем слушателя с отправителем и читаем сообщение.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ps. Не могу не упомянуть что для RabbitMQ есть &lt;a href=&quot;http://jbrisbin.com/web2/articles/log4j-logging-with-rabbitmq/&quot;&gt;аппендер &lt;/a&gt;log4j. Работать с ним можно, но придется немного подработать напильником для удобного пользования.&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/5829086363426997055/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/02/amqp-rabbitmq.html#comment-form' title='Комментарии: 0'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/5829086363426997055'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/5829086363426997055'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/02/amqp-rabbitmq.html' title='Реализуем обмен сообщениями AMQP с помощью RabbitMQ'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1477191244885294571.post-6820035383085573125</id><published>2011-02-09T12:00:00.000-08:00</published><updated>2011-03-30T05:15:43.628-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="primefaces"/><title type='text'>primefaces migrate from 2.2.RC2 to 2.2</title><content type='html'>&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;С выходом на днях новой версии primefaces 2.2 появилось два нововведения. К сожалению не все они мне понравились:&lt;br /&gt;
&lt;br /&gt;
1. теперь user guide платная, стоит порядка 10 евро.&lt;br /&gt;
&lt;a href=&quot;http://primefaces.org/documentation.html%20&quot;&gt;http://primefaces.org/documentation.html &lt;/a&gt;&lt;br /&gt;
2. темы теперь надо подключать через jar. &lt;br /&gt;
&lt;a href=&quot;http://primefaces.org/themes.html&quot;&gt;http://primefaces.org/themes.html&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
ps. &lt;a href=&quot;https://docs.google.com/viewer?a=v&amp;amp;pid=explorer&amp;amp;chrome=true&amp;amp;srcid=0B9n43GlHTxf0Y2JlZDljYzYtYjRmMS00ZmRkLTk3YzMtNWNhOTY2ZmNkNzFh&amp;amp;hl=ru&amp;amp;authkey=CJXK2JQP&quot;&gt;Документация от 26.07.2010&lt;/a&gt;. Настройки тем действительны только до версии 2.2.RC2 включительно.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://vie2004.blogspot.com/feeds/6820035383085573125/comments/default' title='Комментарии к сообщению'/><link rel='replies' type='text/html' href='http://vie2004.blogspot.com/2011/02/primefaces-migrate-from-22rc2-to-22.html#comment-form' title='Комментарии: 2'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6820035383085573125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1477191244885294571/posts/default/6820035383085573125'/><link rel='alternate' type='text/html' href='http://vie2004.blogspot.com/2011/02/primefaces-migrate-from-22rc2-to-22.html' title='primefaces migrate from 2.2.RC2 to 2.2'/><author><name>vie</name><uri>http://www.blogger.com/profile/15916691079821601056</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='29' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigU2xVp_gieROMklTGmd6zmfeGXw55Vl6FT0yQ1nDe4JHq49zbAupDivRoBjSrYMm2nJ0hZroRaYoDUbWBBrQ9em2Cet-5Sz6bT_dM8c6WrUROoG1Mt6rTGZfOK3sgVA/s220/slow.jpeg'/></author><thr:total>2</thr:total></entry></feed>