Dec
6
2010

OpenJPA Auto Detach Configuration and Memory Issues

When I was doing some work with OpenJPA, I found there is a possible memory leaking issue when OpenJPA is used for data access without the proper configuration of the parameter of auto detach (openjpa.AutoDetach).

The scenario that the memory issue may happen:

  • One EntityManagerFactory and One EntityManager are used throughout the whole session;
  • The session contains a lot of queries, they are all read-only queries;
  • Most queries are to retrieve database records based on primary keys;
  • The records retrieved are approximately evenly distributed across primary keys;
  • The database being queried has a large amount of data.


It seems that OpenJPA keeps references to data retrieved from the queries as cache. This prevents JVM garbage collecting them. Eventually, out of memory error happens.

This time, it seems that the call to clear method on EntityManager does not even work. Finally, we added the following properties and it seemed to solve the issue:

openjpa.AutoDetach=nontx-read

In fact, it is not a good practice to use EntityManager as shown in the scenario. Maybe the initial consideration is to re-use the single EntityManager as much as possible to help improve the performance of the session that is created in a batch process.

In general, the EntityManager object should not live in the whole long session. Instead it should be created on demand and closed and disregarded when finishing its unit of work. However, i haven’t got time to test how worse the performance can degrade if it is implemented this way.

Nov
17
2010

GWT CellTable Example (Using AsyncDataProvider)

GWT version 2.1 has finally been released with the anticipated business level data presentation widgets and other interesting features. CellTable is one of the new widgets that supports pagination. Therefore, there no need to use PagingScrollTable in the gwt incubator or implementations in other third-party libraries.

From the Google official document on how to use data presentation widgets, you can get some examples of using these cell widgets including CellTable. It also includes a simple example of using CellTable with SimplePager to implement pagination. That example uses ListDataProvider which requires all the data that needs to be paged to be set at the client (browser) side. However, in realty, the common practice is to load only one page of data from the server (mostly pulled from a database) to the browser in order to save the bandwidth and improve the response time.

Of course the document indicates there are ways to implement the asynchronized page data loading from remote server.  It mentions that (at the time of writing of this post) (Update: the new Google document does not have the following text anymore):

“GWT also provides the abstract class AsyncListViewAdapter, which you can override to connect to an asynchronous data source, such as a database running on a server. Just implement the onRangeChanged() method and request the data in the new Range for the specified cell widget. When the data is returned, call updateRowCount() and/or updateRowData() to push the data to the widgets.”

However,  it seems the official GWT 2.1 release does not have the class AsyncListViewAdapter. Instead, AsyncDataProvider is found. (A document bug?)

To illustrate how to use AsyncDataProvider, I modified a simple example from GWT below.

Please note the example do not actually calls the server to get the data. It should be quite easy to modify the example to do so as illustrated in the next code snippet.

import java.util.Arrays;
import java.util.Date;
import java.util.List;
 
import com.google.gwt.cell.client.DateCell;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
 
public class CellTableExample implements EntryPoint {
 
  /**
   * A simple data type that represents a contact.
   */
  private static class Contact {
    private final String address;
    private final Date birthday;
    private final String name;
 
    public Contact(String name, Date birthday, String address) {
      this.name = name;
      this.birthday = birthday;
      this.address = address;
    }
  }
 
  /**
   * The list of data to display.
   */
  @SuppressWarnings("deprecation")
  private static final List<Contact> CONTACTS = Arrays.asList(
      new Contact("John", new Date(80, 4, 12), "123 Abc Avenue"), 
      new Contact("Joe", new Date(85, 2, 22), "22 Lance Ln"), 
      new Contact("Tom", new Date(85, 3, 22), "33 Lance Ln"), 
      new Contact("Jack", new Date(85, 4, 22), "44 Lance Ln"), 
      new Contact("Tim", new Date(85, 5, 22), "55 Lance Ln"), 
      new Contact("Mike", new Date(85, 6, 22), "66 Lance Ln"), 
      new Contact("George", new Date(46, 6, 6),"77 Lance Ln"));
 
  public void onModuleLoad() {
    // Create a CellTable.
    final CellTable<Contact> table = new CellTable<Contact>();
    // Display 3 rows in one page
    table.setPageSize(3);
 
    // Add a text column to show the name.
    TextColumn<Contact> nameColumn = new TextColumn<Contact>() {
      @Override
      public String getValue(Contact object) {
        return object.name;
      }
    };
    table.addColumn(nameColumn, "Name");
 
    // Add a date column to show the birthday.
    DateCell dateCell = new DateCell();
    Column<Contact, Date> dateColumn = new Column<Contact, Date>(dateCell) {
      @Override
      public Date getValue(Contact object) {
        return object.birthday;
      }
    };
    table.addColumn(dateColumn, "Birthday");
 
    // Add a text column to show the address.
    TextColumn<Contact> addressColumn = new TextColumn<Contact>() {
      @Override
      public String getValue(Contact object) {
        return object.address;
      }
    };
    table.addColumn(addressColumn, "Address");
 
    // Associate an async data provider to the table
	// XXX: Use AsyncCallback in the method onRangeChanged
	// to actaully get the data from the server side
    AsyncDataProvider<Contact> provider = new AsyncDataProvider<Contact>() {
      @Override
      protected void onRangeChanged(HasData<Contact> display) {
        int start = display.getVisibleRange().getStart();
        int end = start + display.getVisibleRange().getLength();
        end = end >= CONTACTS.size() ? CONTACTS.size() : end;
        List<Contact> sub = CONTACTS.subList(start, end);
        updateRowData(start, sub);
      }
    };
    provider.addDataDisplay(table);
    provider.updateRowCount(CONTACTS.size(), true);
 
    SimplePager pager = new SimplePager();
    pager.setDisplay(table);
 
    VerticalPanel vp = new VerticalPanel();
    vp.add(table);
    vp.add(pager);
 
    // Add it to the root panel.
    RootPanel.get().add(vp);
  }
}

