Simple LRU cache implementation.

By this url can be found post about using LinkedHashMap as LRU cache. Also, I've found such code with a direct link as comment in Apache Roller source code.
LinkedHashMap can be used as LRU cache because it supports ordering it's elements not only by insert order, but also by access-order. Also there is protected method removeEldestEntry in the LinkedHashMap that runs in the put() and putAll() methods. If that method returns true, than least recently inserted/accessed element will be removed.

You and your's sofware expansibility.

For a long time one of the scores of software I'm writing is expansibility. That's mean how fast, with minimum of changes, I can add new features or extend existed one.
I've made few notes and use them as often as possible. Here are they:
- Never or almost never requirements you are working on are complete. Even if customer told you that this is finish step and we stop work on it - that mean only - we stop the work for now and we may continue it after some time. And of course, that time may vary from few weeks to few month, so you may and you will forget the code. That's why always write comments to the code even if it is not yours!
- If you can extend the code you've write before - do it! If you need to get the list of some entities - use search engine if it exists. If search engine is not enough - extend it and use it. Be DRY principal follower!
- Write your code with one think: I will use it tomorrow too! That's mean that you should write quality code, well commented code and code that make everything you have now and a little bit more. Sure, this "a little bit more" should be result of your experience. If you don't have enough experience - use this too! Why? You'll get need experience much faster!
- Do code review! Often. Why? Because it increases the quality of your code and as result of software. And also you'll find your and yours colleagues weak and that is 50% of new experience. I like Atlassian experience with code reviewing for many tasks they do.

Simple, but important.



Spring MVC + FreeMarker + Tiles 2

This is extended and translated into English version of my post Spring MVC + FreeMarker + Tiles 2. I've found that many are interested about the joint work of those frameworks.
Well, this article shows how to configure the Spring MVC application with Tiles 2 and FreeMarker. You may don't use the SpringMVC framework, and in this case you need to make by your hands all the configuration work that Spring MVC does for you.
As you may know, Freemarker is popular template engine write on Java and used by mostly by Java applications. Tiles 2 is also Java frameworks used to prepare document using one or more "tiles" - the parts that are defined separately but used to be generated at one document. For example, using tiles you can define site header/footer, news or post blocks at your site etc.
So, how did I get it working?
Simple!

In file web.xml add the freemarker configuration.

<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>


And here is the important part *-servlet.xml configuration:

<!-- Tiles 2 configuration-->
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<property name="definitions">
<list>
<!-- the tiles configuration files are declared here -->
<value>/WEB-INF/defs/general.xml</value>
<value>/WEB-INF/defs/secure.xml</value>
</list>
</property>
</bean>

<bean id="tilesViewResolver" class="com.javaua.spring.integration.ext.ExtUrlBasedViewResolver">
<property name="viewClass" value="com.javaua.spring.integration.ext.ExtTilesView"/>
<property name="exposeSpringMacroModel" value="true"/>
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="cache" value="true"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
<!-- if you want to use the Spring FreeMarker macros, set this property to true -->
<property name="exposeSpringMacroHelpers" value="true"/>
</bean>

<!-- Controller that returns view = /layout/header -->
<bean name="/layout/header.page" class="com.javaua.HeaderController"/>


Also show here the part of general.xml file where Tiles definitions are set up.:

<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"/>


Source code of com.javaua.spring.integration.ext.ExtUrlBasedViewResolver class:

import org.springframework.core.Ordered;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;

public class ExtUrlBasedViewResolver extends UrlBasedViewResolver implements Ordered {

private boolean exposeSpringMacroModel = false;

public void setExposeSpringMacroModel(boolean exposeSpringMacroModel) {
this.exposeSpringMacroModel = exposeSpringMacroModel;
}

protected View loadView(String viewName, Locale locale) throws Exception {
AbstractUrlBasedView view = buildView(viewName);
View viewObj = (View) getApplicationContext().getAutowireCapableBeanFactory().initializeBean(view, viewName);

if (viewObj instanceof ExtTilesView) {
ExtTilesView tilesView = (ExtTilesView) viewObj;
tilesView.setExposeSpringMacroModel(exposeSpringMacroModel);
}

return viewObj;
}



Source code of com.javaua.spring.integration.ext.ExtTilesView class:

import org.springframework.web.servlet.view.tiles2.TilesView;
import org.springframework.web.servlet.view.AbstractTemplateView;
import org.springframework.web.servlet.support.RequestContext;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.ServletException;
import java.util.Map;


public class ExtTilesView extends TilesView {

private boolean exposeSpringMacroModel = false;

public void setExposeSpringMacroModel(boolean exposeSpringMacroModel) {
this.exposeSpringMacroModel = exposeSpringMacroModel;
}

@SuppressWarnings("unchecked")
protected final void renderMergedOutputModel(Map model, HttpServletRequest request,
HttpServletResponse response) throws Exception {

if (exposeSpringMacroModel) {
if (model.containsKey(AbstractTemplateView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE)) {
throw new ServletException(
"Cannot expose bind macro helper '" +
AbstractTemplateView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE +
"' because of an existing model object of the same name");
}
model.put(AbstractTemplateView.SPRING_MACRO_REQUEST_CONTEXT_ATTRIBUTE,
new RequestContext(request, getServletContext(), model));
}

super.renderMergedOutputModel(model, request, response);
}
}


Why we need those two classes? Simple enough. Class ExtTilesView exposes Spring macro model which is required when using standard macros used to support work with Freemarker and Velocity typelate frameworks. And the class ExtUrlBasedViewResolver helps us to prevent view-not-found-error. Because, standard UrlBasedViewResolver is used for getting tiles view, it will throw an error when view with specified name is not found. In my case, I have two view resolvers and each will throw an error if view can't be found.
And FreeMarkerViewResolver will request for the file, while tiles requests just for XML definition. That's why I've ran the tiles view resolver as first one.



GC and performance

Мабуть, нікому не секрет, що GC є дуже важливою річчю в JVM, і що вона займається звільненням памяті, що вже не використовуються. Також багатьом відомо, що є кілька різних політик виконання очистки пам'яті. Конфігурація не виглядає надто складною, є всього кілька можливих варіантів вибору політики GC:



  • SerialGC - встановлена по дефолту, працює найкраще якщо на машині тільки один процесор, коли виконуєть збір сміття, то програма тормозить, адже в даний момент вона не відповідає.

  • ParallelGC - використовується можливість виконувати мінорний (minor) збір сміття в паралельних потоках. Програма здатна відповідати на запити клієнта в момент збору сміття

  • ParallelOldGC - виконує мажорний (major) збір сміття в паралельних потоках

  • ConcMarkSweepGC - В даному випадку постійно відбувається збір сміття, програма не тормозить при зборах сміття, як це можна замітити в 3 попередніх випадках.


Таким чином, я вирішив переконфігурувати для прикладу IntellijIdea, що я використовую.

-Xms256m
-Xmx512m
-XX:MaxPermSize=120m
-XX:+UseConcMarkSweepGC
-ea
-Dawt.useSystemAAFontSettings=lcd


Для покращення швидкодії роботи, можна також установити значення ms = mx, так щоб

-Xms512m
-Xmx512m
-XX:MaxPermSize=120m
-XX:+UseConcMarkSweepGC
-ea
-Dawt.useSystemAAFontSettings=lcd


Ресурси