Google App Engine & Java

Google нарешті таки вирішив, що наступна версія App Engine буде підтримувати Java. З самого початку пора. А ще би було добре позбутися декотрих дивних обмежень, як от, тривалість запиту, маскимальний розмір файлу тощо.

SoftReference & WeakReference: time of life

Well, I found some free time to write few articles. This one is about the SoftReference class from Java library.
SoftReference will help you to get the best variant between using memory and performance. Soft reference means that the value wrapped in soft reference will be garbage collected only and only if there are no free memory.
More about this. First I set -verbose:gc parameter for Java machine. If this parameter is set than GC logs will be output to the console. Also was set parameter -Xmx32m. The simple code:

void test() {
Reference<List> listRef = new SoftReference<List>(
Arrays.asList("1", "2", "3", "4", "5"));

List list = new LinkedList();
for (int i = 1; i <= 5; i++) {
list.add(new Object());

if (i == 5) {
if (listRef.get() == null) {
break;
}
i = 1;
}
}
}

Here the soft reference to the long string was created. The loop adds the references to the object to the linked list. Sometimes it checks whether the soft reference to the list of strings is not gc'ed; if it is than loop is breaked. Here is the output of GC:

[GC 896K->708K(5056K), 0.0059887 secs]
[GC 1604K->1603K(5056K), 0.0064902 secs]
[GC 2499K->2498K(5056K), 0.0064698 secs]
[GC 3394K->3393K(5056K), 0.0062198 secs]
[GC 4289K->4287K(5184K), 0.0061248 secs]
[Full GC 4287K->4287K(5184K), 0.0378679 secs]
[GC 5120K->5119K(8000K), 0.0141557 secs]
[GC 6015K->6014K(8000K), 0.0069241 secs]
[GC 6910K->6908K(8000K), 0.0064464 secs]
[GC 7804K->7804K(8768K), 0.0061396 secs]
[Full GC 7804K->7804K(8768K), 0.0595140 secs]

We may see that more than one Full GC were run before the soft reference was cleaned up.
The same test for the WeakReference (change new SoftReference(...) into new WeakReference(...)) prints next output:

[GC 896K->707K(5056K), 0.0063061 secs]

So, weak reference is cleaned up after the next first GC runs.
These tests were made on Java 1.6.0_10.
The outputs for Java 1.5.0_07 are respectively

[GC 512K->387K(1984K), 0.0047419 secs]
[GC 899K->898K(1984K), 0.0046456 secs]
[GC 1410K->1409K(1984K), 0.0048894 secs]
[GC 1921K->1920K(2496K), 0.0046743 secs]
[Full GC 1920K->1920K(2496K), 0.0203305 secs]
[GC 2431K->2430K(3776K), 0.0103943 secs]
[GC 2942K->2941K(3776K), 0.0048556 secs]
[GC 3453K->3452K(4032K), 0.0047855 secs]
[Full GC 3452K->3452K(4032K), 0.0340532 secs]
[GC 3964K->3963K(6332K), 0.0044411 secs]
[GC 4475K->4474K(6332K), 0.0049126 secs]
[GC 4986K->4985K(6332K), 0.0046232 secs]
[GC 5497K->5496K(6332K), 0.0045682 secs]
[GC 6008K->6007K(6588K), 0.0047892 secs]
[Full GC 6007K->6007K(6588K), 0.0523812 secs]
[GC 6775K->6774K(10848K), 0.0061404 secs]
[GC 7542K->7540K(10848K), 0.0065743 secs]
[GC 8308K->8307K(10848K), 0.0067296 secs]
[GC 9075K->9074K(10848K), 0.0066386 secs]
[GC 9842K->9841K(10848K), 0.0066439 secs]
[GC 10609K->10608K(11488K), 0.0066955 secs]
[Full GC 10608K->10606K(11488K), 0.1112694 secs]

and

[GC 512K->387K(1984K), 0.0049869 secs]


Since, these results show that Java 6 works with memory better than Java 5 and cleans up the soft reference faster than it is in Java 5.

Spring MVC + FreeMarker + Tiles 2

Може комусь і знадобиться ще. Тут описується як прикрутити Spring MVC та FreeMarker та Tiles 2 так, щоб вони жили та працювали разом.
Задача: Tiles2 повинен організовувати шаблони створені на основі FreeMarker (хоча можна і не тільки FreeMarker, можна поєднувати). Для того, щоб досягнути це необхідно виконати декотру конфігурацію. У файлі web.xml

<servlet>
<servlet-name>pages</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>pages</servlet-name>
<url-pattern>*.page</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>freemarker</servlet-name>
<servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>

