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

воскресенье, 30 ноября 2008 г.

Тестирование при помощи JUnit и Spring-Tests

При разработке веб-приложений с помощью связки Spring+Hibernate тестирование становится достаточно нетривиальной задачей, если подходить к ней в лоб. В процессе запуска теста необходимо выполнить следующие шаги: поднять контекст Spring'a, произвести необходимые dependency-injection, обеспечить открытую сессию Hibernate на протяжении выполнения теста (в веб-приложениях эту работу выполняет OpenSessionInViewFilter, который держит сессию открытой на период обслуживания запроса пользователя). Рассмотрим как это сделать на примере использования распространенного фреймворка для тестирования JUnit версии 4.4 (более новая версия 4.5 имеет проблемы совместимости со Spring) и модуля Spring-tests из SpringModules (spring-test.jar). Класс простейшего теста приведен ниже:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring-config.xml" })
public class MessageServiceTest {

private MessageStringDataServiceInterface messageStringDataService;
private DefaultWebConfig defaultWebConfig;
private SessionFactory sessionFactory;

@Autowired
public void setDefaultWebConfig(DefaultWebConfig defaultWebConfig) {
this.defaultWebConfig = defaultWebConfig;
}

@Autowired
public void setMessageStringDataService(
MessageStringDataServiceInterface messageStringDataService) {
this.messageStringDataService = messageStringDataService;
}

@Autowired
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

@Test
public void onSetUp() {
TransactionSynchronizationManager.bindResource(sessionFactory,
new SessionHolder(sessionFactory.openSession()));
}

@Test
public void testMessageDataService() throws DomainException {
assertNull(messageStringDataService.getMessageString("test.message",
defaultWebConfig.getDefaultLanguage()));
}

@Test
public void onTearDown() {
TransactionSynchronizationManager
.unbindResourceIfPossible(sessionFactory);
}
}
Для того, чтобы при запуске теста поднимался контекст Spring'a необходимо аннотировать класс при помощи следующих аннотаций:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring-config.xml" })
Первая из них сообщает Spring'у, что надо использовать специальный wrapper для запуска этого теста в JUnit, а вторая указывает имя конфигурационного файла контекста. Все конфигурационные файлы, на которые есть ссылки в конфиге контекста должны находиться также в classpath для корректного запуска теста. После этого можно устанавливать все зависимости при помощи аннотации @Autowired. Аннотация @Test относится к JUnit и ей маркируются собственно методы для тестирования. Выполняются они в порядке следования в коде, поэтому методы onSetUp() и onTearDown() будут выполнены соответственно в первую и в последнюю очередь. Это мы и используем для демаркации сессии при помощи менеджера транзакций Spring. Примерно так же работает и OpenSessionInViewFilter, который при старте обработки запроса пользователя открывает сессию и затем привязывает ее к сессии, а при окончании обработки запроса - освобождает ресурс. Два вышеописанных метода выполняют аналогичную функцию. На этом интеграционную часть можно считать раскрытой, а по новым возможностям JUnit рекомендую краткий обзор с примерами.

среда, 26 ноября 2008 г.

Hibernate и танцы с бубном

Иногда возникают такие ситуации, когда программа на ровном месте не работает, причем потом причина оказывается более чем прозаической. Так было и сейчас - никак не мог понять, почему не генерится таблица в БД при старте приложения (есть у Хибернейта такая милая возможность - создавать все таблицы при старте). Все остальные - преспокойно, а одна никак не хочет. После получаса шаманских плясок у ноутбука оказалось, что не нравится Хибернейту поле (и колонка в аннотации) с именем "key".  Естесственно это зарезервированное ключевое слово в MySQL, поэтому использовать его как имя колонки никак  нельзя, но создавая классы доменной модели, об этом как-то забываешь, а Хибернейт не считает нужным перенаправить в лог ошибку сервера.  Так что мораль сей басни - товарищи, будьте бдительны! :))

вторник, 7 октября 2008 г.

JMX+Spring+Hibernate

Хибернейт поддерживает сбор самой разнообразной информации и метрик, которые могут быть весьма полезны при отладке и разработке. При использовании широко распространенной связки Spring+Hibernate можно очень легко получить доступ к этим данным следующим образом:

1) в конфигурации SessionFactory указываем: 
<property name="hibernate.generate_statistics">true</property>
это включает собственно сбор статистики.

2) регистрируем следующие бины в Spring:
<bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter">
        <property name="autodetect" value="false" />
        <property name="assembler">
            <bean id="jmxAssembler"                class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
                <property name="attributeSource">
                    <bean               class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource" />
                </property>
            </bean>
        </property>
        <property name="beans">
            <map>
                <entry key="org.hibernate:name=statistics">
                    <bean class="org.hibernate.jmx.StatisticsService">
                        <property name="statisticsEnabled" value="true" />
                        <property name="sessionFactory">
                            <ref bean="sessionFactory"/>
                        </property>
                    </bean>
                </entry>
            </map>
        </property>
    </bean>
Этот бин предоставляется нам Spring'ом и делает всю работу по экспорту статистики посредством JMX и сам выполняет все необходимые действия, нам нужно только передать ему нашу SessionFactory(выделено жирным).

3) В Томкате добавляем следующие параметры JVM:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8004 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
Здесь важен порт - туда мы будем коннектиться JConsole'ю, которая и отобразит всю статистику.

4) Запустив Томкат и убедившись, что ошибок и эксепшенов нет, идем в JAVA_HOME/bin и запускаем отттуда jconsole.exe. Когда поднимется форма, идем на вкладку Remote (удаленные соединения с JMX-сервером) и указываем host(Томката) и port(8004 в нашем случае). После успешного соединения можно смотреть самую разнообразную статистику по JVM вообще и Hibernate в частности.