To make remote calls to retrieve table data from the server, The code snippet should look like the following.

// Associate an async data provider to the table
    AsyncDataProvider<Contact> provider = new AsyncDataProvider<Contact>() {
      @Override
      protected void onRangeChanged(HasData<Contact> display) {
        final int start = display.getVisibleRange().getStart();
        int length = display.getVisibleRange().getLength();
        AsyncCallback<List<Contact>> callback = new AsyncCallback<List<Contact>>() {
          @Override
          public void onFailure(Throwable caught) {
            Window.alert(caught.getMessage());
          }
          @Override
          public void onSuccess(List<Contact> result) {
            updateRowData(start, result);
          }
        };
        // The remote service that should be implemented
        remoteService.fetchPage(start, length, callback);
      }
    };
Nov
15
2010

How to use PagingScrollTable in the gwt incubator

The core GWT library (prior to version 2.1) does not provide an official widget that allows for a table with pagination support. Instead, there is a widget in gwt incubator called PagingScrollTable that has the paging functionality.

However, the “official wiki document” does not provide enough detailed information to use this widget. Luckily someone has made an illustrative example with informative documentation on how to implement a table with pagination support using PagingScrollTable in gwt incubator.

Jun
9
2010

How to Configure Spring beans.xml File: The Use of PropertyPlaceholderConfigurer

The file “beans.xml” used for you application is already a kind of configuration file. However, this file is designed for the developer who can quickly customize the application with less coding changes. It is not recommended for an end user to change the file.

For example, you can, of course, define the database connection properties in the beans.xml file straight away. This way, every time a user wants the application to connect to a database at a different location, the beans.xml file needs to be modified. For a complicated application, the file can grow very complicated as well. Therefore, making changes to the beans.xml file directly may not seem obvious to the end user.

Fortunately, Spring have already come up with a solution for this problem. You can define the properties in the “beans.xml” file with place holders and use the Spring provided bean PropertyPlaceholderConfigurer to replace the place holders with the value from a properties file. Here is an example of the use of PropertyPlaceholderConfigurer.

In the example from the above link, it specifies one location for the properties file with a classpath: “classpath:com/foo/jdbc.properties”. In addition to that, you can also specify a file on your file system. When using a file on file system, remember to add “file:/” to an absolute path; otherwise, Spring will treat it as a relative path even the value starts with “/”.

PropertyPlaceholderConfigurer also allows you to define some default values using the property “properties“. The following is an example of using the default values if the file defined by “locations” property does not exist. Please note setting “ignoreResourceNotFound” to true is necessary. If not set, the application will throw exception if the defined property does not exist even we’ve defined the default values.

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="ignoreResourceNotFound" value="true" />
  <property name="locations">
    <value>file:///etc/app/jdbc.properties</value>
  </property>
  <property name="properties">
    <props>
      <prop key="jdbc.driverClassName">com.mysql.jdbc.Driver</prop>
      <prop key="jdbc.url">jdbc:mysql://localhost:3306/mytechtip</prop>
      <prop key="jdbc.username">jdbc_username</prop>
      <prop key="jdbc.password">xxx</prop>
    </props>
  </property>
 
</bean>
 
<bean id="dataSource" destroy-method="close" 
    class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="${jdbc.driverClassName}"/>
  <property name="url" value="${jdbc.url}"/>
  <property name="username" value="${jdbc.username}"/>
  <property name="password" value="${jdbc.password}"/>
</bean>
Jun
7
2010

How to Configure Spring beans.xml File: Collection properties and EntityManagerFactory Examples

Java beans in Spring can also have their collection properties populated in the beans.xml file. The collection properties here mean things like List, Map and Array.

For example, if you want to create a JPA EntityManagerFactory with a set of connection properties, these properties can be configured in beans.xml like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:p="http://www.springframework.org/schema/p"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id="entityManagerFactoryCreator" 
    class="com.mytechtip.example.EntityManagerFactoryCreator">
    <property name="persistenceUnitName" value="HRMN_Repository"/>
    <property name="jpaProperties">
      <props>
        <prop key="openjpa.ConnectionURL">the_url</prop>
        <prop key="openjpa.ConnectionDriverName">the_driver_class_name</prop> 
        <prop key="openjpa.ConnectionUserName">the_user_name</prop>
        <prop key="openjpa.ConnectionPassword">the_password</prop>
      </props>
    </property>
  </bean>
</beans>

Here, jpaProperties in the actual java class “EntityManagerFactoryCreator” is an instance of Properties. And you can just use this properties to create EntityManagerFactory.

    // ...
    private Properties jpaProperties;
    //...
    public void setJpaProperties(Properties prop) {
        this.jpaProperties = prop;
    }
    // ...
    public EntityManagerFactory create() {
        return Persistence.createEntityManagerFactory("myPersistenceUnit", prop);
    }

Actually, Spring already have something similar for you to access EntityManagerFactory with ease. The beans used for the task are:

  • org.springframework.orm.jpa.LocalEntityManagerFactoryBean
  • org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean

More information / examples can be found here about the support of JPA entity manager factory creatation in Spring.