среда, 13 апреля 2011 г.

Перевод xdoclet-based ejb-2.0 проекта на платформу ejb-3.0

Зачем?
Есть ещё такие проекты. Но нет уже таких application server-ов. Приходит долгожданное время, когда в организации появляются новые сервера, админы ставят на них новенький софт, все счастливы... И тут выясняется что технологически наш успешный и всё ещё развивающийся проект находится глубоко в прошлом веке. А ведь для него собственно и покупались сервера. А ставить раритетный resin 3.0 на новую систему ой как не хочется, да и неправильно. Очевидное решение - переписать проект - сталкивается с непониманием руководства. На старом сервере работало? Новый сервер лучше? Так почему не работает? И времени на "переезд" обычно даётся минимум. В таких условиях мне пришлось портировать уже третий проект, когда я решил всё-таки описать процедуру. Может быть, пригодится кому-то. Может даже мне :)

Что должно быть в наличии перед началом процедуры
Во-первых, конечно же, исходники проекта. Во-вторых xdoclet-библиотеки, ant, build.xml - короче всё, что нужно для его сборки. Достаточно даже не полной сборки а хотя бы исполнения target-а xdoclet-а.

Что получим
Проект совместимый с ejb-3.0 application server (resin 4, glassfish 3 ...), который нормально собирается в среде NetBeans или просто с коммадной строки.

Задача №1: Бины
В нашем старом проекте бины реализовывали интерфейс javax.ejb.SessionBean, в новом - будут реализовавать свои Local интерфейсы. Поэтому первое что нужно сделать - сгенерировать исходники Local-интерфейсов с помощью xdoclet. Выполняем соответствующий target нашего build.xml и получаем в нашей build-директории дерево каталогов с Local, Session, Util и LocalHome - классами. Local-интерфейсы переносим в каталоги с исходниками (подкаталоги src) и раскладываем рядом с исходниками бинов. Не забудем на этом этапе поменять библиотеку ejb-20.jar на ejb-30.jar. Проект перестал собираться. Теперь можно начать правку кода.
В local-интерфейсах добавляем перед объявлением класса аннотацию @Local, соответственно добавляем и импорт javax.ejb.Local. Удаляем из объявления класса "extends javax.ejb.EJBLocalObject". Больше интерфейсы трогать не будем.
В бине меняем обьявление класса с "public class MySuperBean implements SessionBean" на "public class MySuperBean implements MySuperLocal", добавляем аннотацию @Stateless с соответствующим импортом javax.ejb.Stateless и убираем метод ejbCreate(). Настройки транзакционности для методов бина, которые выносились в конфиг инструкцией для xdoclet вида @ejb.transaction type="NotSupported" теперь прописываем аннотациями: @TransactionAttribute(TransactionAttributeType.NOTSUPPORTED). Выполняем все эти операции для каждого бина в проекте. Надеюсь у вас их не слишком много :). Понятно, что если у вас конфигурация методов или типы бинов другие, аннотации ставите свои.

Задача №2: Сервлеты
Тут всё проще. Раньше получали обьект бина в сервлете мы в переопределённом методе public void init(ServletConfig conf) такой конструкцией:
InitialContext = new InitialContext();
Object objref = ic.lookup("java:comp/env/ejb/MyCoolBean");
MyCoolLocal cool = ((MyCoolLocalHome) PortableRemoteObject.narrow(objref, MyCoolLocalHome.class)).create();
Теперь метод init нам больше не нужен. Бины подключаем аннотацией:
@EJB MyCoolLocal cool;

Что не трогаем
Пока оставим использование xdoclet, это позволит нам получить web.xml автоматически. Остальные конфиги, сгенерированные им, уже не нужны. Поэтому задачу по генерации ejb-jar.xml выключаем. Также убираем в сервлетах  инструкции для xdoclet вида @web.ejb-local-ref.
Скорее всего ещё прийдётся поправить скрипт сборки, но это уже мелочи зависящие от конкретного проекта.
При такой схеме работы, по моим оценкам, адаптация небольшого проекта (300 - 400 классов) потребует не более 4 часов.

четверг, 7 апреля 2011 г.

Включение jar-библиотек в Andriod-приложение

