SimpleJPA + Maven + Dependencies

January 2nd, 2012

Whilst I am very grateful to the folks who developed SimpleJPA, I found it a bit problematic building (with Maven) a project having SimpleJPA as of its dependencies. In this article, I attempt to make it easier for others who intend to use Maven for building their project which uses SimpleJPA.

Read more…

Java , , ,

Regex Pattern In XSD For Comma-Separated Attribute Value

June 16th, 2010

Relevant Section Of The XML

<my_element xyz="ABC3"/>
<my_element xyz="ABC21,a1"/>

Relevant Section Of The XSD

1
2
3
4
5
6
7
8
9
10
11
<xs:element name="my_element" maxOccurs="unbounded" minOccurs="1">
  <xs:complexType>
    <xs:attribute name="xyz" use="required">
      <xs:simpleType> 
        <xs:restriction base="xs:string"> 
          <xs:pattern value="[a-zA-Z0-9]+[,a-zA-Z0-9]*"/>
        </xs:restriction> 
      </xs:simpleType>
    </xs:attribute>
  </xs:complexType>
</xs:element>

Uncategorized

Chaining 2 jQuery UI Datepickers

June 10th, 2010

A simple example to chain 2 jQuery UI datepickers such that when a date is selected in the first datepicker (a.k.a. the ‘from date‘, date1), the minimum date in the second datepicker (a.k.a. the ‘to date‘, date2) is set accordingly. Similarly it handles the case where the ‘to date‘ is selected before the ‘from date‘, in which case the maximum date in the ‘from date‘ is lesser than the ‘to date‘ but before current date.

Relevant HTML For Datepicker Placeholders

<p><input type="text" name="date1" id="date1" /></p>
<p><input type="text" name="date2" id="date2" /></p>

Relevant jQuery Setup Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script>
  $(document).ready(function() {  
    $('#date1').datepicker({
      autoSize: true, 
      constrainInput: true, 
      dateFormat: 'ddMyy', 
      minDate: 0, 
      maxDate: '+90D', 
      onSelect: function(dateText, inst) { 
        $('#date2').datepicker("option", "minDate",dateText); 
      } 
    });
    $('#date2').datepicker({
      autoSize: true, 
      constrainInput: true, 
      dateFormat: 'ddMyy', 
      minDate: 0, 
      maxDate: '+90D', 
      onSelect: function(dateText, inst) { 
        $('#date1').datepicker("option", "maxDate",dateText); 
      } 
    });
    //Other setup
  });
</script>

In the jQuery setup code above, I have also set the following

  • Do not allow selection of dates before current date (minDate: 0)
  • Do not allow selection of dates 90 days after current date (maxDate: '+90D')
  • Date format similar to ‘17Jun2010
  • The ‘constrainInput: true‘ indicates that the input field is constrained to those characters allowed by the current dateFormat.

Javascript

Spring + JPA + Hibernate + Tomcat + EHCache

May 2nd, 2010

Having @ManyToMany(fetch=FetchType.EAGER) attributes can slow down retrieval quite significantly (up to 40 times slower).

I recall reading somewhere that FetchType.EAGER is the default for @ManyToMany associations. Also, from experience I noticed that setting FetchType.LAZY caused a org.hibernate.LazyInitializationException thrown with exception message similar to, failed to lazily initialize a collection of role: com.xyz.domain.EntityOne.images, no session or session was closed.

So, it seemed that the only other way to quickly reduce the time it took (for the retrieval) was to look into the caching options such as query caching, second-level caching, both of which are supported by Hibernate (the webapp’s JPA provider). For more information on second-level caching, please refer to this article.

Integrating Spring + JPA + Hibernate + Tomcat + EHCache took me a few hours this afternoon, but the effort paid off. The retrieval is now 40 times faster!

This post is summarizing the setup involved in getting them all to work together.

Relevant Section Of persistence.xml:

<provider>org.hibernate.ejb.HibernatePersistence</provider>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
  <property name="hibernate.cache.provider_class" 
    value="org.hibernate.cache.SingletonEhCacheProvider" />
  <property name="hibernate.cache.provider_configuration" value="/ehcache.xml" />
  <property name="hibernate.cache.use_second_level_cache" value="true" />
  <property name="hibernate.cache.use_query_cache" value="true" />
</properties>

Notes:

  • The persistence.xml is located at {tomcat}/webapps/{your-webapp}/META-INF.
  • I used org.hibernate.cache.SingletonEhCacheProvider instead of org.hibernate.cache.EhCacheProvider. I was getting a WARN message if I used org.hibernate.cache.EhCacheProvider. I referred to this post for a fix.

