What’s The Deal With Half Up and Half Even Rounding?

java.math package came with several rounding mode but there are 2 quite interesting ones: HALF_UP and HALF_EVEN rounding.

HALF_UP

This is basically your elementary school rounding. If the fractions to be rounded are equidistant from its neighbor, then round them into the upper neighbour. In other words, if we’re rounding 1 digit after decimal, then if it ends with .5 just add .5. For example:

Fractional Number Rounded
0.1 0
0.5 1
1.3 1
1.5 2

HALF_EVEN

Similar like HALF_UP, except if the fraction is equidistant, round them into nearest even neighbor. For example:

Fractional Number Rounded
0.1 0
0.5 0
1.3 1
1.5 2

Why Bother With HALF_EVEN?

Why don’t we just stick with what’s learned in elementary school? Well here’s one good reason: accumulative error. Error here means “How much did we lose/gain by rounding the number?”. Let’s take a look again to both table with its rounding error displayed

Fractional Number HALF_UP rounding HALF_UP rounding error HALF_EVEN rounding HALF_EVEN rounding error
0.0 0 0.0 0 0.0
0.1 0 -0.1 0 -0.1
0.2 0 -0.2 0 -0.2
0.3 0 -0.3 0 -0.3
0.4 0 -0.4 0 -0.4
0.5 1 0.5 0 -0.5
0.6 1 0.4 1 0.4
0.7 1 0.3 1 0.3
0.8 1 0.2 1 0.2
0.9 1 0.1 1 0.1
1.0 1 0.0 1 0.0
1.1 1 -0.1 1 -0.1
1.2 1 -0.2 1 -0.2
1.3 1 -0.3 1 -0.3
1.4 1 -0.4 1 -0.4
1.5 2 0.5 2 0.5
1.6 2 0.4 2 0.4
1.7 2 0.3 2 0.3
1.8 2 0.2 2 0.2
1.9 2 0.1 2 0.1
2.0 2 0.0 2 0.0
Total 1 0 0

As you can see the accumulative errors for HALF_UP is incrementally higher whereas HALF_EVEN averages out. This is why HALF_EVEN is often called “Banker’s rounding” because given a large amount of data the bank should not gain/loss money because of rounding.

More Surprises With printf

Don’t yet assume all programming language defaults into HALF_EVEN, try below examples of printf in your shell:

$ printf "%.5f" 1.000015
1.00002
$ printf "%.5f" 1.000025
1.00002
$ printf "%.5f" 1.000035
1.00004
$ printf "%.5f" 1.000045
1.00005

Wait.. what? Isn’t 1.000045 supposed to be rounded to 1.00004? Well in floating point realm the reality is more complicated than that, taking into account floating point is often never accurate in the first place.

Try printing 1.000045 with long enough digits after decimal:

$ printf "%.30f" 1.000045
1.000045000000000072759576141834

Now you can see computers can’t always store accurate value of real numbers in floating point types. (And you should now see why it’s rounded into 1.00005)

Here’s some reading if you’re interested in this problem.

Advertisements

Mapping JSON Request With Spring MVC

Inspired by ContentNegotiatingViewResolver section on Spring manual, this is a short tutorial on how you can map a request with *.json extension into a JSON view.

This tutorial will demonstrate a small subset of Spring JSON capability using the ‘Spring MVC Project’ template application generated by STS. When you first created a new project from the template, the web app came with a default home page showing ‘Hello World’ and a server time passed via Model attribute.

We will extend this home page a little bit so we can obtain the JSON view. Note that the JSON view will only contain the formatted attributes inside the Model object

By the way, if you haven’t already know — JSON stands for Java Script Object Notation. It’s a textual representation of a Java Script object, and it’s one of the most popular way of transferring information from server to client in modern Ajax application.

Create a new project using a template

  1. Assuming you have SpringSource Tools Suite (STS) installed, create a new project and select Spring Template Project Wizard
  2. Select ‘Spring MVC Project’ from the selection of template, it might prompt you to download if this is the first time you’re using it
  3. Enter a project name and top-level package and hit ‘Finish’

Change the view resolver to ContentNegotiatingViewResolver

ContentNegotiatingViewResolver is a unique resolver which will delegate request to another resolver by the requested media types. There are multiple way it can determine the media type, but here we’ll just use the URL extension method (see the javadoc for more).

On the servlet spring beans configuration (servlet-context.xml), replace the default InternalResourceViewResolver with this:

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory.
	If the request has an extension .json, always provide MappingJacksonJsonView regardless -->
	<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
		<property name="mediaTypes">
			<map>
				<entry key="json" value="application/json" />
			</map>
		</property>
		<property name="viewResolvers">
			<list>
				<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
					<property name="prefix" value="/WEB-INF/views/" />
					<property name="suffix" value=".jsp" />
				</bean>
			</list>
		</property>
		<property name="defaultViews">
			<list>
				<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
			</list>
		</property>
	</bean>

In the example above, we define request with the extension “.*json” into “application/json” media type. Normal request is set to “text/html” by the browser by default. When a request came, the list of view resolvers on the “viewResolver” property will be consulted, and if it supports the requested  media type, that view resolver will be used.

