Problem

Majority of enterprise applications use database as a persistence layer. JPA framework allows developers to manage relational data in their J2SE and J2EE applications. While knowledge about JPA domain modeling techniques is widespread and available, there is little known about persistence layer testing. In this post I will describe the process of setting up an environment for an application integration testing using JUnit, Spring Framework and Maven.

The standard Maven 2 directory layout

The standard Maven 2 directory structure can be seen below.

Maven Directory Layout


In the project home directory goes the pom.xml and two subdirectories – src for source code and target for compilation output. The src directory has two subdirectories, main – all files related to the application being developed go here and test – all test related files go here.

Naturally, this layout might be different, most likely having more elements – this depends on the archetype used during project inception, but, nevertheless, the layout above is an absolute minimum. The test directory have two subdirectories – java – with all unit tests and resources – with resources, which are used for testing, but are not deployed.
Having two separate directories for application and test allows us to have two, completely separated configuration files, so that testing environment was completely independent from development environment. It is possible, to develop using one database instance and test on the other, or even use MySQL for development and HSQLDB for testing, if required.

Configuration files

persistence.xml

The persistence.xml file defines a persistence-unit, and according to specification, has to be included an the META-INF directory of a JAR file that contains entities. However, Spring gives a little bit more room here and my approach is to put it in a config subdirectory of test/resources. The minimum persistence.xml:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence version="1.0"
  xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
    http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
  ">

  <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"/>

</persistence>

defines only the persistence-unit name, everything else is configured in Spring Framework configuration file – applicationContext.xml, which goes also to a config directory.

applicationContext.xml

Spring Framework configuration file – applicationContext.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
  ">

  <!-- Enable processing of PersistenceUnit and PersistenceContext annotations  -->
  <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

  <!-- Persistence exception translation for Repositories -->
  <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

  <!-- Enable annotation-driven configuration and auto-detection -->
  <context:annotation-config/>

  <!-- Enable component scan -->
  <context:component-scan base-package="com.bewareofthebear"/>

  <!-- Configure property placeholders for environment-specific properties customization -->
  <context:property-placeholder location="classpath:/properties/*.properties" />

  <!-- Datasource to be used by Hibernate/JPA  -->
  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
    p:driverClassName="${db.driverClassName}"
    p:url="${db.url}"
    p:username="${db.username}"
    p:password="${db.password}"
  />

  <!-- EntityManagerFactory using defined datasource and JPA provider - Hibernate  -->
  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
    p:persistenceXmlLocation="classpath:/config/persistence.xml"
    p:dataSource-ref="dataSource"
  	p:persistenceUnitName="persistenceUnit"
    >
    <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
    <property name="jpaProperties">
      <props>
        <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="hibernate.hbm2ddl.auto">create</prop>
        <prop key="hibernate.format_sql">false</prop>
        <prop key="hibernate.use_sql_comments">false</prop>
      </props>
    </property>
  </bean>

  <!--  Transaction manager -->
  <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
    p:entityManagerFactory-ref="entityManagerFactory"
    p:dataSource-ref="dataSource"
  />

  <!-- Use @Transactional annotation on methods -->
  <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

As seen, using persistenceXmlLocation property of EntityManagerFactory I was able to point to my test version of a persistence.xml file. This approach has however one drawback which comes from limitations of JPA’s entities scan. It scans only paths within a persistent unit root url, which is a parent folder of persistence.xml location. Since maven copies content of the resource folder to the target/test-classes folder, than this folder becomes the root url and is scanned during application start-up. As a result of this, all application entities defined under main/java/… will not be scanned and, if test database is different than development database, than tests will fail. There are few ways to solve this problem.

First, it is possible to use an application version of persistence.xml instead of test version, however, this approach has the same drawback, just in opposite direction – all application entities are scanned, but, if there are any entities defined in a test directory than these will not be scanned.

Second solution is to explicitly list required entities in a persistence.xml file:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence version="1.0"
  xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
    http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
  ">

  <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
    <class>com.bewareofthebear.domain.model.customer.Customer</class>
    <class>com.bewareofthebear.domain.model.customer.Category</class>
  </persistence-unit>

</persistence>

Which works, but could be time consuming and error prone.

Third solution is to use PersistenceUnitPostProcessors, which will scan all entities and add them to persistence unit.

package com.bewareofthebear.application;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.scannotation.AnnotationDB;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;

public class TestPersistenceUnitPostProcessor implements  PersistenceUnitPostProcessor  {
  private final Logger log = LoggerFactory.getLogger( TestPersistenceUnitPostProcessor.class );

  public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
    URL persistenceUnitRootUrl = pui.getPersistenceUnitRootUrl();

    String protocol = persistenceUnitRootUrl.getProtocol();
    String host =  persistenceUnitRootUrl.getHost();
    int port = persistenceUnitRootUrl.getPort();
    String file = persistenceUnitRootUrl.getFile();
    String newFile = file.substring(0, file.lastIndexOf("test-classes")) + "classes/";

    URL url = null;
    try {
      url = new URL(protocol, host, port, newFile);
    } catch (MalformedURLException e) {
      log.warn( "Malformed url: " + url, e );
      return;
    }

    AnnotationDB annotationDB = new AnnotationDB();
    try {
      annotationDB.scanArchives(url);
    } catch (IOException e) {
      log.warn( "Unexpected IOException", e );
      return;
    }

