Selecting Dialog Box Options Using Keyboard on Mac OSX

I’ve been always annoyed with inability of selecting dialog box on Mac using keyboard like you can in Windows:

mac dialog

Thanks to this rather-old-post there’s actually a way to enable dialog box option selection / cycling using keyboard. Go to System Preferences -> Keyboard and select All Controls under Full Keyboard Access at the bottom:

mac keyboard shortcuts

Now there’s one less thing for which you shouldn’t take your fingers off keyboard from.

Tomcat & Apache Reverse Proxy

I have to admit Apache HTTPD has one of the most confusing documentation among other tools out there. Here are my Apache & Tomcat requirements:

  • A domain name mycoolwebsite.com pointing to my hosting server
  • Tomcat running on http://localhost:8080 on my hosting (default)
  • Apache HTTP server running on http://localhost:80 on hosting (default)
  • Request to http://mycoolwebsite.com should be reverse proxied into Tomcat without the end-user noticing the port difference

After 2 hours of reading documentation, trial and error, I managed to get this setup working using following Apache Reverse Proxy and VirtualHost configuration:

<VirtualHost *:80>
   ServerName mycoolwebsite.com
   ProxyPass        / http://localhost:8080/
   ProxyPassReverse / http://localhost:8080/
   ProxyPassReverseCookieDomain localhost mycoolwebsite.com
   ProxyPreserveHost On
</VirtualHost>

Configuration Explained

  1. ProxyPass directive will cause request to http://mycoolwebsite.com/foo/bar (and any other paths) be internally forwarded to http://localhost:8080/foo/bar. Internally here means the user will never know — it will look as if the response came from http://mycoolwebsite.com. Behind the screen (on the server) Apache forwards the request and obtain the response to/from Tomcat. The trailing slash (/) at the end of http://localhost:8080/ is important because without it request to http://mycoolwebsite.com/style.css will be internally translated to http://localhoststyle.css (which is wrong).
  2. ProxyPassReverse directive is useful when Tomcat sends HTTP 3xx redirect response. If Tomcat redirects http://localhost:8080/logout into http://localhost:8080/login, your end user will see http://localhost:8080/login unless you place this directive.
  3. ProxyPassReverseCookieDomain directive will cause the cookie domain be re-written into the intended domain. Without this end-user would see localhost as their cookie domain (which is again wrong).
  4. ProxyPreserveHost directive will cause the domain header be forwarded into Tomcat. Without this Tomcat will see the incoming request coming from localhost. This is handy when you’re planning to serve multiple host name under Tomcat.

You can try this on be adding the above configuration into your httpd.conf file (typically located on /etc/httpd/conf/httpd.conf). Once you’ve edited the config, restart apache using sudo apachectl -k restart command.

Spring MVC + Hibernate + MySQL Quick Start From Scratch

This is a tutorial to build a very simple pizzashop Spring MVC, Hibernate and MySQL application. The main page shows all pizza rows stored on a database table:

03

Technology in Java world moves very fast. Using straight Hibernate might no longer be preferable since Java EE 5 introduces JPA (Java Persistence API) but it’s still good to learn anyway. Spring MVC and Hibernate is one of the most popular Java libraries used out there.

Tools / Environment Required
If you’re just starting fresh and don’t have most of the tools below just install JDK, STS (Springsource Tools Suite) and MySQL server, everything else is bundled within them.

