Sunday, November 16, 2008

Підключаємося до транзакції

Часом в проекті з CMT бінами потірібно працювати з ресурсами які немають підтримки JTA, але мають підтримку двофазних транзакцій (Наприклад з бінів потрібно робити запити до CORBA ресурсів). В таких випадках трохи не зрозуміло де для таких ресурсів потрібно починати і закінчувати транзакцію. І тут на допомогу приходить інтерфейс javax.transaction.Synchronization. Його реалізацію можна зареєструвати в поточній транзакції і відслідковувати коли визвати першу і другу фазу коміту. Отже реалізація має бути типу
public class MyResourceSynchronization implements Synchronization{
public void beforeCompletion() {
    myResource.validate();
}
public void afterCompletion(int status) {
    if(status==Status.STATUS_ROLLEDBACK)
        myResource.rollback();
    else
        myResource.commit();
}}
і чіпляємо його до транзакції наспуним чином
TransactionManager manager=(TransactionManager)sessionContext.getUserTransaction();
manager.getTransaction().registerSynchronization(new MyResourceSynchronization());

Wednesday, November 5, 2008

Toplink Essentials в Resin 2 і не тільки

В продовження теми Toplink Essentials on Caucho Resin.

Як відомо Toplink Essentials являється Reference Implementation специфікації JPA і тому підтримує буквально два сервери - це SunAS9 i OC4J_10_1_3. Щоб пересвітчитись достатньо заглянути в клас oracle.toplink.essentials.config.TargetServer. З рештою серверів Toplink працює як в середовищі без підтримки JTA (при коміті ejb транзакції Toplink зміни в базу не синхронізує). 

Щоб добавити підтримку JTA для свого сервера потрібно створити два класи - перший це клас, що серверну платформу і повинен реалізовувати інтерфейс oracle.toplink.essentials.platform.server.ServerPlatform, як початковуреалізацію можна взяти клас oracle.toplink.essentials.platform.server.ServerPlatformBase. Головним методом в цьому класі є getExternalTransactionControllerClass, який повертає клас що вміє для конкретного сервера шукати референс на javax.transaction.TransactionManager. В нашому випадку це другий клас який потрібно сворити і наслідує він oracle.toplink.essentials.transaction.JTATransactionController

Назвемо перший клас ResinServerPlatform, а другий ResinTransactionController. ResinTransactionController повинен переопреділити метод acquireTransactionManager наступним чином

protected TransactionManager acquireTransactionManager() throws Exception {
  return (TransactionManager)jndiLookup("java:comp/UserTransaction");
 }

Тепер залишилося в persistence.xml прописати для властивості toplink.target-server значення ResinServerPlatform.

Я не наводжу повних кодів для класів, так як достатньо в сорцах подивитися на реалізацю oracle.toplink.essentials.platform.server.sunas.SunAS9ServerPlatform та oracle.toplink.essentials.transaction.sunas.SunAS9TransactionController і все стане зрозуміло.

Monday, November 3, 2008

Javahl в SVN плагіні для eclipse

В tigris є хороший плагін для екліпси, який може працювати як на явовському клієнті так і на натівному. Щоб активувати натівний клієнт, потрібно встановити пакет libsvn-java, а в eclipse.ini прописати -Djava.library.path=/usr/lib/jni.

Saturday, October 25, 2008

Встановлюємо Plone для дівелопінгу

Звичайно можна просто скачати уже готовий пакет з сайту плона і встановити його чи з репозиторія лінукса. Але якщо хочеться не просто поклацати лінки в порталі, а й щось під нього написати, то потрібно мати правильно налаштоване середовище для розробки.
Plone працює поверх Zope2 який ще не підтримує python2.5, а тому у вашій системі повинен бути встановлений python2.4. Для роботи з картинками потрібно щоб була встановлена бібліотека Python Image Library, а для роботи з XML - elementtree. Обидві бібліотеки як правило є в репозиторії дистрибутиву. Тепер скачаємо і виконаємо крипт який створить структуру директорій і згенерує файл конфігурація на основі якого можна буде збирати ізапускати плон зі своїми власнописаними плагінами(продуктами).
$ wget http://peak.telecommunity.com/dist/ez_setup.py
$ python ez_setup.py
$ easy_install ZopeSkel
Скрипт скачаний і встановлений в систему, тепер генеруємо структуру директорій
$ paster create -t plone3_buildout myproject
Щоб запустити проект його потрібно зібрати, для цього виконуємо
$ cd myproject
$ python bootstrap.py
$ ./bin/buildout
Всі заптання можна залишити з дефолтовими значеннями. Так як ми не вказували шлях до Zope i Plone, то вони будуть скачані і зібрані автоматично.
Тепер просто запускаємо Plone
$ ./bin/instance fg
а в браузері відкриваємо http://localhost:8080