    if (annotationDB.getAnnotationIndex().containsKey("javax.persistence.Entity")) {
      for (String entity : annotationDB.getAnnotationIndex().get("javax.persistence.Entity")) {
        pui.addManagedClassName(entity);
        log.debug( "Adding: {}", entity );
      }
    }
  }

}

PersistenceUnitPostProcessors has to be wired to LocalContainerEntityManagerFactoryBean:

  <property name="persistenceUnitPostProcessors">
    <list><bean class="com.bewareofthebear.application.TestPersistenceUnitPostProcessor"/></list>
  </property>

Now, the configuration is completed, so it is time to move on and create some tests.

Test classes

The basic template for creating test classes:

package com.bewareofthebear.test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.AfterTransaction;
import org.springframework.test.context.transaction.BeforeTransaction;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/config/applicationContext.xml"})
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)
@Transactional
public class JPATestTemplate {

  @BeforeTransaction
  public void verifyInitialDatabaseState() {
  // logic to verify the initial state before a transaction is started
  }

  @Before
  public void setUpTestDataWithinTransaction() {
  // set up test data within the transaction
  }

  @Test
  @Rollback(true)
  public void modifyDatabaseWithinTransaction() {
  // logic which uses the test data and modifies database state
  }

  @After
  public void tearDownWithinTransaction() {
  //  execute "tear down" logic within the transaction
  }

  @AfterTransaction
  public void verifyFinalDatabaseState() {
  // logic to verify the final state after transaction has rolled back
  }

}
  • @RunWith(SpringJUnit4ClassRunner.class) – tells JUnit to use Spring’s own built-in Test Runner that is aware of Spring-specific annotations
  • @ContextConfiguration(locations={“classpath:/config/applicationContext.xml”}) – creates a Spring context for this test from the specified context file.
  • @Transactional – before the method is executed a transaction is opened, upon exit the transaction is commited unless an exception occurs in which case it is rolled back.
  • @TransactionConfiguration(transactionManager=”transactionManager”, defaultRollback=false) – defines class-level metadata for configuring transactional tests
  • @Rollback(true) – forces the database to rollback this transaction when the test terminates regardless of whether the test fails, an exception is thrown or not.

Sample usage:

package com.bewareofthebear.test;

import static org.junit.Assert.assertEquals;

import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

import com.bewareofthebear.domain.model.customer.Customer;
import com.bewareofthebear.infrastructure.persistence.CustomerDao;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:/config/applicationContext.xml"})
@TransactionConfiguration(transactionManager="transactionManager", defaultRollback=false)
@Transactional
public class JPATestCustomer {

  @Autowired
  CustomerDao customerDao;

  @Before
  public void setUpTestDataWithinTransaction() {
    Customer customer = null;

    customer = new Customer ();
    customer.setFirstName("John"); customer.setFirstName("Doe");
    customerDao.persist(customer);

    customer = new Customer ();
    customer.setFirstName("Jack"); customer.setFirstName("Rabbit");
    customerDao.persist(customer);

    customer = new Customer ();
    customer.setFirstName("Richard "); customer.setFirstName("Roe");
    customerDao.persist(customer);
  }

  @Test
  @Rollback(true)
  public void countTest() {
    Long count = customerDao.countAll();
    assertEquals(count, new Long(3));
  }

  @Test
  @Rollback(true)
  public void findAllTest() {
    List<Customer> all = customerDao.findAll();
    assertEquals(all.size(), 3);
  }

}

Complete project

complete sources used during writing.

December 25th, 2009Ext JS Integration with Spring

Problem

Create Ext JS grid able to read data in XML format. Provide XML data from Spring controller. Bind it all together.

To demonstrate an integration between Ext JS and Spring frameworks I am going to use one of Ext JS grid samples – Progress Bar Pager. This grid displays Dow Jones components using Ext.data.ArrayReader which is one of the three, built in Ext.data.DataReader implementation. Since data will be served from a server, an ArrayReader has to be replaced with a XMLReader. Ext JS provides a helper class, XMLStore, which is automatically configured with an XMLReader, so I am going to use it.

DJIA Grid

Ext.onReady(function() {

  // example of custom renderer function
  function change(val) {
    if (val > 0) {
      return '<span style="color:green;">' + val + '</span>';
    } else if (val < 0) {
      return '<span style="color:red;">' + val + '</span>';
    }
      return val;
  }

  // example of custom renderer function
  function pctChange(val) {
    if (val > 0) {
      return '<span style="color:green;">' + val + '%</span>';
    } else if (val < 0) {
      return '<span style="color:red;">' + val + '%</span>';
    }
    return val;
  }

  // create the data store
  var xmlStockStore = new Ext.data.XmlStore({
    autoDestroy : true,
    url : '/zone/rest/djia',
    record : 'component',
    idPath : 'symbol',
    totalProperty : 'totalRecords',
    fields : [
      {name : 'name'},
      {name : 'price', type : 'float'},
      {name : 'valChange', type : 'float'},
      {name : 'pctChange', type : 'float'},
      {name : 'lastUpdate', type : 'date', dateFormat : 'Y-m-d H:i:s.u T'}
    ]
  });

  // create the Grid
  var grid = new Ext.grid.GridPanel({
    store : xmlStockStore,
    columns : [
      {id : 'company', header : "Company", width : 160, sortable : true, dataIndex : 'name'},
      {header : "Price", width : 75, sortable : true, renderer : 'usMoney', dataIndex : 'price'},
      {header : "Change", width : 75, sortable : true, renderer : change, dataIndex : 'valChange'},
      {header : "% Change", width : 75, sortable : true, renderer : pctChange, dataIndex : 'pctChange'},
      {header : "Last Updated", width : 95, sortable : true, renderer : Ext.util.Format.dateRenderer('d-m-Y H:i'), dataIndex : 'lastUpdate'}
    ],
    stripeRows : true,
    autoExpandColumn : 'company',
    height : 320,
    width : 545,
    frame : true,
    title : 'DJIA',

    bbar : new Ext.PagingToolbar({
      pageSize : 10,
      store : xmlStockStore,
      displayInfo : true,
      displayMsg : 'Displaying item {0} - {1} of {2}',
      emptyMsg : "No item to display",

      plugins: new Ext.ux.ProgressBarPager()
    })
  });

  grid.render('grid-example');

  xmlStockStore.load({params : {start : 0, limit : 10}});
});