Project Setup and Boilerplate

  1. First, create new Maven project on STS. Skip archetype selection. Pick maven group id, artifact id and select packaging to war.01 02
  2. By default Maven will use JDK 1.5, re-configure it to use 1.6. Add following maven-compiler-plugin section to pom.xml under <pom> element. Ensure the change takes effect by updating maven project settings (right click on project -> Maven -> Update project…).
    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.1</version>
          <configuration>
            <source>1.6</source>
            <target>1.6</target>
          </configuration>
        </plugin>
      </plugins>
    </build>
    
  3. Add Spring, Hibernate, Java EE and MySQL maven dependencies to pom.xml. Place following under <pom> element.
    <properties>
      <spring.version>3.2.3.RELEASE</spring.version>
      <hibernate.version>4.2.2.Final</hibernate.version>
    </properties>
    
    <dependencies>
      <!-- Spring -->
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
      </dependency>
      
      <!-- Hibernate -->
      <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version>
      </dependency>
      
      <!-- Java EE -->
      <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
        <scope>provided</scope>
      </dependency>
      <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
      </dependency>
      
      <!-- Others -->
      <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
      </dependency>
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.25</version>
      </dependency>
      
    </dependencies>
    
  4. Create a web.xml descriptor file with Spring MVC servlet setup on it, place it on src/main/webapp/WEB-INF
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    
      <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
       
      <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
      
    </web-app>
    
  5. Create src/main/webapp/WEB-INF/servlet-context.xml Spring bean config file for dispatcher servlet. We configure few important stuffs in here:
    <?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:mvc="http://www.springframework.org/schema/mvc" xmlns:beans="http://www.springframework.org/schema/beans"
      xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
      xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
    
      <!-- Enable @Controller annotation support -->
      <mvc:annotation-driven />
    
      <!-- Map simple view name such as "test" into /WEB-INF/views/test.jsp -->
      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/" />
        <property name="suffix" value=".jsp" />
      </bean>
      
      <!-- Scan classpath for annotations (eg: @Service, @Repository etc) -->
      <context:component-scan base-package="com.gerrytan.pizzashop"/>
      
      <!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with 
           username root and blank password. Change below if it's not the case -->
      <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/pizzashop"/>
        <property name="username" value="root"/>
        <property name="password" value=""/>
        <property name="validationQuery" value="SELECT 1"/>
      </bean>
      
      <!-- Hibernate Session Factory -->
      <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="packagesToScan">
          <array>
            <value>com.gerrytan.pizzashop</value>
          </array>
        </property>
        <property name="hibernateProperties">
          <value>
            hibernate.dialect=org.hibernate.dialect.MySQLDialect
          </value>
        </property>
      </bean>
      
      <!-- Hibernate Transaction Manager -->
      <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory"/>
      </bean>
      
      <!-- Activates annotation based transaction management -->
      <tx:annotation-driven transaction-manager="transactionManager"/>
    </beans>
    
    