<init-param>
<param-name>TemplatePath</param-name>
<param-value>/</param-value>
</init-param>
<init-param>
<param-name>NoCache</param-name>
<param-value>true</param-value>
</init-param>
<init-paramv
<param-name>ContentType</param-name>
<param-value>text/html</param-value>
</init-param>

....

<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>freemarker</servlet-name>
<url-pattern>*.ftl</url-pattern>
</servlet-mapping>

А тепер конфігурація pages-servlet.xml:

<!-- Конфігурація Tiles -->
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/defs/general.xml</value>
<value>/WEB-INF/defs/secure.xml</value>
</list>
</property>
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>

<!-- Контролер повертає view = /layout/header -->
<bean name="/layout/header.page" class="au.com.at2.web.spring.HeaderController"/>

Частина файла general.xml, в якому описуються оголошення Tiles:

<definition name="home" extends="default">
<put-attribute name="title" value="Home Page"/>
<put-attribute name="body" value="/templates/home.ftl"/>
</definition>
<definition name="default" template="/templates/main.ftl">
<put-attribute name="header" value="/layout/header.page"/>
<put-attribute name="footer" value="/templates/layout/footer.ftl"/>
</definition>
<definition name="/layout/header" template="/templates/layout/header.ftl"/>

Невеличке пояснення:
Спочатку добавив новий сервлет для FreeMarker'а. Всі шаблони в мене наразі стоять в каталозі templates, в той час, як TemplatePath для FreeMarker'а - це /. Я це зробив собі на майбутнє - для добавлення нових каталогів крім templates, - адже аплікація має розширюватися (вони завжди розширюються).
В pages-servlet.xml добавив bean tilesConfigurer, який будує конфігурацію для Tiles. Оголошення же знаходяться у файлах /WEB-INF/defs/general.xml, /WEB-INF/defs/secure.xml. При конфігурації інформація із них мерджеться, отже, оголошення default є доступним і в межах secure.xml.


<put-attribute name="header" value="/layout/header.page"/>

Цей кусок значить - можна використовувати як тайл і сторінку, що обробляється DispatcherServlet, таким чинном, ми можемо мати окремі контролери для окреми тайлів. І це правильно. Без цього би було туго. Контролер au.com.at2.web.spring.HeaderController повертає view /layout/header, який оголошений як definition в general.xml.

RichFaces + JSF RI + JBossPortletBridge + Liferay Portal on JBoss AS 4.2.x

The task to make few portlets for Liferay 5.1 Portal using RichFaces + JSF RI looks trivial. But it isn't.
There are few decisions:

  1. Use Liferay listener for Sun JSF with Sun's FacesPortlet.
  2. Use JBossPortletBridge, because it supports RichFaces and AJAX.

I choosed the second with understanding that JBossPortletBridge is in beta and everywhere says that it supports JBossPortal, but I did not find where says - "It supports Liferay too". It does not support Liferay Portal 5.0.
I found few interesting things, that anyone should know before starting write portlets with RichFaces for Liferay using JBossPortletBridge 1.0.x Beta:

  1. RichFaces should be at least 3.2.1.
  2. You should configure portlet as ajaxable with server side state saving policy
  3. Override the javax.portlet.faces.GenericFacesPortlet given with JBossPortletBridge. You'll need manually setup the request attribute javax.servlet.include.path_info with correct viewId you want to process and render. Or you can setup this request attribute at the PortletExternalContextImpl class in calculateServletPath() method (remember JBossPortletBridge 1.0.x Beta).
  4. Use <a4j:commandXXX/> components to process navigation. <h:commandXXX/> will not help ((.


Good luck!



Update:
My friend Andriy has described the solution with details and configuration samples, and you can find his post by the url http://www.liferay.com/web/guest/community/forums/-/message_boards/message/1712557. It really can be useful for you.



I've uploaded the portlet sample prototype, so it's ready and waits for you :)
http://www.esnips.com/doc/de8b5661-fb6d-4fc7-83a3-ed09aa72c695/PortletPrototype

Java 7

Java 7 в процесі написання. Цікаво знати які саме зміни мають попасти в реліз Java7. Тут можна знайти, що саме планувалося в реліз Java 7 , а ось тут - статус нових фіч станом на початок серпня.

Нажаль, closures - далекі від готовності, і зважаючи, що Ніл Гафтер покинув Google і перейшов працювати в Microsoft, є ризик, що closures не увійдуть до Java7. Проте є всі шанси, що switch для рядків, порівняння enum'ів попадуть в реліз. Але от підтримка операторів +, -, *, /, % для BigDecimal - ще далекі від кінця. Хоча це мені видається не менш важливим, ніж інші нововедення.

Для тих, хто не раз відчував дискомфорт при роботі із generics в Java - слід звернути увагу на type literals і type inference.

Invokedynamic - потрібний для підтримки динамічних мов.