Wednesday, October 22, 2008

Портал

Передивився недавно кучу портальних движків, шукав щось таке, що має вже більш чи меньш закінчений вигляд, і щоб можна було налаштувати під свої потреби. Серед всього того розмаїття особливо хотілось би відмітити два портали - це LifeRay написаний на яві та Plone написаний на пітоні. Якщо LifeRay - це портал в повному розумінні цього слова з підтримкою організай та комуніті, то Plone - це крім портала ще й cms.

Особисто для себе я вибрав Plone, так як дівелоперської доки під нього більше, тай ще існує така чудова книга Мартіна Аспелі як "Professional Plone Development", в якій крок за кроком описані всі стадії розробки під Plone і після її прочитання стає дуже легко і зрозуміло орієнтуватися в документації, що є на сайті. Рекомендую починати вивчення плона саме з цієї книги.

Thursday, August 28, 2008

Cactus і редірект

Часто в одному тест методі визивається більше ніж один екшен стратса особливо коли наступний екшен зав"язаний на данні в сесії з попереднього екшена. Але тут потрібно бути дуже уважним і не забувати, що кожен тест метод виконується не тільки на окремій сесії, але й на одному окремому реквесті та резпонсі. А це може привести до наступної проблеми: якщо перший екшен після виконання робить редірект, то в заголовок резпонса записується всластивість Location, а так як резпонс один на весь метод, то наступний екшен визивається з цим самим інстансом резпонса. А кактус, в момент перевірки форварда, в першу чергу порівнює шлях форварда зі значенням заголовка Location, а вже потім із мапингом стратса.

Tuesday, August 19, 2008

І знову XML паресер

Тільки тепер уже разом з Digester i Resin. Чесно кажучи, не долюблюю я Resin саме через його гнучкість. У Resin є можливість добавити системні властивості на рівні хоста(і не тільки). Так от, якщо ви, наприклад, маєте проект зі struts, який використовує digester, в classpath є xerces, але як парсер на рівні хоста вказаний не xerces, а скажімо com.caucho.xml.parsers.XmlSAXParserFactory, то виходить цікава картина: Digester бачить, що в системі є xerces і пускає логіку по шляху який зав"язаний на xerces, але на справді інітиться резіновська XmlSAXParserFactory. Ну і відповідно отримуємо екшепшен.
Щоб його позбутися прибираємо xerces з classpath, або вказуємо як парсер org.apache.xerces.jaxp.SAXParserFactoryImpl

Friday, August 15, 2008

Java "dll hell"

Буквально на днях стикнувся з таким явищем як "dll hell" тільки в яві. Зараз практично жоден проект має xml файли і, як результат, потребує парсера. Є в мене в Resin кілька проектів, і що саме дивне, одна і та сама копія Resin з проектами на одних серверах працює нормально, а на інших ні - весь час свариться на JAXP парсер.
Виявилося, що розгадка в тому як шукається і інітиться парсер. Спершу шукається системна властивість javax.xml.parser.SAXParserFactory - якщо її не вказано, то шукається в classpath файл \META-INF\services\javax.xml.parsers.SAXParserFactory - ось тут і була проблема. В Resin два jar файли має такий файл і в них описані різні парсери - org.apache.crimson.jaxp.SAXParserFactoryImpl і com.caucho.xml.parsers.XmlSAXParserFactory.
От і виходило, що на одних системах getResourceAsStream повертав одне значення, а на інших - інше.
Мораль цієї історії така - все повинно бути описано в проекті строго настрого.

Tuesday, August 12, 2008

Заради OpenID

І на що тільки не підеш, аби отримати OpenID? От і довелося мені зареєструватися на блогері. Взагалі-то варіантів де отримати OpenID було чимало - http://openid.net/get/, але в блогера можна використовувати гмейловський екаунт. Так що, ось таким нехитрим способом, я перетворив gmailID на OpenID.