Relevant Section Of ehcache.xml:

  <diskStore path="user.dir/mywebapp-special-cache-folder"/>
 
  <defaultCache eternal="false" overflowToDisk="false"
    maxElementsInMemory="1000" timeToIdleSeconds="30" timeToLiveSeconds="60"/>
 
  <cache name="com.xyz.domain.EntityTwo" eternal="false" overflowToDisk="true" 
    maxElementsInMemory="1000" timeToIdleSeconds="300" timeToLiveSeconds="600"
    diskPersistent="true" diskExpiryThreadIntervalSeconds="300"/>
 
  <cache name="com.xyz.domain.EntityOne" eternal="false" overflowToDisk="true" 
    maxElementsInMemory="1000" timeToIdleSeconds="300" timeToLiveSeconds="600" 
    diskPersistent="true" diskExpiryThreadIntervalSeconds="300"/>
 
  <cache name="com.xyz.domain.EntityOne.images" eternal="false" 
    overflowToDisk="true" 
    maxElementsInMemory="1000" timeToIdleSeconds="300" timeToLiveSeconds="600" 
    diskPersistent="true" diskExpiryThreadIntervalSeconds="300"/>

Notes:

  • The ehcache.xml is located at {tomcat}/webapps/{your-webapp}/WEB-INF/classes.
  • The diskStore element indicates where the files to be used for caching will be stored for the entities I wish to be made persistent to disk. In my web application, the files are stored under {tomcat}/bin/{mywebapp-special-cache-folder}
  • diskPersistent="true" indicates that the disk store (for the specific entity) is persistent between cache and VM restarts. Please refer to the EHCache documentation on disk storage for more information.

Relevant JARs: under {tomcat}/webapps/{your-webapp}/WEB-INF/lib

  • ehcache-core-2.0.1.jar
  • hibernate3.jar
  • hibernate-jpa-2.0-api-1.0.0.Final.jar
  • slf4j-api-1.5.8.jar
  • slf4j-log4j12-1.5.6.jar
  • Spring 3.0.2 JARs..

Relevant Section Of Spring Configuration:

<!-- there should be a way out of hardcoding the location of the properties file -->
<bean 
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location" value="/WEB-INF/spring-hes-db.properties" />
</bean>
 
<!-- ENTITY MANAGER FACTORY -->
<!-- LocalEntityManagerFactoryBean did not work for me -->
<bean id="emf-p" 
  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="persistenceUnitManager" ref="pum"/>
  <property name="persistenceUnitName" value="pu1"/>
  <property name="dataSource" ref="dataSource-p" />
  <property name="jpaVendorAdapter">
    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
      <property name="database" value="MYSQL" />
      <property name="showSql" value="true" />
      <property name="generateDdl" value="true" />
      <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
    </bean>
  </property>
</bean>
 
<!-- TRANSACTION MANAGER -->
<bean id="transactionManager" 
  class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="emf-p"/>
  <property name="dataSource" ref="dataSource-p"/>
</bean>
 
<!-- DATA SOURCES -->
<bean id="dataSource-p" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver" />
  <property name="url" 
    value="jdbc:mysql://${db.host}:${db.port}/${db.name}"/>
  <property name="username" value="${db.username}" />
  <property name="password" value="${db.password}" />
</bean>
 
<!-- JPA TEMPLATE -->
<bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate">
 <property name="entityManagerFactory" ref="emf-p" />
</bean>
 
<!-- DAOs -->
<bean id="entityOneDao" class="hes.db.impl.EntityOneDAOImpl">
  <property name="jpaTemplate" ref="jpaTemplate"/>
</bean>
 
<!-- PERSISTENCE UNIT -->
<bean id="pum" 
  class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
  <property name="persistenceXmlLocations">
    <list>
      <value>META-INF/persistence.xml</value>
    </list>
  </property>
  <property name="dataSources">
    <map>
      <entry key="remoteDataSource" value-ref="dataSource-p" />
    </map>
  </property>
  <property name="defaultDataSource" ref="dataSource-p"/>
</bean>

Some of this may be redundant and will be cleaned up later.

If you have some better ideas, please do share. Thanks.

Java, Spring , , ,

AnnotationException : Entity X References An Unknown Entity Y

April 30th, 2010

Problem: I was getting an org.hibernate.AnnotationException when creating a bidirectional one-to-one relationship between 2 entities (EntityOne and EntityTwo).

Relevant Section Of StackTrace:
Caused by: org.hibernate.AnnotationException: @OneToOne or @ManyToOne on com.xyz.domain.EntityOne.anImage references an unknown entity: com.xyz.domain.EntityTwo
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:103)
at org.hibernate.cfg.AnnotationConfiguration.processEndOfQueue(AnnotationConfiguration.java:541)
at org.hibernate.cfg.AnnotationConfiguration.processFkSecondPassInOrder(AnnotationConfiguration.java:523)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:380)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1206)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1449)

Relevant Section Of EntityOne’s Code:

@Entity
@Table(name = "entity1")
public class EntityOne implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "e1_id")
  private Long id;
 
  @OneToOne(fetch = FetchType.LAZY, optional = true)
  @JoinTable(name = "entity1_entity2_map",
    joinColumns = @JoinColumn(name = "e1_id"),
    inverseJoinColumns = @JoinColumn(name = "e2_id"))
  private EntityTwo anImage;
 
  //Other code
}

Relevant Section Of EntityTwo’s Code:

@Entity
@Table(name = "entity2")
public class EntityTwo implements Serializable {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "e2_id")
  private Long id;
 
  @OneToOne(mappedBy = "anImage", optional = true)
  private EntityOne e1;
 
  //Other code
}

Solution That Worked For Me:
Check the persistence.xml to ensure that the 2 entities (EntityOne and EntityTwo) are listed. Previously I had not included EntityTwo, which is why I kept getting the message com.xyz.domain.EntityOne.anImage references an unknown entity: com.xyz.domain.EntityTwo

    com.xyz.domain.EntityOne
    com.xyz.domain.EntityTwo
    <!-- other configurations -->

Java ,

Adding/Removing Workspaces In Eclipse

March 24th, 2010
  1. Go to {path-to-Eclipse-installation}\configuration\.settings
  2. Open the file “org.eclipse.ui.ide.prefs” using any text editor
  3. Look out for the property “RECENT_WORKSPACES” which stores the paths to the workspaces currently in use, each separated by ‘\n’ (for example, C\:\\eclipse-workspaces\\customer1\nC\:\\eclipse-workspaces\\customer2\nC\:\\eclipse-workspaces\\customer3\nC\:\\eclipse-workspaces\\customer4)
    for a setup similar to
      eclipse-workspaces
        - customer1
        - customer2
        - customer3
        - customer4
  4. To add a workspace, add the full path (preceded by a ‘\n’) to the end. To remove a workspace, remove the path any trailing ‘\n’

The above has been tried out and works for Eclipse 3.4.2, 3.5, 3.5.2

Uncategorized

ANT Unable To Find A Javac Compiler

February 3rd, 2010

If ever you find yourself in a similar situation,

BUILD FAILED
C:\work\build.xml:188: Unable to find a javac compiler;
com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK.
It is currently set to “C:\java\jre\6″

Ensure the following:

  1. Ensure that JAVA_HOME is set
  2. Ensure that JAVA_HOME does not end with ‘bin’ – if it does, then ANT will not work as it will look for tools.jar under “{JAVA_HOME}\lib
  3. On command prompt, type SET JAVA_HOME={Full path to JDK install} (for example, C:\java\jdk\160_16)

Uncategorized

Instantiating SimpleDateFormat Objects Consumes A Lot Of Memory

February 1st, 2010

3120 bytes to be precise.

I had access to code which instantiated 3 java.text.SimpleDateFormat objects per method call.

I recently came across simple yet effective instrumentation to query the size of a Java object, javamex. Using it, I found that each instance of java.text.SimpleDateFormat has a deep memory usage of 3120 bytes! In comparison, a 3 character String, say, “ABC” has a deep memory usage of 48 bytes.

This article suggests using an instance of the java.text.SimpleDateFormat per thread by making use of the java.lang.ThreadLoca class.

After referring to two articles online (which you can read here & here), I made some modifications to the code and sure enough, I no longer face the earlier problems related to memory usage.

Some excerpts. I created a per-thread Singleton, DateUtil.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class DateUtil
{
  private static SDF1 sdf1 = new SDF1();
  private static SDF2 sdf2 = new SDF2();
 
  // Returns the SimpleDateFormat object
  // for the date pattern "ddMMMyyyy".
  public static SimpleDateFormat getSimpleDateFormat_ddMMMyyyy() {
    return (SimpleDateFormat) sdf1.get();
  }
 
  // Returns the SimpleDateFormat object
  // for the date pattern "EEE dd MMM yyyy".
  public static SimpleDateFormat getSimpleDateFormat_EEE_dd_MMM_yyyy() {
    return (SimpleDateFormat) sdf2.get();
  }
 
  // A ThreadLocal subclass for the SimpleDateFormat
  // for the date pattern "ddMMMyyyy"
  private static class SDF1 extends ThreadLocal<SimpleDateFormat> {
    public SimpleDateFormat initialValue() {
      return new SimpleDateFormat("ddMMMyyyy");
    }
  }
 
  // A ThreadLocal subclass for the SimpleDateFormat 
  // for the date pattern "EEE dd MMM yyyy"
  private static class SDF2 extends ThreadLocal<SimpleDateFormat> {
    public SimpleDateFormat initialValue() {
      return new SimpleDateFormat("EEE dd MMM yyyy");
    }
  }
}

In the older code which previously instantiated a java.text.SimpleDateFormat object, I replaced it with the following,