Недавно столкнулся с неожиданной проблемой. Оказывается, подключить обычную jar-библиотеку к проекту android-приложения Netbeans позволяет, а вот включить её в скомпилированный .apk не так-то просто. Приложение собирается нормально, но в рантайме при первом обращении к библиотечным классам вываливается с ClassNotFoundException. Стандартными средствами NetBeans победить эту проблему не получилось, пришлось допиливать build.xml. Переопределяем в нём target-ы:
    <target name="-pre-jar">
        <copy todir="${build.classes.dir}">
            <fileset dir="${ext.lib.dir}">
                <include name="*.jar"/>
            </fileset>
        </copy>
    </target>

    <target name="-post-jar">
        <zip update="true" destfile="${dist.apk}">
            <zipfileset dir="${ext.lib.dir}" includes="*.so" prefix="lib/armeabi"/>
        </zip>
        <zip destfile="tmp.apk">
            <zipfileset src="${dist.apk}">
                <exclude name="META-INF/*.*" />
            </zipfileset>
        </zip>
        <move file="tmp.apk" tofile="${dist.apk}" />
        <signjar jar="${dist.apk}" alias="имя вашего ключа" storepass="пароль на хранилище" keypass="пароль на ключ" keystore="путь к хранилищу ключей.jks"/>
    </target>

В файле nbproject/project.properties объявляем свойство ext.lib.dir, в котором прописываем относительный путь к каталогу, где лежат jar-ники библиотек.
С помощью этих нехитрых манипуляций мы заставим ant при сборке проекта включить в него библиотеки и подписать полученный .apk нашим сертификатом.

Jsoup: Парсинг Html в Android-приложении

В internet масса полезных данных и так хочется наполнить ими своё приложение... И крайне редко для этого удаётся использовать публичное api или хотя бы rss. Но не беда. С современными библиотеками парсинг страниц превращается в предельно простую задачу. К тому же сайты в стиле web 2.0 содержат относительно немного html, полагаясь всё больше на css и javascript. Соответственно и объём данных, который нужно загрузить для парсинга становится меньше.
Мне довелось использовать разные инструменты для парсинга html, но недавно я открыл для себя библиотеку jsoup и остался ей весьма доволен. Впечатляет скорость работы в сочетании с богатством возможностей. Библиотека позвояет строить документ из "не совсем валидного" html, использовать xpath и css селекторы а также прямую навигацию по DOM-дереву, получать данные из элементов DOM в виде html-фрагментов или "очищенного" текста.
Приведу простой пример:
  1. class TableParser {    
  2.     
  3.     private HashMap map = new HashMap();
  4.     private final String url = "http://site.com"
  5.     
  6.     public HtmlParser() {
  7.         try {
  8.             Document doc = Jsoup.connect(url).get();
  9.             Elements rows = doc.select("div#leftCol table.main tr");
  10.             for (int i=1; i<rows.size();i++) {
  11.                 Element row = rows.get(i);
  12.                 map.put(row.child(0).text().trim(), row.child(1).text());
  13.             }
  14.         } catch (Exception e) {
  15.             e.printStackTrace(System.err);
  16.         }
  17.     }
  18.     
  19.     public HashMap getMap() {
  20.         return this.map;
  21.     }
  22. }
Тут мы создаём документ из url, css-селектором вынимаем из этого документа строки некоторой таблицы и в цикле обходим строки (кроме первой) для того чтобы получить значения первой и второй колонки а затем сложить их к себе в HashMap. Задача, как видим весьма распространённая а решение очень простое.

суббота, 2 апреля 2011 г.

Русификация Eclipse

...нашёл в сети массу способов, порой весьма извращённых: с подкладыванием библиотек и правкой конфигов. А ведь всего-то нужно воспользоваться услугами Eclipse Babel Project. Скачивать и подкладывать ничего не нужно. Идём на страницу загрузки и берём оттуда ссылку на "update site" для своей версии. Например, для Helios:
http://download.eclipse.org/technology/babel/update-site/R0.8.1/helios 
Потом в своём Eclipse заходим в help -> install new software. Добавляем новый источник используя полученную ссылку. Ждём, пока Eclipse получит список доступных обновлений из нового источника. Дальше - выбираем language pack для вашего языка. Соглашаемся с  лицензионным соглашением, выполняем установку. После рестарта ваша Eclipse заговорит на вашем языке :)

Есть одна тонкость: если ваша системная локаль отличается от желаемого языка, запускать Eclipse прийдётся с явным указанием языка:
./eclipse -nl ru

пятница, 1 апреля 2011 г.

Собеседование: три главных вопроса