The Business Functionality

  1. Now all the boilerplate code done, we can start coding the business functionality. For this simple app we will have a pizza database table with just id, name and price column. Create the Pizza entity class representing the table
    package com.gerrytan.pizzashop;
    // imports ..
    
    @Entity
    @Table(name = "pizza")
    public class Pizza {
      @Id @GeneratedValue private long id;
      private String name;
      private double price;
      /* getters & setters */
    }
    
  2. Create a DAO class to obtain Pizza entity persisted on database. Note that we won’t create service layer classes for the sake of simplicity (on real-life complex business application adding service layer is a good practice).
    package com.gerrytan.pizzashop;
    // imports..
    
    @Repository
    @SuppressWarnings({"unchecked", "rawtypes"})
    public class PizzaDAO {
      @Autowired private SessionFactory sessionFactory;
      
      /**
       * @Transactional annotation below will trigger Spring Hibernate transaction manager to automatically create
       * a hibernate session. See src/main/webapp/WEB-INF/servlet-context.xml
       */
      @Transactional
      public List<Pizza> findAll() {
        Session session = sessionFactory.getCurrentSession();
        List pizzas = session.createQuery("from Pizza").list();
        return pizzas;
      }
    }
    
  3. Create a Spring MVC controller to handle request from the main page. Note that PizzaDAO reference is injected, and after collection of Pizza entity objects are obtained it’s passed to the view using Model object.
    package com.gerrytan.pizzashop;
    // imports..
    
    @Controller
    @RequestMapping("/")
    public class PizzaController {
      
      @Autowired private PizzaDAO pizzaDAO;
      
      /**
       * This handler method is invoked when
       * http://localhost:8080/pizzashop is requested.
       * The method returns view name "index"
       * which will be resolved into /WEB-INF/index.jsp.
       *  See src/main/webapp/WEB-INF/servlet-context.xml
       */
      @RequestMapping(method = RequestMethod.GET)
      public String list(Model model) {
        List<Pizza> pizzas = pizzaDAO.findAll();
        model.addAttribute("pizzas", pizzas);
        return "index";
      }
    }
    
  4. Add a JSP view to list all the pizza entities passed by the controller
    src/main/webapp/WEB-INF/index.jsp

    <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Pizzashop</title>
    </head>
    <body>
    	<h1>List of All Pizzas</h1>
    	<ul>
    		<c:forEach var="p" items="${pizzas}">
    			<li>${p.id} - ${p.name} - ${p.price}</li>
    		</c:forEach>
    	</ul>
    </body>
    </html>
    
  5. And finally prepare MySQL pizzashop database schema:
    CREATE SCHEMA `pizzashop`;

    And pizza table:

    CREATE  TABLE `pizzashop`.`pizza` (
      `id` BIGINT NOT NULL AUTO_INCREMENT ,
      `name` VARCHAR(45) NULL ,
      `price` DOUBLE NULL ,
      PRIMARY KEY (`id`) );
    

    And insert some data into it

    INSERT INTO `pizzashop`.`pizza` (`id`, `name`, `price`) VALUES ('I', 'Italian', '7.5');
    INSERT INTO `pizzashop`.`pizza` (`id`, `name`, `price`) VALUES ('2', 'Thin Crust', '6');
    INSERT INTO `pizzashop`.`pizza` (`id`, `name`, `price`) VALUES ('3', 'Pepperoni', '6.2');
    

    It is assumed you have MySQL server running on your local machine (localhost) on the default port 3306. The name of the schema is pizzashop and table pizza. Have a look at Spring beans configuration section above to reconfigure this.

Running The Code

  1. The easiest way to run your code is using in-memory Maven Tomcat plugin. It will launch on-the-fly Tomcat server with your code deployed. Make sure your project is selected on the project exploded and setup a maven run configuration on STS. Go to Run -> Run Configurations.. and create a new maven build entry like this:
    maven goal
  2. Click Run and navigate your browser to http://localhost:8080/pizzashop

Download The Source Code

Source code for this demonstration can be obtained using git:

git clone https://bitbucket.org/gerrytan/pizzashop.git -b basic

Congratz!

Well done on making it this far. Hopefully that was a quick and nice introduction to Spring MVC + Hibernate + MySQL and you can see how the tedious database to java class mapping is now simplified. You might have lots of questions in your mind by now — feel free to ask in the comment section below. Following are few official references and community article links you can browse around:

Also checkout my next tutorial about Hibernate One To Many Entity Relationship.

Java EE & Spring Cheatsheet

JSTL 1.2 Core JSP Taglib (aka c tag)

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

JSTL implementation jar has to exist on the classpath, eg add following dependency (in provided scope if container doesn’t provides it)

<dependency>
  <groupId>jstl</groupId>
  <artifactId>jstl</artifactId>
  <version>1.2</version>
</dependency>

See this blog post for more info.

Spring Taglib

  • Spring:
    <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
  • Form:
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

JSTL fmt Taglib

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

web.xml deployment descriptor

  • v2.3
    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      
    </web-app>
    
  • v3.0
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0"
             xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
        
    </web-app>
    

Commons DBCP / MySQL Spring Bean Config

<!-- JDBC Data Source -->
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/hibernatefiddle"/>
  <property name="username" value="root"/>
  <property name="password" value=""/>
  <property name="validationQuery" value="SELECT 1"/>
  <property name="testWhileIdle" value="true"/>
</bean>

Hibernate / MySQL Session Factory & Transaction Manager Spring Bean Config

