tag:blogger.com,1999:blog-68273632805925329572024-02-08T08:24:51.703+02:00cat **/* | grep яAkshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.comBlogger25125tag:blogger.com,1999:blog-6827363280592532957.post-7143043971323260892009-08-02T14:05:00.003+03:002009-08-02T14:19:34.034+03:00Richfaces / Trinidad совсемстно с FaceletsПроапргрейдил существующий проект с Java 1.4 до Java 1.5, JSF 1.1 до JSF 1.2, реализацию JSF с Myfaces на Sun RI... и решил использовать в проекте какой-нибудь фреймворк предоставляющий AJAX для JSF. Первым попробовал Richfaces. Но оно как-то нестабильно заработало - то работает, то нет. Потратил два дня пытаясь понять почему, но безрезультатно. Затем попробовал Trinidad.. и с тем же успехом. Фреймворк работал нестабильно. Например, я открывал JSF страницу, и если кликал на AJAX'овую кнопку сразу после загрузки страницы, то все было нормально, запрос шел и обрабатывался, а если спустя пару секунд кликал, то запрос не обрабатывался и нужная часть страницы не обновлялась. Через какое-то время обратил внимание на странное и уже привычное сообщение в логах "INFO: Facelet[/page/blah.xhtml] was modified @ 14:23:24 AM, flushing component applied...". Оказалось, что это и есть причина проблемы. Время в виртуальной машине было на три часа меньше времени на компе на котором я собирал WAR файлы. Соответственно время создания файлов выглядила для websphere'ы на три часа из будущего. И похоже, что странный алгоритм Facelets обнаружения изменений в файлах начал сбоить по этой причине и перечитывать файл сбрасывая при этом дерево компонент! Решил проблему, установив facelets.REFRESH_PERIOD контекстный параметр в web.xml. Теперь оба фреймворка работают нормально. Осталось только определится какой я хочу..<ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com1tag:blogger.com,1999:blog-6827363280592532957.post-64383110558506913152009-07-06T12:36:00.004+03:002009-07-06T19:23:13.811+03:00Простое DSL на ScalaНедавно я начал использовать Scala для одного из моих домашних хобби проектов. Ранее я слышал, что Scala позволяет писать код таким образом, что он выглядит как DSL встроенный в саму Scala'у. Решил попробовать использовать эту фичу. Мне было необходимо придумать красивое API для шедулинга сообщений актерам (actors). Вот что из этого получилось:<br /><pre><br />final class TimeSpec[T] (number : Long, action : Long => T) {<br /> def nanoseconds = action (number)<br /> def microseconds = action (number * 1000L)<br /> def miliseconds = action (number * 1000L * 1000L)<br /> def seconds = action (number * 1000L * 1000L * 1000L)<br /> def minutes = action (number * 1000L * 1000L * 1000L * 60L)<br /> def hours = action (number * 1000L * 1000L * 1000L * 60L * 60L)<br /> def days = action (number * 1000L * 1000L * 1000L * 60L * 60L * 24L)<br />}<br /><br />final class Trigger (actor : MyActor, payload : Any) {<br /> def in (number : Long) = new TimeSpec[Unit] (number, scheduleIn)<br /> def every (number : Long) = new TimeSpec[Unit] (number, scheduleEvery)<br /><br /> private def scheduleIn (nanos : Long) = Scheduler.inNano (actor, payload, nanos)<br /> private def scheduleEvery (nanos : Long) = Scheduler.everyNano (actor, payload, nanos)<br />}<br /><br />final class ActorSchedule (actor : MyActor) {<br /> def payload (payload : Any) = new Trigger (actor, payload)<br />}<br /><br />trait MyActor ..... {<br /> protected val schedule = new ActorSchedule (this)<br /> ....<br />}</pre><ad></ad><br /><br />В результате получил возможность писать вот такой код:<pre><br />object TestActor extends MyActor {<br /> schedule payload `Hi in 10 nanoseconds<br /><br /> schedule payload `HowAreYou every 5 seconds<br /><br /> schedule payload `Bye in 5 days<br /><br /> def act () = {<br /> case `Hi => println ("Hello!")<br /> case `HowAreYou => println ("I am fine")<br /> case `Bye => println ("Bye-bye")<br /> }<br />}</pre><br />Идея в том, что schedule - это объект класса ActorSchedule. Этот класс предоставляет один метод payload имеющий один аргумент (собственно то, что будет послано актеру). В действительности "schedule payload `Hi" это вызов "schedule.payload(`Hi)". Этот вызов создаст объект класса Trigger. У класса Trigger есть два публичных метода in(Long) и every(Long). Так как эти методы не могут ничего полезного сделать до тех пор пока не будет известна единица измерения времени, то эти методы создают объекты TimeSpec передавая им в качестве параметра собственный метод, который будет вызван с количеством наносекнуд одним из методов класса TimeSpec.<br /><br />Как мне кажется получился достаточно простой и удобный API без особых усилий.<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-68035989963255122212008-08-11T19:31:00.001+03:002009-02-22T16:33:45.504+02:00Зедаржки в JavaТак как для задач управление домашней автоматикой я сделал не совсем очивидный выбор - Java, то, естественно, мне было необходимо настраивать работу Java приложения под требование иметь минимальные задержки на события. В результате, для того, чтобы получить имеющийся результат, пришлось предпринять следующие действия:<br /><ad2></ad2><br />1. Пускать приложение с schedtool -n -20 -R -p 1 -e /opt/mywire/bin/mywire<br /> Данная команда позволяет запустить приложение в realtime группе с приоритетом 1. Все приложение linux имеют приоритет 0 независимо от nice level'а. Таким образом работа нашего mywire всегда приоритетнее любой задачи.<br /><br />2. В некоторых критичных нитях, с помощью обращения к native методу происходит установка приоритета в значение 40. Таким образом внутри самого приложения нити имеют разные приоритеты. Это опасно и может привести к блокировкам!<br /><br />3. Для того, чтобы ни в коем случае mywire не оказался в свопе, память лочится с помощью обращения к native методу mlockall.<br /><br />4. Сам java процесс пускается со следующими опциями:<pre><br /> -Xms30m -Xmx64m -XX:PermSize=15m -XX:MaxPermSize=30m<br /> -XX:+UseTLAB -jvm server<br /> -XX:MaxGCPauseMillis=20 -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode<br /> -XX:+CMSClassUnloadingEnabled<br /> -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses<br /> -XX:+BackgroundCompilation</pre><br /> Количество памяти, которое я отдаю под heap выбранно таким образом, чтобы сразу после сборки мусора (full gc), свободной памяти было где-то 60%.<br /><br />Надеюсь ничего не забыл. Как результат мы имеем задержки порядки 10-16мс. При том, что библиотека quartz сама работает с дискретеностью в 10мс. Тоесть если ей сказать, что таску нужно запустить через 5мс, она ее все равно запустить через 10.<br /><br />К сожалению раз в час происходит full gc или что-то типа того и это влечет за собой неожиданные задержки. Величина зависит от того, как совпадут время срабатывания и начало сборки мусора. В среднем это 200мс. Бывает и 500мс и 700мс. Будем думать как это побороть.<br /><br />Вот графики:<br />Latency:<br /><img src="http://toril.ru/lj/hour.rrd.png"><br /><br />Память.<br /><img src="http://toril.ru/lj/phour.rrd.png"><br /><ad></ad><br />Видно, что в момент сборки мусора был всплеск задержек.<br /><br />Предугадывая вопросы:<br /> Java - чтобы писать быстрее.<br /><br /> Latency - в данном случае, это разница времени момента срабатывания таймера и времени, в которое данный таймер должен был сработать. Тоесть, например, если было сказано спать 100мс, а таймер проспал 120мс, то задержка 20мс.<br /><br /> Важность Latency заключается в том, что опрашивать некоторые датчики необходимо весьма часто, скажем датчик движения 2 раза в секунду. В моем варианте датчик движения замыкает размыкает контакты конденсатора давая ему зарядится, таким образом датчик напряжения 1-wire успеет заметить какой-нибудь заряд, даже если он пропустит сам импульс. Так вот если Latency будет слишком высокой (скажем 2-3 секунды), то срабатывания датчик может просто остаться незамеченным.<br /><br /> Кто озадачился вопросом, почему датчик движения не может сам сообщить о срабатывании, отвечу: 1-wire сеть может иметь только одного master'а, все остальные slave'ы.Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-32937817545952371742008-08-11T11:35:00.002+03:002009-02-22T16:32:34.122+02:00Home PortalДомашний портал. Эта та страничка, что стоит в браузере как home page. Отсюда я/жена читаю новости, смотрю погоду за окном (графики влажности, температуры), наблюдаю за работой сервера и т.д. Предназначен он для home automation (ну там энергосберегающий умный дом (smarthouse) и т.д.). Работа в свободное время. Сбор информации и управление 1-wire, в будущем будет еще X-10 (управление светом), камеры и т.д.. Много всего написано, но на сервере на production сервере еще не выложено. Сам портал напроч AJAX'ный, перегрузок страниц не требует. В качестве платформы Jboss Portal + DOJO (следующие портлеты будут без dojo, но на GWT). В качестве ядра, standalone java process со стеком spring + termware + quartz и т.д.<br /><br />Но вообще пост не об этом, а о двух подряд идущих анонсах в ленте torrent.net.ua (см. скриншоты).<br /><ad></ad><br /><a href="http://toril.ru/lj/homeportal.png">Картинка 1</a><br /><a href="http://toril.ru/lj/homeportal2.png">Картинка 2</a><br /><a href="http://toril.ru/lj/homeportal3.png">Картинка 3</a>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-87828215752499460962008-07-10T16:48:00.003+03:002009-02-22T16:32:00.178+02:00Выбор domain языкаПредположим нужно контроллировать некоторую автоматику. Для этих целей необходимо выбрать способ формализации алгоритмов управления. Короче и проще говоря, нужен язык со следующими, как мне кажется, требованиями:<br />1. Имеющий реализацию интерпретатора на Java.<br />2. Парсинг исходного кода в runtime'е, а не предварительно.<br />3. Локоничный.<br />4. Расширяемый словарь.<br />5. Возможность захватывать состояние выполнения... мммм.. как это по-русски.. continuationы.<br /><ad></ad><br />Это может быть что угодно, функциональный, императивный, декларативный, rewriting engine, macro и.д.<br /><br />Пример псевдокода, который должен писаться на целевом языке не намного более длиннее чем это:<pre><br />Loop:<br /> T = GetCurrentTemperature<br /> State = AccordingToMode ( If (T < REQUIRED_T, On, Off) )<br /> SetDeviceState ("HeaterDevice", State)<br /> WaitEvent (Polled("TemperatureDevice"), ModeChange)<br /></pre>При этом, в момент вызова WaitEvent выполнение скрипта должно прерваться с сохранением состояния, чтобы я дальше мог продолжить выполнение после WaitEvent. Как это предполагается использовать из Java (типа того):<br /><pre>Script script = Script.prepare (scriptSource);<br />ScriptYield yield = script.run ();<br />eventManager.addPendingScript (yield.getScriptState(), yield.getResult());</pre><br />а где-то позже, может быть очередное:<br /><pre>ScriptYield yield = scriptState.continue ();</pre><ad2></ad2><br />Я не много хочу? :)<br /><br /><b>Update:</b> Groovy не поддерживает cont-ions, jpython из-за отступов не получится никуда встроить толком, jruby не поддерживает (fiber в виде нитей не канает)... ищем дальше<br /><br /><b>Update:</b> По результатам подошел <a href="www.gradsoft.ua/products/termware_eng.html">TermWare</a>.Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-56443822850408751582008-06-20T16:39:00.001+03:002009-02-22T16:30:36.899+02:00Документация AspectJЕсли кто-то как и я документацию читает только по-необходимости, то так же как и я может попасть в ловушку при чтении доки на AspectJ. Например глядя на <a href="http://www.eclipse.org/aspectj/doc/released/devguide/ltw-configuration.html#configuring-load-time-weaving-with-aopxml-files">пример</a>:<pre><br /> <include within="javax.*"/><br /> <include within="org.aspectj.*"/><br /></pre><br />может показаться, что аспекты будут применены ко всему, что внутри javax.*, на самом деле это не так ибо, аспекты будут примены только к тем классам, что в javax ни больше ни меньше. Т.е. к классам внутри javax.security это не относится. А если учесть, что непосредственно в javax пакете вообще нет ни одного класса (или есть, но я по памяти не помню), то пример явно идиотский. Короче, должно там быть на самом деле "javax..*"...<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-49431107635304533212008-06-03T23:27:00.001+03:002009-02-22T16:30:04.069+02:00GWT (1.5)Очень странные ощущения. После возни с AJAX'овыми вещами с помощью JavaScript'а, писать клиентский код на Java просто сказка. Если скомпилировалось - значит заработает. Но компилируется не всегда - к этому надо просто привынуть. Например GWT.create принимает в качестве аргумента Class, но не тут-то было. Например код:<br />Class c = MyService.class; // или получено из аргумента<br />MyServiceAsync svc = GWT.create (c);<br />Прервет компиляцию с сообщением "Only class literals may be used as arguments to GWT.create()".<br /><br />Подход к package structure, который вроде как strongly recomended, весьма странен с моей точки зрения. Ну сабпакаджи client и server весьма логичны, но вот сабпакадж public - сомнителен (в него предполагается ложить ресурсы как я понял(?)). Более того, client классы не могут зависить от server классов. Т.е. нельзя ложить интерфейс сервиса в package server - его нужно ложить в пакадж client, а в server'е должна лежать только имплементация этого сервиса. Получается по сути таже tier based архитектура, но только наоборот. В классической (ну той к которой я привык), клиентская часть знает о серверной, но не наоборот. А в GWT'ной модели, как раз наоборот получается: серверная часть пользуется классами из клиентской (наследует интефрейсы которые хочет видеть клиент). Собственно это при желании можно обойти сделав отдельный GWT-Module для какого-то отдельно пакаджа с общими классами.. но это ж делать надо и против recomended structure. Впрочем я с первого же дня забил на эту структуру и разложил все по своему - главное понимать, что делаешь и тогда все работает.<br /><ad></ad><br />Сервисы-сервлеты в Module.gwt.xml не прописываю. Заюзал spring-mvc: прописал в web.xml его диспатчер, а в app context'е прописываю сами сервисы-контроллеры (для spring-mvc они контроллеры, а для gwt они сервлеты, а для клиента они сервисы). Получилось красиво весьма. Пока нравится.<br /><br />По уровню boilerplate'ности напоминает EJB 2.1.Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-81152381124525005992008-05-28T22:45:00.001+03:002009-02-22T16:29:28.079+02:00Hibernate vs JDBCJDBC изначально содержит совсем небольшое количество кубиков-понятий для работы с базами данных, что делает его простым в использовании инструментом и в тоже время достаточно гибким оставаясь понятным. Hibernate и прочие ORM (включая JPA) - это в некотором роде макро-абстракция над JDBC. Изначально кажется, что ORM позволяет абстрагироваться от синтаксиса конкретной базы данных и упростить запросы, сократить процесс переноса данных из запроса в домэйн обьекты. Но чем больше я работаю с ORM тем больше понимаю, что абстракция от базы данных на практике мало нужна, разве в простых приложениях. А простота маппинга достигается за счет оверхеадов при работе, сложности с маханизмами каскадирования, дэтачмента обьектов, майнтененсом сессии и в конце-концов выясняется, что временя потраченное на поиск причины сообщения о проблемы с транзиентными записями, попытке приаттачить обьект внутри сессии, с валидацией полей, проблемами ленивой подгрузки обьектов и прочих проблем.. это время равносильно, а то и больше времени которое было бы потрачено на разработку с JDBC + портирование приложения на новую базу (с учетом, что изначально в коде используется шаблон проектирования DAO). ORM привносит обилие новых понятий, сущностей и рычагов, добавляет mutual состояния (а мы знаем, что чем меньше в приложении мутирующих перменных/состояний, тем более стабильно приложении (именно по этому фнкц-языки рулят)), что очевидным образом вытекает во все что я описал в предыдущем предложении. Есть ли смысл?<ad></ad><br />Есть такой фреймворк iBatis. Судя по названию сначала кажется, что делали его славяни (особенно с учетом н овости на главной странице "Abator Renamed to iBATOR"). Но вот заяление "iBATIS couples objects with stored procedures or SQL statements using a XML descriptor. Simplicity is the biggest advantage of the iBATIS Data Mapper over object relational mapping tools." притягивает. И вообще как оказалось замечательный фрэймворк!Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-48254958294286461172008-05-28T22:10:00.001+03:002009-02-22T16:28:50.937+02:00Flash, JavaFX, Silverlight, FlexВ эпоху достаточной конкуренции среди одинаковых веб услуг, появление модного слова AJAX показало, что пользователи хотят видеть веб сайты не просто информативными, но с красивым гуевым интерфейсом. Осознав это, компании, практически одновременно, принялись "первыми" выкидывать на рынок или просто разрабатывать новую технологию которая непременно же должна заменить HTML и сделать internet application'ы не просто Rich, а как я услышал в одном докладе на SUN'вской конференции прямо таки Filthy Rich! И все это под open source. Ну прям таки не жизнь, а мед грядет. За что я люблю веб over обыкновенное приложение (пусть оно хоть трижды filthy like a whore):<ad></ad><br />1. Любую вэб страницу я могу отмасштабировать (увеличить или уменьшить шрифт).<br />2. Выключить стили мега дизайнера нахрен.<br />3. Сохранить отдельную страницу.<br />4. Поставить ссылку на отдельную страницу.<br />5. Вернуться на пару страниц назад.<br />6. Окно можно растянуть или сжать не в ущерб содержимому. При этом браузер все красиво переформатирует.<br />7. И т.д.<br /><br />Все это конечно же можно реализовать и плагином, но я уверен, что 90% RIA сайтов делать этого не будут. Короче все это бред и лажа. По крайней мере в том виде в котором оно сейчас есть в виде флэша или ему подобных технологий.<br /><br />Что я точно не понимаю, так это стратегию компании SUN. Ну ладно, хрен с ними с апплетами. Проипали они это поле битвы. Но почему бы в джава плагин не встроить нативно API для интеграции с DOM и Javascript? Модифицировать DOM дерево страницы браузера вроде бы можно, но я так и не нашел, читая javadoc, способа, как например из java повесить свой java handler для onclick или другого event'а какого-то узла этого DOM дерева. Сдается мне, что все на что хватает интеграции из коробки - удалять/добавлять узлы DOM дерева. Есть сбоку LiveConnect, но во первых он сбоку. А во-вторых что с event'ами сходу не понятно, но вроде как есть надежда. Ну чтож, хрен с ними с евентами, может что-то и получилось бы. НО!! Компания САН уже несколько лет не в состоянии выпустить плагин под 64 битные платформы (с 2004го кажется)... и обещают они выпустить java plugin к 2009г. Какие нахрен апплеты, какие RIA..?<br /><br />А всего-то. Была бы в джаве вместо всей этой мега-графической мега-херни для создания мега-никому-не-нужных-грязных-апплетов возможность работать с деревом DOM и событиями - небыло бы необходимости в виде костылей GWT (компиляция из ограниченного сабсета Java в Javascript), потому как это java код напрямую бы работал и делал все, что сейчас делается на JS. Те же GWT виджеты и т.д. все бы было, но с отладкой прям в браузере, мониторинг по JMX и прочие прелести разработки и отладки java standlone, но в вебе. Такое чувство, что в сан только и могут языком трепать и евангелистов разбрасывающих дюков по миру катать.<br /><br />А пока пойду попробую GWT 1.5rc1...<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-66491396845841042622008-04-27T20:03:00.001+03:002009-02-22T15:48:55.600+02:00Linux: Thread Priorities in JavaГрустно мне. Приоритеты нитей в linux джава игнорирует.<br /><a class="snap_shots" href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4813310">http://bugs.sun.com/bugdatabase/view_bu<wbr>g.do?bug_id=4813310</a><br /><br /><b>Update:</b> Решение кажется нашел. Разберусь до конца опишу подробнее.<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com1tag:blogger.com,1999:blog-6827363280592532957.post-5910942518382713162008-04-06T20:36:00.001+03:002009-02-22T15:50:20.548+02:00Ускорение JRobin 1.5.8Уже наверное месяц назад написал патч для JRobin и сегодня вот запостил его в sourceforge для этого проекта. Патч увеличивает производительность раз наверное в 10 при интенсивном использовании CDef'ов и как минимум раза в 1.5 для графиков без CDef'ов. Не знаю включат этот патч в проект или нет - мне пофигу. Также патч расширяет возможности класса Plottable позволяя реалзиовывать графики аналогичнее CDEF'овым, но значительно мощнее и быстрее. Помимо всего этого, имеется возможность рисовать поверх графика все что угодно.<br /><br /><a href="http://toril.ru/soft/jrobin-1.5.8-speedup.patch.gz">Патч</a><ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-55956002965754623892008-04-06T19:26:00.001+03:002009-02-22T15:51:08.366+02:00Sun Tech Days 2008Сьздил в Питер на сабж. В очередной раз убедился, что на таких конференциях мне делать нечего. Мне нужно на net ехать - я там ничего не знаю. А конференции по Java...? Похоже в области java я и так достаточно осведомлет о всяких там фрэймфорках типа GWT, DOJO, WICKET, JPA, о новинках в Java 5, Java 6, Java 7 на том уровне на котором об этом рассказывают на конференциях. Практически ничего нового я нигде не узнал. Хорошое снотворное - прям какбудто всю ночь учил экзамены.<ad2></ad2><br /><br />Из интересных докладов для себя: java hotspot. bpel (хоть я мало че понял), G1.<br /><br />Пару слов про организацию мероприятия. Жесть. Прям как на концерт Moonspell или Cradle Of Filth. В здание пускали по 10 человек а потом 10 минут перерыва. Перед входом толпа и давка. Внутри очереди на регистрацию и девочки с формами (и в фирменной сановской форме). Везде непрерывно раздавали бланки для участия в викторинах или просто опросники за которые давали призы или сувениры. Мне было вломы заполнять всю эти простыни поэтому я уехал из Питера без: нового рюкзака с логотипом Сан, кружки с логотипом Сан, плюшевого Дюка, футболки и дисков с солярисом.<br /><br />А вообще хорошо отдохнул. Прям отпуск непредвиденный :). Питер и вправду весь серый. Но только он серый не потому, что старый или построен из строительных материалов такого оттенка. НЕТ. Просто он весь в пыли. Пыль кругом: на стенах, на поручнях, на асфальте, в воздухе...<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-59544764853233511332008-02-13T15:02:00.001+02:002009-02-22T15:52:07.101+02:00YourKit Java Profiler vs JProfilerЭто первое впечатление по вторичным <s>половым</s> признакам. Никакого глубокого анализа :).<ad2></ad2><br /><br />1. <b>Лицензия.</b> И тот и тот продукт необходимо покупать. У обоих есть возможность получить eval лицензию, которая дает полную функциональность, но с ограничением по времени. YJP к томуже имеет community лицению, которая выдается по заявке группе разработчиков известного открытого софта.<br /><br />2. <b>"Тонкости лицензирования".</b> JProfiler проверяет пригодность лицензии как на клиенте так и на агенте (сервере). Поэтому время на сервере в случае использования eval лицензии должно быть актуальным. YJP только на клиентской части.<br /><br />3. <b>Юзабилити.</b> YJP позволяет настраивать шрифты. Для меня это важно.<br /><br />В остальном по функциональности они мне показались похожими. На основе этих трех пунктов я уже сделал выбор в пользу YJP :)<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-82143163200777236722008-02-10T14:45:00.001+02:002009-02-22T15:52:55.148+02:00Java 6 & AMD64JIT в Java 6 update 4 на amd64 ужасно глючная вещь все время где-то падает (например eclipse падает на компиляции класса). Поэтому если нужно юзать java 6 на amd64, а оно падает, то можно заюзать ключик -Djava.compiler=none - это отключает JIT. Если цели использовать именно Java 6 нет, то можно поставить Java 5 update 14 оно вроде бы работает стабильно.<br /><pre><br />Current thread (0x00002aab2d10e800): JavaThread "CompilerThread1" daemon [_thread_in_native, id=20462, stack(0x00000000406b2000,0x00000000407b3000)]<br /><br />siginfo:si_signo=SIGSEGV: si_errno=0, si_code=1 (SEGV_MAPERR), si_addr=0x0000000000000000<br /><br />Registers:<br />RAX=0x0000000000000000, RBX=0x00002aab311cc4d8, RCX=0x00002aab3137e9b0, RDX=0x0000000000000046<br />RSP=0x00000000407aee70, RBP=0x00000000407aeee0, RSI=0x00002aab3137e9b0, RDI=0x00002aab311cc4d8<br />R8 =0x00002aab3137ea08, R9 =0x00002aab3137e9b0, R10=0x00002aab3137e9b0, R11=0x0000000000000000<br />R12=0x00002aab311cc4a0, R13=0x0000000000000000, R14=0x00002aab2cd3b870, R15=0x0000000000000001<br />RIP=0x00002b5f70ae122a, EFL=0x0000000000010246, CSGSFS=0x0000000000000033, ERR=0x0000000000000004<br /> TRAPNO=0x000000000000000e<br /><br />Top of Stack: (sp=0x00000000407aee70)<br />0x00000000407aee70: 00002aab30548b88 00000001ffffffff<br />0x00000000407aee80: 00002aab3137e9b0 0000000270a85331<br />0x00000000407aee90: 00002aab30548b80 00000007407afaa0<br />0x00000000407aeea0: 00000000407afb68 01000000000004a7<br />0x00000000407aeeb0: 00000000407afaa0 00002b5f7112a4f0<br />0x00000000407aeec0: 00000000407afaa0 00000000407af030<br />0x00000000407aeed0: 00000000407aeff0 00000000407aefc0<br />0x00000000407aeee0: 00000000407af100 00002b5f70ae076c<br />0x00000000407aeef0: 00000000407afb68 00000000407af0b0<br />0x00000000407aef00: 00002aab330b0fb0 00002aab30000020<br />0x00000000407aef10: 00000000407aef80 00002b5f711438d0<br />0x00000000407aef20: 00002aab307d8a20 0000000000000151<br />0x00000000407aef30: 00000000407afbc0 00002b5f70608bbc<br />0x00000000407aef40: 00000000407b2950 00000000407aef80<br />0x00000000407aef50: 00002b5f71146040 00002aab3100b990<br />0x00000000407aef60: 0000000000000151 00002b5f70f1a9d2<br />0x00000000407aef70: 0000000040110b90 00002b5f70f1aaa1<br />0x00000000407aef80: 00000000407b2950 00000000407aefc0<br />0x00000000407aef90: 00002b5f71146040 0000000000007fe8<br />0x00000000407aefa0: 00002aab307f5d10 00002b5f70f1a9d2<br />0x00000000407aefb0: 0000000040110b90 00002b5f70f1aaa1<br />0x00000000407aefc0: 00002b5f7112a4f0 00002b5f0000000e<br />0x00000000407aefd0: 00000000407b1450 00000000407afaa0<br />0x00000000407aefe0: 00000000000008c8 00002aab2d10ec70<br />0x00000000407aeff0: 000000000000000d 00000000407b1450<br />0x00000000407af000: 00002aab32c78490 00002b5f70a84d00<br />0x00000000407af010: 00002aab311bd4b0 00000000000004a8<br />0x00000000407af020: 00000000407af0b0 00002aab332443e0<br />0x00000000407af030: 000000000000000c 00000000407b1450<br />0x00000000407af040: 00002aab3178f090 00002aab31ce1aa0<br />0x00000000407af050: 00002aab3184eb70 00002aab3184f6b0<br />0x00000000407af060: 00002aab330c8c60 00000000407afbc0<br /><br />Instructions: (pc=0x00002b5f70ae122a)<br />0x00002b5f70ae121a: 48 89 cf 41 ff 95 80 00 00 00 48 89 df 49 89 c5<br />0x00002b5f70ae122a: 8b 00 41 21 44 24 38 41 8b 45 04 21 43 04 41 8b<br />Stack: [0x00000000406b2000,0x00000000407b3000], sp=0x00000000407aee70, free space=1011k<br />Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)<br />V [libjvm.so+0x1f122a]<br />V [libjvm.so+0x1f076c]<br />V [libjvm.so+0x244525]<br />V [libjvm.so+0x241035]<br />V [libjvm.so+0x1e05c7]<br />V [libjvm.so+0x248ec8]<br />V [libjvm.so+0x248866]<br />V [libjvm.so+0x62a3f9]<br />V [libjvm.so+0x6246a1]<br />V [libjvm.so+0x505eea]<br /><br /><br />Current CompileTask:<br />C2:581 org.eclipse.core.internal.dtree.DataTreeNode.forwardDeltaWith([Lorg/eclipse/core/internal/dtree/AbstractDataTreeNode;[Lorg/eclipse/core/internal/dtree/AbstractDataTreeNode;Lorg/eclipse/core/internal/dtree/IComparator;)[Lorg/eclipse/core/internal/dtree/AbstractDataTreeNode; (469 bytes)<br /></pre><ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-57095419996486870542008-01-08T14:11:00.000+02:002009-02-18T21:37:18.153+02:00CAL & ScalaРешил заюзать что-то отличное от Java для своего очередного домашнего хобби проекта (ну и изучить новую технологию как обычно...). Впечатление после чтения документация во время прибывания в Омске.<br /><br />CAL (Quark Framework) - прикольно все-таки, что это Haskell для Java, но вот что-то интеграция с Java меня не впечатлила - чисто на урове FFI как в Haskell. Как домэйн язык оно может и удобно, но как полная замена Java не катит. Правда сильно не вчитывался - может и не прав.<br /><br />Scala - весмьа красиво и многообщеюще. Почему-то постоянно слышал про этот язык несколько лет назад, когда читал рассылку O'Caml, но ни разу Scala не удосужился попробовать. А зря, весьма элегантно. Немного расстроило отсутствие поддержи Scripting for Java (не помню номер JSR).Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-30412312866995072682007-10-19T13:18:00.003+03:002009-02-22T16:06:05.285+02:00JSF & FaceletsВ чем была суть проблемы:<br />Когда в facelet'ах мы создаем template или tag на основе template'а, мы можем передавать в него параметры. Например custom tag с именем link имеет параметр myCoolAction, а тушка определения тэга выглядит банально:<br /><h:commandLink action="#{myCoolAction}"><br />Мы пользуемся тэгом:<br /><customNs:link myCoolAction="hello"><br />И ожидаем, что это равносильно <h:commandLink action="hello">.<br />Но не тут-то было. Facelet'ы передает аргументы внутрь template'а заворачивая их в ValueExpression. Тоесть у action аттрибута значение на самом деле оказывается не типа String, а типа ValueExpression. Умный commandLink это просекает и решает, что раз это не string, то это биндинг! А как же? Что это может быть еще? И обламывается. Ибо после eval'а на ValueExpression он таки получает String, а не MethodExpression - как нужно для биндинга к методу. Вот такая вот фигня.<br /><br />Мне удалось это вылечить написав на java другой custom tag, который берет ValueExpression и превращает его в MethodExpression возвращающий оригинальный ValueExpression. Костыль.<ad></ad><br /><br />На самом деле, это не самое страшное в faceletах. Хотя признаюсь, без facelet'ов JSF хочется об стену убить.Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-51212922785009141812007-03-09T14:23:00.003+02:002009-02-22T16:11:10.161+02:00LPTRAДля EE фанатиков, я реализовал адаптер ресурсов (JCA 1.5 через CCI), это правильный способ работы с параллельным портом из J2ee приложения. Чтобы использовать адаптер, нужно установить <a href="http://rus.akshaal.info/2007/03/uparport.html">UParPort</a>. Затем продеплоить <a href="http://toril.ru/soft/LPTRA.rar">этот RAR</a> (resource adapter archive) в сервер приложений. Когда это будет сделано, создайте датасоурс для LPTRA. При создании надо будет указать имена пинов, типа такого: 1PinName=eye1, 2PinName=eye2 и т.д.. Вот и все. В дополнение можно сказать <a href="http://toril.ru/soft/LPTRA.tar.gz">исходники LPTRA</a>.<br /><br /><b>Пример:</b><br /><ad></ad><pre>@Resource (name = "eis/ParPort")<br />private ConnectionFactory connFactory;<br /><br />Connection conn = null;<br />try {<br /> conn = connFactory.getConnection();<br /> Interaction interaction = conn.createInteraction ();<br /> MappedRecord r =<br /> connFactory.getRecordFactory ().createMappedRecord ("");<br /><br /> r.put ("eye1", true); // turn eye1 pin into the on state<br /> r.put ("eye2", false); // turn eye2 off<br /> interaction.execute (null, r);<br />} catch (ResourceException e) {<br /> e.printStackTrace (); // Not sexy<br />} finally {<br /> if (conn != null) {<br /> try {<br /> conn.close();<br /> } catch (ResourceException e) {<br /> e.printStackTrace (); // Not sexy<br /> }<br /> }<br />}<br /></pre>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-39977432015334182322007-03-09T13:29:00.001+02:002009-02-22T16:11:47.920+02:00UParPortДавно я планировал выложить эту программку. UParPort - библиотека для работы с параллельным портом (портом принтера) из Java программ. Но в отличии от <a href="http://www.geocities.com/Juanga69/parport/">parport</a>, эта библиотека не требует привилегий root'а. Есть главный класс UParPort в пакете package ru.toril.uparport. В качестве аргумента он получает имя устройства. Имя устройства выглядит типа "/dev/par0" или "lpt1". После создания экземпляра класса можно использовать следующие методы: getData, getStatus setData, close. isClosed, toString. Итак, <a href="http://toril.ru/soft/uparport.zip">бинарники</a> и <a href="http://toril.ru/soft/uparport.tar.gz">исходники</a> UParPort..<ad></ad>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-81867000601037101212007-01-01T04:56:00.001+02:002009-02-22T16:20:55.037+02:00Перечитывая спецификациюДжава как язык сдохнет под тяжестью собственной распухшей спецификации.<br /><br />Чем меньше в языке синтаксических конструкций тем язык красивее и логичнее. Например лямбда исчисление... красота. Хаскелл - можно реализовывать в терминах языка те фичи которые в других языках зашиты в сам язык. Язык форт - алфавит языка до ужаса прост и расширяем.<br /><br />Может в качестве хобби покомпилировать хаскелл в джава байт код? Есть ли смысл в таком?<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-19271257375220412982006-10-17T01:24:00.001+03:002009-02-22T16:24:44.289+02:00JCAДопустим мы пишем JCA RA который поддерживает исходящие соединения к EIS. Все написали. Верифицировали. Продеплоили в GlassFish. Все OK. Теперь продеплоили какое-то приложение, чтобы протестировать соединение к EIS. Запускаем. А оно нам @#%!: "Exception in NamingManagerImpl copyMutableObject() ... java.io.NotSerializableException".<ad></ad><br />Покопавшись мы выясняем, что падение происходит при копировании нашей имплементации java.resource.cci.ConnectionFactory интерфейса. А имеено в нашем классе ConnectionFactoryImpl есть не Serealizable поле, например ManagedConnectionFactory (содержащая сокет например). Убив N часов времени на поиски в гугле, выясняем, что GlassFish в JNDI помещает копии объектов! Наматерившись и решив, что разработчикам JNDI реализации виднее, мы делаем неугодное в ConnectionFactoryImpl поле transient'ым. А вдруг этот объект будет использоваться, только чтобы getReference вызвать? Хрен там. Повозившись еще, оказывается, что dependency injection отдает нам именно копию из JNDI у которой наше transient поле установленно в NULL!<br /><br />Даём GlassFish'у последний шанс. Читаем его исходники и оказывается, что не все объекты помещаются в JNDI в сереализованном виде. Так например Connector'ы должны помещаться не сереализованными! Хм, а как же оно определяет, что этот объект коннектор? А вот как:<br /><pre><br /> private boolean isConnector(String logicalJndiName){<br /> return (logicalJndiName.indexOf(EIS_STRING)!=-1);<br /> }<br />где EIS_STRING = "/eis/".<br /></pre><br />Короче, чтобы не иметь лишний геморрой: ConnectionFactory экземпляры должны помещаться в субконтексте /eis/ ! Если теперь поискать в гугле по словам "eis subcontext" то находятся <i>рекомендации</i>, а не <i>требования</i>!.<br /><br />Вообще, это частая ошибка, проявляется в виде NPE (null pointer exception) при вызове transient полей (activemq этим страдает). Мне кажется, в ConnectionFactoryImpl разумно вставить:<br /><pre><br /> /**<br /> * Ensure that managedConnectionFactory is not null.<br /> * @throws ResourceException if managedConnectionFactory is null.<br /> */<br /> protected void ensureManagedConnectionFactory () throws ResourceException {<br /> if (this.managedConnectionFactory == null) {<br /> throw new ResourceException (<br /> "No reference to managed connection factory exists."<br /> + " Either it is a bug of the RA or your JNDI resource"<br /> + " is not in the /eis/ subcontext");<br /> }<br /></pre><br />и вызывать этот метод перед использованием this.managedConnectionFactory внутри ConnectionFactoryImpl.<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-73866327387481698142006-10-11T10:36:00.001+03:002009-02-22T16:25:32.327+02:00Из спецификации по JNI"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-54775803480297138042006-10-09T09:57:00.002+03:002009-02-22T16:25:58.418+02:00Смысл javax.resource.cci.*Я наконец-то понял зачем нужен CCI. Все время казалось, что из-за него в простых RA много ненужного кода. А теперь ощутил зачем этот CCI нужен.<br /><br />Если реализовывать RA без CCI, то наш MCF возвращает CF который не CCI-compliant, а тот уже в свою очередь по запросу RA клиента делегирует обращение в RM и получает соединение к RA отдавая его клиенту. Все просто и хорошо, но:<br />- в этом случае мы не может использовать DI, оказывается @Resource работает только для набора предопределенных интерфейсов (типа тогоа же CCI CF), поэтому CF придется ручками из JNDI доставать.<br />- если RA не продеплоена как EAR, а задеплоена в виде одельного RAR файла и клиент RA задеплоен соответственно как отдельный JAR, то, чтобы клиент мог использовать наш собственный CF, у него должен быть на руках интерфейс этого CF. В случае CCI CF этого не требуется, так как CCI CF определен в java.resource.cci.<br />- наверное есть еще что-то, но мне хватило этого<br /><ad2></ad2><br />Доздравствует CCI!Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-47844984799003106212006-10-05T12:33:00.001+03:002009-02-22T16:26:35.172+02:00SUNWappserver uninstallЕсли кто-то пытается переустановить Sun Application Server 9.0 Platform Edition и у него не получается это в течении часа (то already installed, то unexpected exception), то стоит грохнуть нахрен (или аккуратно почистить) /var/tmp/productregistry или /tmp/productregistry.<br /><br />Навеяно <a href="http://docs.sun.com/app/docs/doc/819-3664/6n5sbeo20?a=view">вот этим советом</a> в котором неправильно указан путь.<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-75824682153516605502006-10-04T23:02:00.001+03:002009-02-22T16:27:11.534+02:00Mastering EJB 4edОфигенный код в книге Mastering EJB 4ed!<br />Chapter 15, конец метода execute:<br /><b><pre>if (out != null) {<br /> return true;<br />} else {<br /> return false;<br />}<br /></pre></b>класс! :))<ad></ad><br />А еще в этой книге есть строки в раздели Best Practice:<br /> <i>Many organizations have tried—and failed—to truly reuse components. Because of this, it is a perfectly valid strategy to not attempt true reuse at all. Rather, you can shoot for a copy-and-paste reuse strategy, which means to make the source code for components available in a registry to other team members or other teams. They can take your components’ code and change it as necessary to fit their business problem. While this may not be true reuse, it still offers some benefits.</i><BR><H6><I>Эта запись писалась в течении 7 минут 37 секунд.</I></H6>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0tag:blogger.com,1999:blog-6827363280592532957.post-30590049480443722042006-03-29T22:03:00.001+03:002009-02-22T17:00:13.072+02:00JDeveloperНаконец-то поставил Oracle JDeveloper 10g на ноутбук. Не могу нарадоваться. После подучих и тормозных eclipse'ов прям бальзам на "душу". Хоть месяца три ничего не java и не писал, но все равно приятно..<br /><br />Себе на будущее, чтобы не искать потом, отмечу, что системный шрифт в нем настраивается через файл ${HOME}/jdevhome/system/oracle.jdeveloper.${JDEV_VERSION}/ide.properties<ad2></ad2>Akshaalhttp://www.blogger.com/profile/05677582369584740657noreply@blogger.com0