Любой нормальный IT-проект вначале появляется в голове одного человека. Один человек может сделать прототип, может спроектировать "ядро" системы. Но дальше нужна команда. Мне по роду деятельности часто приходится оценивать кандидатов в ходе "технического" собеседования. И результаты такой оценки я потом ощущаю непосредственно на себе: люди, которых я отбираю, работают со мной в одних и тех же проектах.
Безусловно, есть масса методик по проведению собеседований. И любой наёмный работник со стажем наверняка испытал на "своей шкуре" много того, о чём я даже не читал. Тут я не буду углубляться в теорию вопроса, а просто опишу тот метод, что выработал для себя сам.

О чём не стоит спрашивать
Не стоит задавать "олимпиадных" задач. Реальные проекты очень редко требуют от программиста знания пяти способов сортировки массивов и трёх способов обхода бинарного дерева. Все давно есть в библиотеках, а "велосипеды" часто оказываются бомбами замедленного действия в вашем проекте. Также не стоит обращать внимания на титулы и громкие "ранее занимаемые" должности. Крутые сертификаты означают, по моему, только то, что кандидат давно думает о смене места работы и умеет готовиться к экзаменам. 

Что стоит узнать о кандидате за час до собеседования
E-mail и краткое резюме. Остальное расскажет Google. Работа программиста такова, что он поневоле "засвечивается" в самых разных местах. По его e-mail можно найти все его актуальные резюме на сайтах, большую часть его аккаунтов в социальных сетях, его блог, его посты на форумах, в конце концов, его проекты. Они могут рассказать о человеке больше чем он сам.  

Что спрашивать
Первый вопрос: "Расскажите о своём последнем проекте. Или о другом проекте, которым вы гордитесь". Тут главное заставить человека разговориться. Во-первых, так мы проверяем правда ли написана в его резюме. Можно перечислить в резюме пару десятков популярных сайтов, но ведь прийдётся рассказывать, как именно они написаны... Во-вторых появляется представление о том, что умеет кандидат. Иногда люди ищут совсем не ту вакансию, которая им подходит по квалификации. Я однажды собеседовал специалиста по юзабилити который был очень слаб в этой сфере, но отлично умел верстать и писать javascript. И в качестве верстальщика и javascript-программиста он с успехом проработал полтора года. Но самое главное в ответе на этот вопрос не в том, что говорит кандидат. Главное - КАК он это говорит. Он должен увлекаться. Он должен гордиться своим кодом, своими реализациями, своими, пусть даже "непромышленными" решениями. Я, возможно, неправ, но мне категорически не нравятся девелоперы с десятилетним стажем, которым "всё равно что писать"... Такие люди похожи на станки. Они включаются в 9.00 и выключаются в 17.30. С одной стороны в них нужно вставлять идеально оформленное ТЗ, а с другой у них выходит идеально документированный и покрытый тестами код. Выходит, конечно, медленно... И часто, когда выходит, то уже никому не нужен. И в первую очередь самим программистам. Им не станет стыдно, если у них найдут баг. Они не останутся на ночь, чтобы его исправить. Просто аргументируют перенос сроков. Когда-нибудь, наверное, IT станет такой же медленной и консервативной отраслью как, к примеру металлургия, и такие "станки" будут лучшим выбором. Но, надеюсь, это будет ещё не скоро. 
Второй вопрос: "Что лучше, XXXX или YYYY"? Варианты могут быть любыми: jQuery или Prototype, MsSQL или Sybase, Windows или Linux в конце концов. Поспорьте с ним. Во-первых кандидат должен иметь своё мнение. Пусть даже неправильное на ваш взгляд. И он должен уметь его аргументировать. И не бояться сделать это. И не быть в то же время совсем уж фанатичным. Хороший холивар - неплохой тест на интеллект и способность к общению. 
Задача этого этапа собеседования выяснить что может делать кандидат и КАК он это будет делать. А третий вопрос следует задать себе. "Приятно ли мне будет с ним работать"? Я не считаю, что замкнутость, дефекты речи или физическое уродство должны быть решающими факторами при принятии решения. Но свои 20% баллов третий вопрос должен положить на весы. Вам работать с этим человеком. Вам его прикрывать от порой "слишком энергичного" начальства, вам доверять ему свою репутацию, свой код, свой проект. Если вам не захочется делать это - это плохо отразится на работе. Лучше исключить такие проблемы в самом начале. 

Это не всё
Есть ещё пару десятков вопросов, которые стоит задать. Если в ответах почувствуете неуверенность, стоит дать предельно простую задачу, из тех, что можно "запрограммировать" на словах. Можно долго "пытать" кандидата на тему уровней изоляции транзакций, если для вашего проекта это так важно. Но всё это менее важно чем три главных вопроса.