The grid above is configured to consume an xml of the form:

<?xml version="1.0" encoding="UTF-8"?>
<djia>
  <totalRecords>30</totalRecords>
  <components>
    <component>
      <symbol>MMM</symbol>
      <name>3M Co </name>
      <price>60.46</price>
      <valChange>0.12</valChange>
      <pctChange>0.2</pctChange>
      <lastUpdate>2009-12-24 15:00:00.0 CET</lastUpdate>
    </component>
  </components>
</djia>

So the last thing to do is to configure Spring to deliver an XML in a required form.

Thanks to Spring 3.0 REST support and ContentNegotiatingViewResolver providing an XML content is an extremally easy task. First, Spring configuration:

web.xml

	<servlet>
		<servlet-name>SpringDispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value/>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>SpringDispatcher</servlet-name>
		<url-pattern>/rest/*</url-pattern>
	</servlet-mapping>

applicationContext.xml

  <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver" p:order="1">
    <property name="mediaTypes">
      <map>
        <entry key="xml" value="application/xml"/>
      </map>
    </property>
    <property name="defaultViews">
      <bean class="org.springframework.web.servlet.view.xml.MarshallingView">
        <property name="marshaller">
          <bean class="org.springframework.oxm.xstream.XStreamMarshaller"
            p:autodetectAnnotations="true"
          />
        </property>
      </bean>
    </property>
  </bean>

As seen above, I am going to use an XStream library to serialize objects to XML. XStream is easy configurable with annotations, so the single DJIA component:

Component

import java.util.Date;

import com.thoughtworks.xstream.annotations.XStreamAlias;

@XStreamAlias("component")
public class Component {

  private String symbol;
  private String name;
  private Double price;
  @XStreamAlias("valChange")
  private Double valueChange;
  @XStreamAlias("pctChange")
  private Double percentChange;
  private Date lastUpdate;

  public Component () {
    super ();
  }

  public Component(String symbol, String name, Double price, Double valueChange, Double percentChange, Date lastUpdate) {
    super();
    this.symbol = symbol;
    this.name = name;
    this.price = price;
    this.valueChange = valueChange;
    this.percentChange = percentChange;
    this.lastUpdate = lastUpdate;
  }

  public String getSymbol() {
    return symbol;
  }
  public String getName() {
    return name;
  }
  public Double getPrice() {
    return price;
  }
  public Double getValueChange() {
    return valueChange;
  }
  public Double getPercentChange() {
    return percentChange;
  }
  public Date getLastUpdate() {
    return lastUpdate;
  }

  public void setSymbol(String symbol) {
    this.symbol = symbol;
  }
  public void setName(String name) {
    this.name = name;
  }
  public void setPrice(Double price) {
    this.price = price;
  }
  public void setValueChange(Double valueChange) {
    this.valueChange = valueChange;
  }
  public void setPercentChange(Double percentChange) {
    this.percentChange = percentChange;
  }
  public void setLastUpdate(Date lastUpdate) {
    this.lastUpdate = lastUpdate;
  }
}

and all of the components:

IndexDTO

import java.util.LinkedList;

import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.zone.domain.model.Component;

@XStreamAlias("djia")
public class IndexDTO {

  private int totalRecords;
  private LinkedList <Component> components;

  public void setTotalRecords(int totalRecords) {
    this.totalRecords = totalRecords;
  }
  public void setComponents(LinkedList <Component> components) {
    this.components = components;
  }

  public int getTotalRecords() {
    return totalRecords;
  }
  public LinkedList <Component> getComponents() {
    return components;
  }

}

IndexDTO is a helper class, which will be eventually marshalled and sent to browser, totalRecords variable is optional, but grid PagingToolbar will not work without it.

Finally, the controller:

IndexController

import java.util.LinkedList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.zone.domain.model.Component;
import com.zone.infrastructure.repository.DJIARepository;
import com.zone.web.grid.IndexDTO;

@Controller
public class IndexController {

  @Autowired
  DJIARepository djiaRepository;

  @RequestMapping(value = "/djia")
  public void getComponents(@RequestParam("start") int start, @RequestParam("limit") int limit, Model model) {

    List <Component> components= (List<Component>) djiaRepository.findAll();
    IndexDTO indexDTO = new IndexDTO ();

    indexDTO.setTotalRecords(components.size());
    indexDTO.setComponents(new LinkedList<Component> (components.subList(start, start+limit > components.size() ? components.size() : start+limit)));

    model.addAttribute("indexDTO", indexDTO);
  }

}

DJIARepository is a class holding all DJIA components.

Conclusion

It is actuall all, what is necessary, to have an Ext JS grid populated with data coming from Java based back end. Of course, all hard work is done by Spring and Xstream with some configuration and programming left to the application developer.

Problem

Mapping One to One association with JPA is pretty straitforward. The following entities:

Employee.java

package com.application.onetoone.model;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "EMPLOYEES")
public class Employee  {

  private Integer employeeId;
  private Desk desk;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name="employee_id")
  public Integer getEmployeeId() {
    return employeeId;
  }

  @OneToOne (cascade=CascadeType.ALL, fetch=FetchType.LAZY)
  @JoinColumn(name="desk_id", unique=true)
  public Desk getDesk() {
    return desk;
  }

  public void setEmployeeId(Integer employeeId) {
    this.employeeId = employeeId;
  }

  public void setDesk(Desk desk) {
    this.desk = desk;
  }

}

and

Desk.java

package com.application.onetoone.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "DESKS")
public class Desk {

  private Integer deskId;
  private String description;
  private Employee employee;

  @Id
  @GeneratedValue(strategy=GenerationType.AUTO)
  @Column(name="desk_id")
  public Integer getDeskId() {
    return deskId;
  }

  @Column(name="description")
  public String getDescription() {
    return description;
  }

  @OneToOne(mappedBy="desk", fetch=FetchType.EAGER)
  public Employee getEmployee() {
    return employee;
  }

  public void setDeskId(Integer deskId) {
    this.deskId = deskId;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  public void setEmployee(Employee employee) {
    this.employee = employee;
  }

}

generate the following database schema:
One-To-One
The owning entity – Employee – contains additional column – desk_id, which maps to the ownded entity – Desk. Having the configuration above I can:

assign a desk to employee:

    Employee employee = new Employee ();

    desk = deskDao.load(2);
    if (null == desk.getEmployee()) {
      employee.setDesk(desk);
    }

ask where a given employee is sitting:

    String description = employee.getDesk().getDescription();

or ask who is sitting at given desk:

    Integer employeeId = desk.getEmployee().getEmployeeId();

and, since they are not glued, an employee can empty his current desk and get a new one:

    Employee employee = new Employee ();

    desk = deskDao.load(4);
    if (null == desk.getEmployee()) {
      employee.setDesk(desk);
    }

A relation between employee and a seat is temporal. An employee can leave, a seat can be freed and reassing to someone else. There are however relations, which are everlasting and can not be changed over the time of entity life. Let’s say, I want to identify an employee – I give him a first name, last name and a date of birth. In order to to this I crete a separate entity:

EmployeeDetails.java

package com.application.onetoone.model;

import java.util.Calendar;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name = "EMPLOYEE_DETAILS")
public class EmployeeDetails {

  private Integer employeeId;
  private String firstName;
  private String lastName;
  private Calendar dateOfBirth;
  private Employee employee;

  @Id
  @Column(name="employee_id")
  public Integer getEmployeeId() {
    return employeeId;
  }

  @Column(name="first_name")
  public String getFirstName() {
    return firstName;
  }

  @Column(name="last_name")
  public String getLastName() {
    return lastName;
  }

  @Temporal(TemporalType.DATE)
  @Column(name="date_of_birth")
  public Calendar getDateOfBirth() {
    return dateOfBirth;
  }

  @OneToOne(mappedBy="employeeDetails", fetch=FetchType.EAGER)
  public Employee getEmployee() {
    return employee;
  }

  public void setEmployeeId(Integer employeeId) {
    this.employeeId = employeeId;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
  public void setDateOfBirth(Calendar dateOfBirth) {
    this.dateOfBirth = dateOfBirth;
  }

  public void setEmployee(Employee employee) {
    this.employee = employee;
  }

}

which I want to share a primary key with it’s parent entity – employee, which I need to amend:

package com.application.onetoone.model;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "EMPLOYEES")
public class Employee  {

  private Integer employeeId;
  private Desk desk;
  private EmployeeDetails employeeDetails;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name="employee_id")
  public Integer getEmployeeId() {
    return employeeId;
  }

  @OneToOne (cascade=CascadeType.ALL, fetch=FetchType.LAZY)
  @JoinColumn(name="desk_id", unique=true)
  public Desk getDesk() {
    return desk;
  }

  @OneToOne (cascade=CascadeType.ALL, fetch=FetchType.LAZY)
  @PrimaryKeyJoinColumn
  public EmployeeDetails getEmployeeDetails() {
    return employeeDetails;
  }

  public void setEmployeeId(Integer employeeId) {
    this.employeeId = employeeId;
  }

  public void setDesk(Desk desk) {
    this.desk = desk;
  }

  public void setEmployeeDetails(EmployeeDetails employeeDetails) {
    this.employeeDetails = employeeDetails;
  }

}

The entities above generate the following database schema:
One-To-One
As you can see, there is no foreign key generated between Employee and EmployeDetails. This is default Hibernate behaviour and was already raised as a bug, however, it is not fixed as of now. Additionally, the configuration above does not assign any key to EmployeeDetails and the following code:

    Employee employee = new Employee ();

    Desk desk = new Desk ();
    desk.setDescription("T114A45");
    employee.setDesk(desk);

    EmployeeDetails employeeDetails = new EmployeeDetails ();
    employeeDetails.setFirstName("John");
    employeeDetails.setLastName("Doe");
    employee.setEmployeeDetails(employeeDetails);      

    employeeDao.save(employee);

throws a HibernateSystemException with a following message: ids for this class must be manually assigned before calling save()
.
How do I assign it ?

Solution one – simple and ugly

Without going beyond the JPA annotation there is nothing smart that can be done. employee_id is not known before the Employee record is actually persisted, so it seems that the only way to get it right is:

    Employee employee = new Employee ();

    Desk desk = new Desk ();
    desk.setDescription("T114A45");
    employee.setDesk(desk);

    // save it
    employee = employeeDao.save(employee); 

    EmployeeDetails employeeDetails = new EmployeeDetails ();
    employeeDetails.setFirstName("John");
    employeeDetails.setLastName("Doe");
    // set employee_id
    employeeDetails.setEmployeeId(employee.getEmployeeId());
    employee.setEmployeeDetails(employeeDetails);      

    // save again
    employeeDao.save(employee);

The part of the code responsilbe for a proper mapping is left to the client. Obviously, it does the job, but this looks like workaround rather than solution.

Solution two – Hibernate GenericGenerator

JPA does not provide support for custom key generators, but Hibernate is closing the gap. First, we have to tell Hibernate, where the source of the primary key. Hibernate @GenericGenerator annotations provides the solution:

EmployeeDetails.java

package com.application.onetoone.model;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@Entity
@Table(name = "EMPLOYEE_DETAILS")
public class EmployeeDetails {

  private Integer employeeId;
  private String firstName;
  private String lastName;
  private Date dateOfBirth;
  private Employee employee;

  @Id
  @GeneratedValue(generator = "foreign")
  @GenericGenerator(name = "foreign", strategy = "foreign",
    parameters = {@Parameter(name = "property", value = "employee")}
  )
  @Column(name="employee_id")
  public Integer getEmployeeId() {
    return employeeId;
  }

  @Column(name="first_name")
  public String getFirstName() {
    return firstName;
  }

  @Column(name="last_name")
  public String getLastName() {
    return lastName;
  }

  @Temporal(TemporalType.DATE)
  @Column(name="date_of_birth")
  public Date getDateOfBirth() {
    return dateOfBirth;
  }

  @OneToOne(mappedBy="employeeDetails", fetch=FetchType.EAGER)
  public Employee getEmployee() {
    return employee;
  }

  public void setEmployeeId(Integer employeeId) {
    this.employeeId = employeeId;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

  public void setDateOfBirth(Date dateOfBirth) {
    this.dateOfBirth = dateOfBirth;
  }

  public void setEmployee(Employee employee) {
    this.employee = employee;
  }

}

@GenericGenerator with strategy set to foreign tells Hibernate to obtain a primary key value from one of its properties.
The last thing left to do is to make sure, the property used to generate id value is not null. Since EmployeeDetails is an owned entity, it makes perfect sense to change the the owning entity – Employee:

package com.application.onetoone.model;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "EMPLOYEES")
public class Employee  {

  private Integer employeeId;
  private Desk desk;
  private EmployeeDetails employeeDetails;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name="employee_id")
  public Integer getEmployeeId() {
    return employeeId;
  }

  @OneToOne (cascade=CascadeType.ALL, fetch=FetchType.LAZY)
  @JoinColumn(name="desk_id", unique=true)
  public Desk getDesk() {
    return desk;
  }

  @OneToOne (cascade=CascadeType.ALL, fetch=FetchType.LAZY)
  @PrimaryKeyJoinColumn
  public EmployeeDetails getEmployeeDetails() {
    return employeeDetails;
  }

  public void setEmployeeId(Integer employeeId) {
    this.employeeId = employeeId;
  }

  public void setDesk(Desk desk) {
    this.desk = desk;
  }

  public void setEmployeeDetails(EmployeeDetails employeeDetails) {
    this.employeeDetails = employeeDetails;
    // for @GenericGenerator
    employeeDetails.setEmployee(this);
  }

}

Now we can create an employee:

    Employee employee = new Employee ();      

    EmployeeDetails employeeDetails = new EmployeeDetails ();
    employeeDetails.setFirstName("John"); employeeDetails.setLastName("Doe");
    employee.setEmployeeDetails(employeeDetails);

    Desk desk = new Desk ();
    desk.setDescription("T114A45");
    employee.setDesk(desk);

    employeeDao.save(employee);

Ask where employee is sitting:

    String desk = employeeDetailsDao.find("lastName", "Doe").get(0).getEmployee().getDesk().getDescription();

or who is sitting here:

    String employeeName = deskDao.find("description", "T114A45").get(0).getEmployee().getEmployeeDetails().getLastName();

Problem

Most likely, each DAO class implements basic CRUD operations. Since these are the same for all possible entities, it makes perfect sense to have one generic DAO class which implements common CRUDs and extend it when necessary adding anything which is required by a specific entity instance.

Simple generic DAO should implement the following interface:

SimpleDao.java

package com.application.sample;

import java.io.Serializable;

public interface SimpleDao <PK extends Serializable, E extends AbstractEntity <PK>> {
  public E create(E entity);
  public E read(PK id);
  public E update(E entity);
  public void delete(PK id);
}

When implementing generic DAO using Hibernate as JPA provider we are facing the problem. Hibernate load and get operations require information about object being retrieved. Either object class, class name or the object instance has to be provided before actual read operation can be executed. None of these information is accessible before generic DAO is extended and instantiated. I can think of two possible solutions, an obvious one – asking implementation to deliver required information, and nice one – using java.lang.reflection.ParameterizedType.

Lets assume, I have an abstract entity, which defines fields common to all entities in my application:

AbstractEntity .java

package com.application.sample;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import javax.persistence.Version;

@MappedSuperclass
public abstract class AbstractEntity <PK extends Serializable> implements Serializable {
  private static final long serialVersionUID = -6991226731574845156L;

  public AbstractEntity () {
  }

  private PK primaryKey;
  private Integer version;

  @Transient
  public PK getPrimaryKey () {
    return primaryKey;
  }

  @Version
  @Column(name="version", nullable=false)
  public Integer getVersion() {
    return version;
  }

  public void setPrimaryKey (PK primaryKey) {
    this.primaryKey = primaryKey;
  }

  public void setVersion(Integer version) {
    this.version = version;
  }

}

And Employee entity:

Employee.java

package com.application.sample;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Index;

@Entity
@Table(name = "EMPLOYEES")
@org.hibernate.annotations.Table(
  indexes = {@Index(name="lastNameIdx", columnNames={"last_name"} )},
  appliesTo = "EMPLOYEES"
)
public class Employee extends AbstractEntity <Integer> {
  private static final long serialVersionUID = -1693502528557287614L;

  private String firstName = null;
  private String lastName = null;

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name="employee_id")
  public Integer getEmployeeId() {
    return getPrimaryKey();
  }

  @Column(name = "first_name")
  public String getFirstName() {
    return firstName;
  }

  @Column(name = "last_name")
  public String getLastName() {
    return lastName;
  }

  public void setEmployeeId(Integer employeeId) {
    setPrimaryKey(employeeId);
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }

}

For an Employee entity I want to have a possibility to find employees by their last name, so I add the required method the specification:

EmployeeDao.java

package com.application.sample;

import java.util.List;

public interface EmployeeDao extends SimpleDao<Integer, Employee> {

  public List<Employee> readEmployeeByLastName(String lastName);

}


Solution one – pass the buck.

Generic DAO implementation:

AbstractPassTheBuckDao.java

package com.application.sample;

import java.io.Serializable;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class AbstractPassTheBuckDao<PK extends Serializable, E extends AbstractEntity <PK>>
       extends HibernateDaoSupport implements SimpleDao <PK, E>   {

  public AbstractPassTheBuckDao() {
  }

  protected AbstractPassTheBuckDao(SessionFactory sessionFactory) {
    this();
    this.setSessionFactory(sessionFactory);
  }

  // Ask the implementation for entity class
  abstract protected Class<E> getPersistentClass ();

  public E create(E entity) {
    this.getHibernateTemplate().save(entity);
    return entity;
  }

  @SuppressWarnings("unchecked")
  public E read(PK id) {
    E entity = (E) this.getHibernateTemplate().get(getPersistentClass(), id);
    return entity;
  }

  public E update(E entity) {
    this.getHibernateTemplate().merge(entity);
    return entity;
  } 

  public void delete(PK id) {
    this.getHibernateTemplate().delete(read(id));
  }

}

Employee DAO implementation:

EmployeePassTheBuckDao.java

package com.application.sample;

import java.util.List;

public class EmployeePassTheBuckDao
       extends AbstractPassTheBuckDao <Integer, Employee> implements EmployeeDao {

  // Deliver entity class
  protected Class<Employee> getPersistentClass() {
    return Employee.class;
  }

  @SuppressWarnings("unchecked")
  public List<Employee> readEmployeeByLastName(String lastName) {
    String queryString = "from Employee where lastName = :lastName";
    String paramName = "lastName";
    return (List<Employee>) this.getHibernateTemplate().findByNamedParam(queryString, paramName, lastName);
  }

}


Solution two – do it yourself.

Generic DAO implementation:

AbstractDoItYourselfDao.java

package com.application.sample;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;

import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class AbstractDoItYourselfDao<PK extends Serializable, E extends AbstractEntity <PK>>
       extends HibernateDaoSupport implements SimpleDao <PK, E>   {

  private Class<E> persistentClass;

  @SuppressWarnings("unchecked")
  public AbstractDoItYourselfDao() {
    // retrieve entity class
    ParameterizedType paramType = null;
    Type type = getClass().getGenericSuperclass();
    if (type instanceof ParameterizedType) {
      paramType = (ParameterizedType) type;
    } else {
      paramType = (ParameterizedType) getClass().getSuperclass().getGenericSuperclass();
    }

    if (paramType.getActualTypeArguments().length == 2) {
      if (paramType.getActualTypeArguments()[1] instanceof TypeVariable) {
        throw new IllegalArgumentException("Could not persistent entity class using reflection");
      } else {
        persistentClass = (Class<E>) paramType.getActualTypeArguments()[1];
      }
    } else {
      persistentClass = (Class<E>) paramType.getActualTypeArguments()[0];
    }

  }

  protected AbstractDoItYourselfDao(SessionFactory sessionFactory) {
    this();
    this.setSessionFactory(sessionFactory);
  }

  // deliver entity class
  protected Class<E> getPersistentClass () {
    return persistentClass;
  }

  public E create(E entity) {
    this.getHibernateTemplate().save(entity);
    return entity;
  }

  @SuppressWarnings("unchecked")
  public E read(PK id) {
    E entity = (E) this.getHibernateTemplate().get(getPersistentClass(), id);
    return entity;
  }

  public E update(E entity) {
    this.getHibernateTemplate().merge(entity);
    return entity;
  } 

  public void delete(PK id) {
    this.getHibernateTemplate().delete(read(id));
  }

}

Employee DAO implementation:

EmployeeDoItYourselfDao .java

package com.application.sample;

import java.util.List;

public class EmployeeDoItYourselfDao
       extends AbstractDoItYourselfDao <Integer, Employee> implements EmployeeDao {

  @SuppressWarnings("unchecked")
  public List<Employee> readEmployeeByLastName(String lastName) {
    String queryString = "from Employee where lastName = :lastName";
    String paramName = "lastName";
    return (List<Employee>) this.getHibernateTemplate().findByNamedParam(queryString, paramName, lastName);
  }

}

As seen above, the EmployeeDao implementation implements only Employee related operations and there is no need to deliver Employee class to generic DAO superclass.

Java generics are checked for type correctness at compile time, when a generic type is instantiated, the compiler removes generic type information by a type erasure technique. A generic class is translated to a raw type – generic type without any type arguments. Consequently, when a type is not known during both compile time and runtime, it is not possible to instantiate a generic type parameter using a constructor call. The following code:

  private I i= new I ();

will not compile.

In this post I’ll describe two possible solutions, both using java.lang.Reflection package.

Let’s assume we have a generic Envelope class, which is used to pair a content object – Content – with additional information related to it – ContentInfo.

Envelope.java

package com.application.generics;

import java.io.Serializable;

public class Envelope <I extends ContentInfo, C extends Serializable> implements Serializable {
  private static final long serialVersionUID = -6433250240547869806L;

  private I contentInfo;
  private C content;

  public Envelope () {
  }

  public Envelope (I contentInfo) {
    this.contentInfo = contentInfo;
  }

  public Envelope (I contentInfo, C content) {
    this.contentInfo = contentInfo;
    this.content = content;
  }

  public I getContentInfo() {
    return contentInfo;
  }

  public C getContent() {
    return content;
  }

  public void setContent(C content) {
    this.content = content;
  }

  public void setContentInfo(I contentInfo) {
    this.contentInfo = contentInfo;
  }

}

ContentInfo is an interface:

ContentInfo.java

package com.application.generics;

public interface ContentInfo {

  public boolean isContentValid();

}

And its three possible implementations:

ContentAlwaysValid.java

package com.application.client;

import java.io.Serializable;

import com.application.generics.ContentInfo;

public class ContentAlwaysValid implements ContentInfo, Serializable {
  private static final long serialVersionUID = 8019707740072299936L;

  public boolean isContentValid() {
    return true;
  }

}

ContentNeverValid .java

package com.application.client;

import java.io.Serializable;

import com.application.generics.ContentInfo;

public class ContentNeverValid implements ContentInfo, Serializable {
  private static final long serialVersionUID = -861952203103353570L;

  public boolean isContentValid() {
    return false;
  }

}

ContentSometimesValid.java

package com.application.client;

import java.io.Serializable;

import com.application.generics.ContentInfo;

public class ContentSometimesValid implements ContentInfo, Serializable {
  private static final long serialVersionUID = 2731488051426426010L;

  private boolean contentValid;

  public ContentSometimesValid (boolean contentValid) {
    this.contentValid = contentValid;
  }

    public boolean isContentValid() {
      return contentValid;
    }

}

Additionally, let’s say, there is requirement, that the contentInfo is initialized to its default value whenever an object of the Envelope class is instantiated. The common solution is a factory class, which provides a method which instantiates an object of a given class using Reflection API. In our case, a simple factory class – ContentWrapper – might look like this:

ContentWrapper.java

package com.application.generics;

import java.io.Serializable;

public class ContentWrapper <I extends ContentInfo, C extends Serializable> {

  @SuppressWarnings("unchecked")
  public Envelope <I, C> wrapContent (Class<?> cls, C content) {
    I contentInfo = null;
    try {
      contentInfo = (I) cls.newInstance();
    } catch (Exception exception) {
      throw new RuntimeException(exception);
    }
    return new Envelope <I, C> (contentInfo, content);
  }

}

ContentWrapper does the job. The following code:

ContentWrapperTest.java

public class GenericsTest {

  private void ContentWrapperTest () {

    ContentWrapper <ContentInfo, String> contentWrapper = new  ContentWrapper <ContentInfo, String> ();
    Envelope <ContentInfo, String> envelope = null;

    envelope = contentWrapper.wrapContent(ContentAlwaysValid.class, new String("I am a message"));
    System.out.println("Content is " + (envelope.getContentInfo().isContentValid() ? "valid" : "invalid") + ".");    

    envelope = contentWrapper.wrapContent(ContentNeverValid.class, new String("I am a message"));
    System.out.println("Content is " + (envelope.getContentInfo().isContentValid() ? "valid" : "invalid") + ".");    

  }

}

compiles and runs fine. However, this test:

    envelope = contentWrapper.wrapContent(ContentSometimesValid.class, new String("I am a message"));
    System.out.println("Content is " + (envelope.getContentInfo().isContentValid() ? "valid" : "invalid") + ".");

compiles, but during the runtime a java.lang.InstantiationException is thrown.

In some cases, instantiating an object without any meaningful content makes no sense, and developers are protecting themselves against such cases by not providing default, public constructor. Now we have a conflict of interests. Implementation deliberately does not provide a default constructor, which is necessary to instantiate an object in a reflective way. What if a constructor were provided, but with non public access modifier?

ContentSometimesValid.java

package com.application.client;

import java.io.Serializable;

import com.application.generics.ContentInfo;

public class ContentSometimesValid implements ContentInfo, Serializable {
  private static final long serialVersionUID = 2731488051426426010L;

  private boolean contentValid;

  protected ContentSometimesValid () {
    contentValid = true;
  }

  public ContentSometimesValid (boolean contentValid) {
    this.contentValid = contentValid;
  }

  public boolean isContentValid() {
    return contentValid;
  }

}

Protected constructor alone does not solve the problem – java.lang.IllegalAccessException is thrown during the runtime with a following message: Class com.application.generics.ContentWrapper can not access a member of class com.application.client.ContentSometimesValid with modifiers “protected”. Fortunately, reflection API allows code to perform actions, which would be illegal in standard code, such as invoking non public methods. In order to use this feature, we need to change our ContentWrapper class to make constructor accessible:

ContentWrapper .java

package com.application.generics;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;

public class ContentWrapper <I extends ContentInfo, C extends Serializable> {

  @SuppressWarnings("unchecked")
  public Envelope <I, C> wrapContent (Class<?> cls, C content) {

    Constructor<?> ctor = null;
    try {
      ctor = cls.getDeclaredConstructor((Class<?>[]) null);
    } catch (Exception exception) {
      throw new RuntimeException(exception);
    } 

    // make constructor accessible, if it is not already public
    if (!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) {
      ctor.setAccessible(true);
    }        

    I contentInfo = null;
    try {
      contentInfo = (I) ctor.newInstance();
    } catch (Exception exception) {
      throw new RuntimeException(exception);
    }

    return new  Envelope <I, C> (contentInfo, content);
  }

}

Modified ContentWrapper class is sufficient to do what is required, however, it is not type-safe. Since the singature of a wrapContent method:

  public Envelope <I, C> wrapContent (Class<?> cls, C content);

requires a parameter of type Class, then the following code:

  envelope = contentWrapper.wrapContent(String.class, new String("I am a message"));

compiles and obviously failes during the runtime with a java.lang.ClassCastException.

Solution to this problem comes with a java.lang.reflect.ParameterizedType interface. Using this interface is a little bit tricky since a class, within it is used, must be derived from another generic class. We can achieve it by making our ContentWrapper abstract and then instantiating it with unnamed implementations. Then, instead of passing a ContentInfo class as a parameter, we can retrieve it from ParameterizedType.

ContentWrapper .java

package com.application.generics;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;

public abstract class ContentWrapper <I extends ContentInfo, C extends Serializable> {

  @SuppressWarnings("unchecked")
  public Envelope <I, C> wrapContent (C content) {

    // get a class
    Class<I> cls  = (Class<I>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];

    Constructor<I> ctor = null;
    try {
      ctor = cls.getDeclaredConstructor((Class<?>[]) null);
    } catch (Exception exception) {
      throw new RuntimeException(exception);
    } 

    if (!Modifier.isPublic(ctor.getModifiers()) || !Modifier.isPublic(ctor.getDeclaringClass().getModifiers())) {
      ctor.setAccessible(true);
    }        

    I contentInfo = null;
    try {
      contentInfo = ctor.newInstance();
    } catch (Exception exception) {
      throw new RuntimeException(exception);
    }

    return new  Envelope <I, C> (contentInfo, content);
  }

}

And on the client side:

  private void ContentWrapperTest () {

    // an abstract class is implemented
    ContentWrapper <ContentSometimesValid, String> contentWrapper = new  ContentWrapper <ContentSometimesValid, String> () {};
    Envelope <ContentSometimesValid, String> envelope = null;

    envelope = contentWrapper.wrapContent(new String("I am a message"));    

    System.out.println("Content is " + (envelope.getContentInfo().isContentValid() ? "valid" : "invalid") + ".");    

  }

Enforcing type correctness makes ContentWrapper and Envelope classes less generic, since it is not possible now to have one Envelope and one ContentWrapper instance for any ContentInfo implementation. the following code:


    Envelope <ContentInfo, String> envelope = contentWrapper.wrapContent(new String("I am a message"));

does not compile.

As seen, there is a certain trade off between both approaches and it is difficult to say which implementation is more correct. My guess is, it depends.

October 18th, 2009Hello World!

Hello World.

public class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello World!");
  }
}

© 2007 Toss a coin | iKon Wordpress Theme by Windows Vista Administration | Powered by Wordpress