<!-- Hibernate Session Factory -->
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
  <property name="dataSource" ref="myDataSource"/>
  <property name="packagesToScan">
    <array>
      <value>com.gerrytan.hibernatefiddle</value>
    </array>
  </property>
  <property name="hibernateProperties">
    <value>
      hibernate.dialect=org.hibernate.dialect.MySQLDialect
    </value>
  </property>
</bean>

<!-- Hibernate Transaction Manager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
  <property name="sessionFactory" ref="mySessionFactory"/>
</bean>

Log4j Properties File

# Root logger option
log4j.rootLogger=INFO, stdout

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n

This will print log in following format:

2013-06-26 10:15:35 DEBUG com.gerrytan.hibernatefiddle.StudentDAO:21 - StudentDAO created

To create file logger, limited to 5 file with max size 1000KB:

# Root logger option
log4j.rootLogger=WARN, file
 
# Rolling file appender
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=MyLog.log
log4j.appender.file.MaxFileSize=1000KB
log4j.appender.file.MaxBackupIndex=5
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n

Hibernate Logging

log4j.logger.org.hibernate.SQL=DEBUG
log4j.logger.org.hibernate.engine.transaction=DEBUG

On Hibernate 3 or earlier transaction logger is:

log4j.logger.org.hibernate.transaction=DEBUG

Hibernate 4.2.2 Transactions Logging

I just a hard time trying to enable transactions logging for hibernate. Checked the manual many times and it said the logger name is

org.hibernate.transaction=DEBUG

But not a single logging output is given.

I then dig a bit deeper into the source code. Realized my hibernate version is 4.2.2 (latest doc as of writing this post is 4.2.1) and they seem to have refactored the package name into

org.hibernate.engine.transaction=DEBUG

And yes finally I can see my transactions being logged.

C++ min max Macro When Including Windows API

This is yet another quirks of C++ programming I found (and could be very hard to debug).

When you use Windows API (eg: you have #include <afxwin.h>), it will pull min() and max() macro.

Apparently this will cause confusion for the compiler if you’re including another 3rd party library which expects standard library min() and max(). The error message you get is something like this (how obscure is this?):

1>c:\mongodbsrc\src\mongo\db\../bson/bsonelement.h(630): warning C4003: not enough actual parameters for macro 'max'
1>c:\mongodbsrc\src\mongo\db\../bson/bsonelement.h(630): error C2589: '(' : illegal token on right side of '::'
1>c:\mongodbsrc\src\mongo\db\../bson/bsonelement.h(630): error C2059: syntax error : '::'
1>c:\mongodbsrc\src\mongo\db\../bson/bsonelement.h(630): error C2143: syntax error : missing ';' before '{'

To avoid pulling the macros from Windows API, hash define following:

#define NOMINMAX

Merging Git Conflicts On Github

This article applies to following environments (but conceptually it can be applied to any environment):

  • Github
  • Windows 7

If you’ve been relying on the github GUI, you may get (very) annoyed when the conflict screen appear (Failed to sync this branch due to unmerged files)

gitmerge

This is few (often not so) simple steps to resolve the conflicts:

  1. Click OPEN SHELL, a windows powershell will come up
  2. Start by running git status, this command will help you as you progress resolving the conflict. It also contain pretty clear instruction on how to mark a file resolved, and how to finish conflict resolution
  3. In this examply (luckily) I only have 1 file in conflict hello.txt. Open it using a text editor, and edit the conflict. Conflicts are presented in a unified diff format:
    hello world
    <<<<<<< HEAD
    mary
    =======
    bobby
    >>>>>>> bobby
    the many
    testing
    file
    

    Above example is saying you changed the 2nd line to “mary”, but your colleague changed it to “bobby”. You now have to decide either (or merge both).

  4. For every conflict you resolved, you can tell git so by git add command, eg: git add hello.txt
  5. Once all conflicts are resolved do git rebase –continue command (if you’re in rebase mode — sometime github will use other conflict resolution and will tell you what command to run when completed)