The “defaultViews” property specifies the view that will be override the ones provided by matching resolvers (even if none matches) — regardless of the view name returned by the controller. This however only hold true if the View supports the requested media type.

For example, if “/home” path is requested with Accept header “text/html”, ContentNegotiatingViewResolver will set the media type to “text/html”, consult InternalResoursceViewResolver bean (which supports text/html) and use it. If “/home.json” path is requested, the media type is set to “application/json” (not supported by InternalResourceViewResolver), and since the specified default view MappingJacksonJsonView supports it, it will be used. This is sufficient for common usage because all JSON view can be rendered in the same fashion

Have a look at Spring Reference Section 16.5.4 ContentNegotiatingViewResolver for more info.

Change the Controller mapping

STS Spring MVC new project template mapped the MainController into “/”, however for our demonstration purpose, let’s map it to “/home”, so we can compare the different media type easily.

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

	private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

	/**
	 * Simply selects the home view to render by returning its name.
	 */
	@RequestMapping(value = "/home", method = RequestMethod.GET)
	public String home(Locale locale, Model model) {
		logger.info("Welcome home! the client locale is "+ locale.toString());

		Date date = new Date();
		DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);

		String formattedDate = dateFormat.format(date);

		model.addAttribute("serverTime", formattedDate );

		return "home";
	}

}

Add Jackson dependency to your classpath

The MappingJacksonJsonView requires Jackson library in your classpath. This library will help you to transform java objects into JSON representation. Add the following dependency to your pom.xml

		<dependency>
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-lgpl</artifactId>
			<version>1.2.1</version>
		</dependency>

Ready to go

Fire up embedded tomcat using mvn package tomcat:run goals, and:

  1. Point your browser to http://localhost:8080/json-simple/home. Inspect you are getting the normal hello world page with server time
  2. Point your browser to http://localhost:8080/json-simple/home.json. Inspect you are getting the json representation of the model object

The sourcecode for this tutorial is available:

Persisting Data Using JPA

If you ever written a Java application that reads and updates into a relational database in the past, most likely you’ll use the JDBC API. Typically you’ll need to represent the database entity as a java object, and write a service/DAO class to provide CRUD (Create Read Update Delete) facility.

Dealing with persistent data became more tricky when the number of entity types keep growing, and also their complexity of relationships. The amount of code keep growing, and it became harder and harder to maintain. More recently, the better approach is to use ORM (Object Relational Mapping) solution such as Hibernate. With the popularity of ORM techniques, the Java community has also introduced JPA (Java Persistence API) which is a standardized ORM API. Hibernate is one of the popular JPA implementation available.

To give a basic idea, consider following simple example about a book entity. A book is identified by book id, and has author, title and year property.

public class Book {
	private int bookId;
	private String title;
	private String author;
	private int year;

	public Book() {}

	public Book(int bookId, String title, String author, int year) {
		this.bookId = bookId;
		this.title = title;
		this.author = author;
		this.year = year;
	}

	// Getters and setters omitted for brevity
}

Let’s create a DAO to provide CRUD facility over book entity. The DAO is implemented as an interface so it doesn’t need to know what the underlying mechanism used. Later we’ll implement the BookDAO interface using both Jdbc and JPA to compare the difference

public interface BookDAO {
	/**
	 * Find a book by id
	 * @return null if can't find bookId
	 */
	public Book findById(int bookId);

	/**
	 * List all books
	 */
	public List list();

	/**
	 * Persist a new book object into database. The id attribute of the book object will be set
	 * and returned.
	 * @return id of the newly inserted book
	 */
	public int save(Book book);

	/**
	 * Persist changes to existing book object into database.
	 * @param book
	 */
	public void update(Book book);

	/**
	 * Remove persisted book object from database
	 * @param book
	 */
	public void delete(Book book);
}

Following is example on how to implement BookDAO using plain JDBC. This implementation simply opens and closes connection for every method calls, assuming a connection pooled datasource is used. Note how we have to manually construct our CRUD SQL and map the ResultSet object returned by JDBC.

/**
 * Implementation of BookDAO using jdbc, creates and close a new connection for every
 * CRUD method calls. Use connection pooled datasource for efficiency.
 *
 * @author gerry
 *
 */
public class BookJdbcDAOImpl implements BookDAO {

	private DataSource dataSource;

	public BookJdbcDAOImpl (DataSource dataSource) {
		this.dataSource = dataSource;
	}

	@Override
	public Book findById(int bookId) {
		Connection connection = null;
		try {
			connection = dataSource.getConnection();
			Statement statement = connection.createStatement();
			ResultSet rs = statement.executeQuery("SELECT * FROM book WHERE book_id = " + bookId);
			if (!rs.next()) {
				return null;
			}
			Book result = mapRow(rs);
			statement.close();
			return result;

		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				connection.close();
			} catch (SQLException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
		}

	}

