Инструменты пользователя

Инструменты сайта



// Quartz Scheduler

Потребовалось использовать в одном проекте данный планировщик (http://quartz-scheduler.org/). Запускается на ура в виде бина в JBoss… Но вот тут с размаху врезался лбом в косяк:

  1. планировщик регистрируется в JNDI
  2. я успешно получаю инстанс планировщика
  3. добавляю свои задачу со своим воркером

И кряк вам с хреном, а не профит:

ClassNotFoundException...

// Hibernate + SQLite

Шаг 1. Взять sqlite-jdbc отсюда: http://www.xerial.org/trac/Xerial/wiki/SQLiteJDBC или при помощи Maven (описание по той же ссылке)

Шаг 2. Положить у себя в проект класс SQLiteDialect, взятый отсюда: http://arnoraps.tweakblogs.net/blog/3146/hibernate-with-sqlite.html или из архива отсюда: http://code.google.com/p/hibernate-sqlite/ (HibernateSQLite.zip)

Шаг 3. В конфигурацию Hibernate добавить примерно следующее:

  <!-- SQLite settings -->
  <property name="hibernate.connection.driver_class">org.sqlite.JDBC</property>
  <property name="hibernate.connection.url">jdbc:sqlite:./data.db</property>
  <property name="hibernate.dialect">ru.sincore.db.SQLiteDialect</property>
 
  ...
 

// Jetty, JSP и Maven

На правах заметки:

  • Список зависимостей для Maven, что бы получить последнюю (8.0.4) версию embedded Jetty и получить рабочий JSP.
  • Конфиг для embedded Jetty, что бы завёлся JSP.

Подробности подкатом

// Java Timezone

В последней Java6 не включена tzdata с информацией о том, что в России, сейчас нет перехода на зимнее время. Дальнейшие пояснения излишни.

Как фиксить? Обновить tzdata при помощи предлагаемой ораклом утилиты:

// Hibernate Tutorial

Отличный, по моему мнению, туториал по Hibernate:

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

// Изменение версии в многомодульном Maven проекте

Что бы одним махом изменить версию в многомодульном проекте, достаточно использовать плагин versions, подключив его к корневому pom:

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>versions-maven-plugin</artifactId>
                <version>1.2</version>
            </plugin>

Установить версию после этого можно командой:

mvn versions:set -DnewVersion=1.0.0-SNAPSHOT

или аналогичным образом.

Подробнее:

// JBoss, JDBC: Closing a connection for you

Если узреете у себя такие исключения:

2011-07-14 17:11:14,652 INFO  [org.jboss.resource.connectionmanager.CachedConnectionManager] (http-localhost%2F127.0.0.1-8080-1) Closing a connection for you.  Please close them yourself: org.jboss.resource.adapter.jdbc.jdk6.WrappedConne
ctionJDK6@6ae0286d: java.lang.Throwable: STACKTRACE

Или около того, обратите внимание на этот документ: http://community.jboss.org/wiki/WhatDoesTheMessageDoYourOwnHousekeepingMean

А так же ознакомьтесь со следующей темой на форуме: http://community.jboss.org/thread/73267

А если коротко: если вы получаете подключение из пула, всегда обрамляйте работу с ним в конструкцию try/catch/finally примерно следующего вида:

Connection conn = null;
try
{
    // работа с базой...
}
finally
{
   try
   {
       conn.close();
   }
   catch (Throwable ignored)
   {
   }
}

// Maven trouble

Сегодня отхватили, что Maven отказался на отрез выкачивать пакеты с HTTPS репозитария JBoss, матерясь:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

Решение найдено было тут: http://blogs.sun.com/andreas/entry/no_more_unable_to_find

Если коротко:

  1. Компиляем его:
    javac InstallCert.java
  2. Запускаем рраз:
    java InstallCert repository.jboss.org

    жмахаем 1 и <RETURN>

  3. Запускаем два:
    java InstallCert repository.jboss.org

    видим что сертификат теперь trusted.

  4. Копируем файл jssecacerts в $JAVA_HOME/jre/lib/security
  5. Удаляем кеш Maven:
    rm -rf ~/.m2/repository

Всё, после этого должно всё работать.

// Перенос строки по заданной границе без разбивки слов (word-wrap) в Java

В составе Apache Commons есть чудная библиотечка Lang в которой есть класс WordUtils который и поможет нам решить поставленную задачу, примерно следующим образом:

WordWrap.java
package test;
 
import java.io.IOException;
 
import org.apache.commons.lang.WordUtils;
 
public class WordWrap
{
  public static void main(String[] args) throws IOException 
  {
    String str = "This is a sentence that we're using to test the wrap method";
    System.out.println("Original String 1:\n" + str);
    System.out.println("\nWrap length of 10:\n" + WordUtils.wrap(str, 10));
    System.out.println("\nWrap length of 20:\n" + WordUtils.wrap(str, 20));
    System.out.println("\nWrap length of 30:\n" + WordUtils.wrap(str, 30));
 
    String str2 = "This is a sentence that we're using to test the wrap method and hereisaveryveryveryverylongword";
    System.out.println("\nOriginal String 2:\n" + str2);
    System.out.println("\nWrap length of 10, <br/>\\n newline, wrap long words:\n"
			+ WordUtils.wrap(str2, 10, "<br/>\n", true));
    System.out.println("\nWrap length of 20, \\n newline, don't wrap long words:\n"
			+ WordUtils.wrap(str2, 20, "\n", false));
  }
}

// Сортировка "цифровых" строк в Java

Для сортировки массивов в Java есть Arrays.sort(array). Есть так же форма с указанием своего компаратора.

Задача: нужно отсортировать строки, в которых содержатся цифровые значения, вроде:

bg1
bg3
bg20
bg10

После классический сортировки получим такой результат:

bg1
bg10
bg20
bg3

Не всегда это нужно, и не всегда есть возможность выравнивать нулями до формы bg01,bg03,bg30

По ссылке ниже вариант компаратора, выполняющего данную задачу: http://sanjaal.com/java/206/java-data-structure/alphanumeric-string-sorting-in-java-implementation/

// Hightide

Hightide (High Tide - большая вода) - сборка Jetty с включенными дополнительными библиотеками и сервисами JavaEE (эдакий не совсем JavaEE Application Server). Решили попробовать его для своих нужд, пока возможностей JBoss нам не нужно.

Последняя стабильная версия - 7.3.0 (поддерживается Java5), нестабильная - 8.0.0.M2 (нумерация по версии Jetty, поддерживает Java6).

Скачать можно отсюда: http://dist.codehaus.org/jetty/

Для удобной работы потребуется адаптер для WTP, который поддерживает Jetty 7 и 8: http://wiki.eclipse.org/Jetty_WTP_Plugin/Jetty_WTP_Install

Единственный нюанс: адаптер рассчитан чисто на Jetty, поэтому в дефолтной конфигурации просто не запустится - не будет хватать jar-ников. Пока выход нашёл ровным счётом один: по двойному клику на вкладке Servers по Jetty открываем диалог конфигурации, там идём в «Open launch configuration» и далее двигаемся на вкладку Classpath и в категории User Entries добавляем External JARs, которые ищем в lib директории и поддиректориях в jetty.home.

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

При работе с Maven поможет эта статья: http://docs.codehaus.org/display/JETTY/Fast+WebApps+with+Hightide

А про мой «любимый» JAAS почитать можно тут: http://docs.codehaus.org/display/JETTY/JAAS, а вообще по документации:

По вопросам горячего деплоя можно почитать тут: http://phishbouncer.com/trac/browser/trunk/jetty/demo/webapps/jetty/faq/HotDeploy.html, где сказано, цитирую:

Q: Can Jetty Hot Deploy?

A: Jetty is fully hot deployable, but does not have any native hot deployers.
What this means is that Jetty contexts, servlets and filters may be added, stopped,
started and reloaded dynamically, but that Jetty does not have any services that
trigger these events.

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

Пока реализовывать не пробовал. Будут результаты - будет отчёт.

// Apache Maven 2

На правах мемориза:

// Maven и WTP

WTP - Eclipse Web Tools Platform. Набор расширений для удобной работы с WEB проектами. Деплой на различные серверы приложений, отладка, профилирование и много всего другого вкусного.

Про Maven не пишу, многим понятно. В последних версиях плагина для Eclipse в extra есть модули для j2ee проектов различных версий соглашений (j2ee 5/6 и младше). Но статья по ссылке:
http://www.devx.com/Java/Article/36785

будет полезна как инструкция по переводу существующего проекта, созданного средсвами Eclipse и WTP на сборку maven'ом.

// Java и LDAP. Малость заметок

Помаленьку, понемножку, на уровне ссылок.

Заметка первая: LDAP как JNDI ресурс в context.xml

Читать тут: http://old.nabble.com/LDAP-as-resource-in-context.xml-td14204908.html

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

new InitialDirContext(env);

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

Заметка вторая: использование DN в фильтрах

Не сразу прокурил как, вот статейка на русском языка, поясняющая - как это нужно делать: http://sysadminblog.ru/ldap/2011/01/18/tipichnye-primery-ispolzovaniya-entrydn-v-ldap-filtrah.html

// ThreadLocal Memory Leak

Использовать ThreadLocal переменные удобно, для расшаривания данных между разными частями одного потока (допустим достучаться из POJO объекта к HTTP сессии и т.п.). Другое дело, что чревато в контексте использования сервера приложений: тут треды не уничтожаются, а возвращаются в пул потоков, как следствие: GC не собирает их, они остаются в памяти, а тут, помимо явной утечки, есть ещё и потенциальная дырка в безопасности.

По ссылке статья на английском на эту тематику. Как решить теперь буду думать.

По этой ссылке:
http://wiki.apache.org/tomcat/MemoryLeakProtection
Можно почитать про разные MemLeaks в веб-приложениях (точнее про технологию защиты от оных в Tomcat)

UPD: подкатом решение (???)

Решение

Найдено тут: http://weblogs.java.net/blog/jjviana/archive/2010/06/09/dealing-glassfish-301-memory-leak-or-threadlocal-thread-pool-bad-ide

какое выбирать, решать вам, я выбрал второй вариант с наследованием класса. Скопирую его тут с форматированием:

import java.lang.ref.SoftReference;
 
public abstract class SoftThreadLocal<T> extends ThreadLocal<T>
{
    // Encapsulation required because Generics is stupid about references, and there is no interface for ThreadLocal, 
    //so I can't simply extend a single ThreadLocal, grr! Java has so many brittle design mistakes in it.
    private final ThreadLocal<SoftReference<T>> local = new ThreadLocal<SoftReference<T>>();
 
 
    @Override
    public T get() 
    {
        SoftReference<T> ref = local.get();
        T result = null;
 
        if (null != ref) 
        {
            result = ref.get();
        }
 
        if (null == result) 
        {
            result = initialValue();
            ref = new SoftReference<T>(result);
            local.set(ref);
        }
 
        return result;
    }
 
 
    @Override
    public void set(T value) 
    {
        if (null == value) 
        {
            remove();
        } 
        else 
        {
            local.set(new SoftReference<T>(value));
        }
    }
 
 
    @Override
    public void remove() 
    {
        local.remove();
    }
}

Далее работа классическая, к примеру, как у меня через ThreadLocal Singleton:

import java.util.HashMap;
 
/**
 * Небольшой вспомогательный статический класс
 * для расшариванить локальных для треда переменных. Значение будет для каждого треда своё.
 * 
 * Допустим, получая в методе doPost()/doGet() сервлета значение сессии и для проброса во все дочерние
 * классы, без необходимости передачи оных параметром, что, собственно говоря, не всегда возможно.
 *
 * @author hatred
 * 2011-01-27
 */
public class ThreadContext
{
    private /*static*/ final SoftThreadLocal<HashMap<Object, Object>> _context = new SoftThreadLocal<HashMap<Object, Object>>()
    {
        protected HashMap<Object,Object> initialValue()
        {
            return new HashMap<Object,Object>();
        }
    };
 
    private static ThreadContext _instance = null;
    //
 
    synchronized public static ThreadContext getContext()
    {
        if (_instance == null)
        {
            _instance = new ThreadContext();
        }
 
        return _instance;
    }
 
    synchronized public static void releaseContext()
    {
        if (_instance != null)
        {
            _instance.clear();
            _instance.contextRemove();
        }
 
        _instance = null;
    }
 
    public void put(Object key, Object value)
    {
        _context.get().put(key, value);
    }
 
    public Object get(Object key)
    {
        return _context.get().get(key);
    }
 
    public void remove(Object key)
    {
        _context.get().remove(key);
    }
 
    public void clear()
    {
        _context.get().clear();
    }
 
    protected void contextRemove()
    {
        _context.remove();
    }
}

Кстати, не могу понять, насколько правильно делать getContext() и releaseContext() synchronized?