1
2
3
  SimpleDateFormat travelDateFormat = DateUtil.getSimpleDateFormat_ddMMMyyyy();
  Date date = travelDateFormat.parse(strToParse);
  //where, strToParse is a String similar to "31Jan2010"

Java

noNamespace Problem When Using The XmlBean Task In ANT

January 19th, 2010

Here’s something that worked for me after having spent several hours on it. First the relevant part of the build.xml file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    <copy todir="${build.dir}${file.separator}schemaSrc">
      <fileset dir="${schemas.dir}">
        <include name="*.xsd"/>
        <include name="*.xsdconfig"/>
      </fileset>
    </copy>
    <path id="xmlbeans.path">
      <fileset dir="${lib.dir}/xmlbeans">
        <include name="xbean.jar"/>
        <include name="jsr173_1.0_api.jar"/>
      </fileset>
    </path>
    <property name="xmlbeans.compiler" value="javac1.5"/>
    <taskdef name="xmlbean" classname="org.apache.xmlbeans.impl.tool.XMLBean" 
             classpath="${toString:xmlbeans.path}" />
    <xmlbean schema="${build.dir}${file.separator}schemaSrc"
             destfile="schemas.jar"
             srcgendir="${build.dir}"
             debug="on"
             classpath="${toString:xmlbeans.path}"
             javasource="1.5"
             />

A sample .xsd file,

1
2
3
4
5
6
7
8
9
10
11
12
13
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="Employee">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="SSN" type="xsd:string"/>
        <xsd:element name="Name" type="xsd:string"/>
        <xsd:element name="DateOfBirth" type="xsd:date"/>
        <xsd:element name="EmployeeType" type="xsd:string"/>
        <xsd:element name="Salary" type="xsd:long"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

A sample .xsdconfig file,

1
2
3
4
5
<xb:config xmlns:xb="http://xml.apache.org/xmlbeans/2004/02/xbean/config">
  <xb:namespace uri="##any">
    <xb:package>com.acompany.xsd</xb:package>
  </xb:namespace>
</xb:config>

Java , , ,

Java Code To Get Dates Before And After A Specific Date

December 3rd, 2009

Very trivial Java code to get the dates in a window around a specified date (i.e., X days before and Y days after a specified date). The dates are returned as strings of a configurable format.

For example, to get the dates 2 days before and 1 day after 25Dec2009, the returned String[] contains the Strings “23Dec2009“, “24Dec2009“, “25Dec2009“, “26Dec2009“. In this example, I chose to use “ddMMMsyyyy” format, so the date strings look similar to 25Dec2009.

Calling The getDatesAround Method

1
2
3
4
5
6
7
8
SimpleDateUtil util = new SimpleDateUtil();
final String pattern = "ddMMMsyyyy";
try {
  util.getDatesAround(util.constructDate( pattern, "25Dec2009"), 2, 1, pattern);
  util.getDatesAround(util.constructDate( pattern, "14Feb2010"), 4, 1, pattern);
} catch (ParseException e) {
  e.printStackTrace();
}

Calling the getDatesAround method to get the dates 2 days before and 1 day after 25Dec2009, the returned String[] contains the Strings “23Dec2009″, “24Dec2009″, “25Dec2009″, “26Dec2009″.

And now, the source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public Date constructDate(String pattern, String dateString) throws ParseException {
  dateFormatter.applyPattern(pattern);
  return dateFormatter.parse(dateString);
}
 
public String[] getDatesAround(Date centredDate, int numDaysBefore, int numDaysAfter, String pattern) {
  int totalNumDays = ((numDaysBefore > 0) ? numDaysBefore : 0) + 1 + ((numDaysAfter > 0) ? numDaysAfter : 0), pos = 0;
  String[] dateStrings = new String[totalNumDays];
  SimpleDateFormat sdf = new SimpleDateFormat(pattern);
  // Get a Date object, which we will be using for manipulations
  Calendar cal = GregorianCalendar.getInstance();
  cal.setTime(centredDate);
  Date dateObj = cal.getTime();
  long time = dateObj.getTime();
  // Constructing the date Strings before the centredDate
  if (numDaysBefore > 0) {
    time = dateObj.getTime();
  for (int i = numDaysBefore; i > 0; i--) {
    dateObj.setTime(time - oneDayInMillis * i);
    dateStrings[pos] = sdf.format(dateObj);
    pos++;
    }
  }
  // centredDate
  dateStrings[pos] = sdf.format(centredDate);
  dateObj.setTime(centredDate.getTime());
  pos++;
 
  // Constructing the date Strings after the centredDate
  if (numDaysAfter > 0) {
    for (int i = pos; i < totalNumDays; i++) {
      time = dateObj.getTime();
      dateObj.setTime(time + oneDayInMillis);
      dateStrings[i] = sdf.format(dateObj);
    }
  }
  return dateStrings;
}

Java