	@Override
	public List list() {
		Connection connection = null;
		try {
			connection = dataSource.getConnection();
			Statement statement = connection.createStatement();
			ResultSet rs = statement.executeQuery("SELECT * FROM book");
			ArrayList result = new ArrayList();
			while (rs.next()) {
				result.add(mapRow(rs));
			}
			statement.close();
			return result;
		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				connection.close();
			} catch (SQLException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
		}
	}

	@Override
	public int save(Book book) {
		Connection connection = null;
		try {
			connection = dataSource.getConnection();
			Statement statement = connection.createStatement();
			statement.executeUpdate(
				String.format("INSERT INTO book (title, author, year) VALUES ('%s','%s',%s)",
					book.getTitle(),
					book.getAuthor(),
					book.getYear()),
				Statement.RETURN_GENERATED_KEYS);
			ResultSet rs = statement.getGeneratedKeys();
			if (!rs.next()) {
				throw new IllegalStateException("Error when inserting book to database " + book);
			}
			int generatedKey = rs.getInt(1);
			book.setBookId(generatedKey);
			statement.close();
			return generatedKey;
		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				connection.close();
			} catch (SQLException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
		}
	}

	@Override
	public void update(Book book) {
		Connection connection = null;
		try {
			connection = dataSource.getConnection();
			Statement statement = connection.createStatement();
			int rowUpdated = statement.executeUpdate(
					String.format(
						"UPDATE book " +
						"SET title = '%s', " +
						"author = '%s', " +
						"year = %s " +
						"WHERE book_id = %s",
						book.getTitle(),
						book.getAuthor(),
						book.getYear(),
						book.getBookId()));
			if (rowUpdated != 1) {
				throw new IllegalStateException("Error when trying to update " + book);
			}
			statement.close();
		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				connection.close();
			} catch (SQLException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
		}

	}

	@Override
	public void delete(Book book) {
		Connection connection = null;
		try {
			connection = dataSource.getConnection();
			Statement statement = connection.createStatement();
			int rowUpdated = statement.executeUpdate(
					String.format(
						"DELETE FROM book WHERE book_id = %s",
						book.getBookId()));
			if (rowUpdated != 1) {
				throw new IllegalStateException("Error when trying to delete " + book);
			}
			statement.close();
		} catch (SQLException e) {
			throw new RuntimeException(e.getMessage(), e);
		} finally {
			try {
				connection.close();
			} catch (SQLException e) {
				throw new RuntimeException(e.getMessage(), e);
			}
		}

	}

	private Book mapRow(ResultSet rs) throws SQLException {
		return new Book (
			rs.getInt("book_id"),
			rs.getString("title"),
			rs.getString("author"),
			rs.getInt("year"));
	}

}

With JPA we can achieve the same outcome with much less code. JPA API leverage annotation based entity mapping to make it more easier to map a POJO into database. Let’s decorate our Book entity with some annotation to tell JPA what our database schema looks like.

@Entity
public class Book {
	@Id @GeneratedValue private int bookId;
	@Column private String title;
	@Column private String author;
	@Column private int year;

	public Book() {}

	public Book(int bookId, String title, String author, int year) {
		this.bookId = bookId;
		this.title = title;
		this.author = author;
		this.year = year;
	}

	// Getters and setters omitted for brevity
}

As you can see, we still have the same Book entity POJO class, and the extra @Entity, @Id and @Column annotations is enough to tell JPA what the database schema looks like, and how to persist / retrieve the instance from database. Following is a sample of JPA implementation of BookDAO. Note how in this implementation we don’t have to write any native SQL to retrieve, or save the object, and more importantly, no cumbersome code to map the result set row into an entity object!

	/**
	 * Simple implementation of BookDAO using JPA. Each method simply starts and closes
	 * transaction. Entity object returned by these methods are always detached
	 *
	 * @author gerry
	 *
	 */
	public class BookJPADAOImpl implements BookDAO {

		private EntityManager em;

		public BookJPADAOImpl (EntityManager entityManager) {
			this.em = entityManager;
		}

		@Override
		public Book findById(int bookId) {
			Book result = em.find(Book.class, bookId);
			em.detach(result);
			return result;
		}

		@Override
		public List list() {
			List result = em.createQuery("SELECT b FROM Book b", Book.class)
					.getResultList();
			for (Book b : result) { em.detach(b); }
			return result;
		}

		@Override
		public int save(Book book) {
			em.getTransaction().begin();
			em.persist(book);
			em.getTransaction().commit();
			em.detach(book);
			return book.getBookId();
		}

		@Override
		public void update(Book book) {
			em.getTransaction().begin();
			em.merge(book);
			em.getTransaction().commit();
			em.detach(book);
		}

		@Override
		public void delete(Book book) {
			em.remove(book);
			em.flush();
		}

	}

This is only a very simple example of JPA, but  if you read more, it’s capable of much more such as mapping entity relations, and implementing optimistic locking using row versioning.

You can view or checkout the sample code here: http://code.google.com/p/gerrytan/source/browse/#svn%2Ftrunk%2Fjpa-simple. In the sample code I wrote few unit test classes using HyperSQL in memory database.

Following are good reference links if you want to find out about: