Groovy, Oracle example

Please refer to my previous posts on how to get Oracle XE installed and a demonstration of the HR Schema Sample Data.

The dynamic nature of Groovy with built-in support for Sql really shines on quick scripts like this example:

def printHeader(name, sql){
    println """\nThere are
             ${sql.firstRow("SELECT COUNT(*) TOTAL FROM ${name}".toString()).TOTAL}
             total ${name.toLowerCase()}."""
    println "\n${name}\n${"=".multiply(name.size())}"
}

import groovy.sql.Sql
sql = Sql.newInstance("jdbc:oracle:thin:@127.0.0.1:1521:orcl",
                "hr", "oracle", "oracle.jdbc.pool.OracleDataSource")


printHeader("EMPLOYEES", sql)
sql.eachRow("SELECT FIRST_NAME, LAST_NAME FROM EMPLOYEES") {
            println "${it.FIRST_NAME} ${it.LAST_NAME}"
        }

printHeader("COUNTRIES", sql)
sql.eachRow("SELECT COUNTRY_NAME FROM COUNTRIES") {
    println it.COUNTRY_NAME
}

printHeader("DEPARTMENTS", sql)
sql.eachRow("SELECT DEPARTMENT_NAME FROM DEPARTMENTS") {
    println it.DEPARTMENT_NAME
}

printHeader("REGIONS", sql)
sql.eachRow("SELECT REGION_NAME FROM REGIONS") {
    println it.REGION_NAME
}

Please note that the ojdbc jar is provided in the classpath.

Pay attention on the easiness by which we create the connection doing the needed import on the spot:

import groovy.sql.Sql
sql = Sql.newInstance("jdbc:oracle:thin:@127.0.0.1:1521:orcl",
                "hr", "oracle", "oracle.jdbc.pool.OracleDataSource")

Also the easiness and compactness by which we iterate through the result set via the help of closures and the default it reference is unparalleled in the ecosystem of JVM languages:

sql.eachRow("SELECT FIRST_NAME, LAST_NAME FROM EMPLOYEES") {
            println "${it.FIRST_NAME} ${it.LAST_NAME}"
        }

For the demo purposes I’ve created a function that is creating the printed header output. It is accepting Sql instance on the input parameters which is not advisable but I wanted to demonstrate the powerful GString injection within a String literal:

def printHeader(name, sql){
    println """\nThere are
             ${sql.firstRow("SELECT COUNT(*) TOTAL FROM ${name}".toString()).TOTAL}
             total ${name.toLowerCase()}."""
    println "\n${name}\n${"=".multiply(name.size())}"
}

Please note how we inject the table name on the SQL literal and also how we are populating the underlying of the table name header using the size of the table name string. Moreover by surrounding the literal with triple double-quotes we can expand across multiple lines without needing implicit/explicit concatenation.

The above code yields output:

There are 107 total employees.


EMPLOYEES
=========
Ellen Abel
Sundar Ande
Mozhe Atkinson
David Austin
Hermann Baer
Shelli Baida
Amit Banda
Elizabeth Bates
Sarah Bell
David Bernstein
Laura Bissot
Harrison Bloom
Alexis Bull
Anthony Cabrio
Gerald Cambrault
...

There are 25 total countries.

COUNTRIES
=========
Argentina
Australia
Belgium
Brazil
Canada
Switzerland
China
Germany
Denmark
Egypt
France
HongKong
Israel
India
Italy
Japan
Kuwait
Mexico
Nigeria
Netherlands
Singapore
United Kingdom
United States of America
Zambia
Zimbabwe

There are 27 total departments.

DEPARTMENTS
===========
Administration
Marketing
Purchasing
Human Resources
Shipping
IT
Public Relations
Sales
Executive
Finance
Accounting
Treasury
Corporate Tax
Control And Credit
Shareholder Services
Benefits
Manufacturing
Construction
Contracting
Operations
IT Support
NOC
IT Helpdesk
Government Sales
Retail Sales
Recruiting
Payroll

There are 4 total regions.

REGIONS
=======
Europe
Americas
Asia
Middle East and Africa

Spring, JdbcTemplate, Oracle example

This is a demonstration of how Spring and Oracle are playing happily together via JdbcTemplate.

Prerequisites:

Let’s start from the end: this is how the JUnit 4 test case looks like for the DAO of our domain object for all its CRUD operations armored with rollback functionality so our database data are not being altered after our transactional operations. Notice the use of matchers and the spring-context-enabling annotation of the test class:

package com.dimitrisli.springJdbcOracle.dao.impl;

import com.dimitrisli.springJdbcOracle.dao.LocationDao;
import com.dimitrisli.springJdbcOracle.model.Location;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
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 javax.inject.Inject;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/spring/context/applicationContext.xml")
@TransactionConfiguration(transactionManager = "jdbcTransactionManager", defaultRollback = true)
@Transactional
public class LocationDaoTest {

    @Inject private LocationDao locationDao;

    @Test
    public void testSelectAllLocations(){
    List<Location> locations = locationDao.getLocations();
    assertThat(locations.size(), is(23));
    }

    @Test
    public void testSelectOneLocation(){
      Location location = locationDao.getLocation(1000L);
      assertNotNull("test entry not found", location);
    }

    @Test
    public void testDeleteLocation(){
        assertNotNull("entry for test should be there", locationDao.getLocation(1000L));
        locationDao.deleteLocation(1000L);
        assertNull("entry wasn't successfully deleted", locationDao.getLocation(1000L));
    }

    @Test
    public void testInsertLocation(){
        Location location = new Location(1000L,"test","11111","athens","athens","IT");
        int sizeBeforeInsert = locationDao.getLocations().size();
        locationDao.createLocation(location);
        assertThat(locationDao.getLocations().size(),is(sizeBeforeInsert + 1));
    }

    @Test
    public void testUpdateLocation(){
        Location newLocation = new Location(1000L,"test","11111","athens","athens","IT");
        locationDao.updateLocation(newLocation);
        Location changedLocation = locationDao.getLocation(1000L);
        assertThat(changedLocation.getStreetAddress(), is("test"));
    }

}

The POM looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>SpringJdbcOracle</groupId>
    <artifactId>SpringJdbcOracle</artifactId>
    <version>1.0</version>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>

            <!--Logging related plugin
                this plugin breaks the build if non-wanted logging frameworks are spotted in the classpath
            -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <version>1.0.1</version>
                <executions>
                    <execution>
                        <id>enforce-versions</id>
                        <goals>
                            <goal>enforce</goal>
                        </goals>
                        <configuration>
                            <rules>
                                <bannedDependencies>
                                    <excludes>
                                        <exclude>commons-logging:commons-logging</exclude>
                                        <exclude>log4j:log4j</exclude>
                                    </excludes>
                                </bannedDependencies>
                            </rules>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!--Spring related dependencies -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>


        <!--Oracle jdbc driver-->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>

        <!-- DB Connection Pool -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>

        <!--Logging related dependencies
            Further info: http://www.slf4j.org/faq.html#excludingJCL and

http://blog.frankel.ch/configuring-maven-to-use-slf4j

        -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <!--scope should be runtime but applied at compile time
                to get autocompletion visibility at logback.xml-->
            <!--scope>runtime</scope-->
            <version>0.9.24</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.2</version>
        </dependency>

        <!-- JUnit 4 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>

        <!-- Misc -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
            <scope>runtime</scope>
        </dependency>


    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>3.1.2.RELEASE</spring.version>
     </properties>


</project>

Notes:
- Note how we explicitly piping any commons logging or log4j logging through our logback slf4j wrapper
- Notice how we are declaring our Oracle driver dependency given that it’s already installed in our local Maven repo (see prerequisites section)

The applicationContext:

<?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:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <import resource="classpath*:spring/database/database.xml"/>
    <context:component-scan base-package="com.dimitrisli.springJdbcOracle" />
</beans>

The imported database context above is:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="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.xsd">

    <bean  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
           p:location="properties/database.properties" />

    <bean  id="dataSource"
           class="org.apache.commons.dbcp.BasicDataSource"
           destroy-method="close"
           p:driverClassName="${jdbc.driverClassName}"
           p:url="${jdbc.url}"
           p:username="${jdbc.username}"
           p:password="${jdbc.password}" />

    <bean  class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate"
           c:dataSource-ref="dataSource"  />

    <bean  id="jdbcTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
            p:dataSource-ref="dataSource"/>
    <tx:annotation-driven transaction-manager="jdbcTransactionManager"/>

</beans>

Notes:

- We are using DBCP for our DB connection pool datasource
- We are using the parameter namespace to save on some attribute injection open-close xml characters
- We are explicitly stating NamedParameterJdbcTemplate as our jdbcTemplate and inject it with the needed datasource so we can have it available for injection conveniently in our DAOs.

The domain POJO object we are about to play with is the Location object that corresponds to the Locations table on the Oracle HR schema:


package com.dimitrisli.springJdbcOracle.model;

public class Location {

    private Long locationId;
    private String streetAddress;
    private String postalCode;
    private String city;
    private String stateProvince;
    private String countryId;

    public Location(Long locationId, String streetAddress, String postalCode, String city, String stateProvince, String countryId) {
        this.locationId = locationId;
        this.streetAddress = streetAddress;
        this.postalCode = postalCode;
        this.city = city;
        this.stateProvince = stateProvince;
        this.countryId = countryId;
    }

//getters, hashcode(), equals(), toString() ignored for brevity

The RowMapper that will provide Location objects having resultSets coming from the DB. It’s a factory method (although not static but stateless by our design) used internally from Spring per DB line result returned:

package com.dimitrisli.springJdbcOracle.orm;

import com.dimitrisli.springJdbcOracle.model.Location;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import java.sql.ResultSet;
import java.sql.SQLException;

@Component
public class LocationRowMapper implements RowMapper<Location> {

    @Override
    public Location mapRow(ResultSet rs, int rowNum) throws SQLException {
        return  new Location(rs.getLong("LOCATION_ID"),
                             rs.getString("STREET_ADDRESS"),
                             rs.getString("POSTAL_CODE"),
                             rs.getString("CITY"),
                             rs.getString("STATE_PROVINCE"),
                             rs.getString("COUNTRY_ID"));
    }
}

Here’s the DAO interface responsible for the CRUD operations:

package com.dimitrisli.springJdbcOracle.dao;

import com.dimitrisli.springJdbcOracle.model.Location;

import java.util.List;

public interface LocationDao {

    public void createLocation(Location location);
    public List<Location> getLocations();
    public Location getLocation(Long locationId);
    public void updateLocation(Location location);
    public void deleteLocation(Long locationId);

}

and its implementation looks like this:


package com.dimitrisli.springJdbcOracle.dao.impl;

import com.dimitrisli.springJdbcOracle.dao.LocationDao;
import com.dimitrisli.springJdbcOracle.model.Location;
import com.dimitrisli.springJdbcOracle.orm.LocationRowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Repository;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.List;

@Repository("locationDao")
public class LocationDaoImpl implements LocationDao {

    private static final String CREATE_SQL = "INSERT INTO LOCATIONS( LOCATION_ID, STREET_ADDRESS, POSTAL_CODE, CITY, " +
                                             "STATE_PROVINCE, COUNTRY_ID) " +
                                             "VALUES (LOCATIONS_SEQ.NEXTVAL, :streetAddress, :postalCode, :city, " +
                                             ":stateProvince, :countryId)";

    private static final String GET_ALL_SQL = "SELECT LOCATION_ID, STREET_ADDRESS, POSTAL_CODE, CITY, STATE_PROVINCE, COUNTRY_ID " +
                                              "FROM LOCATIONS";

    private static final String GET_SQL = "SELECT LOCATION_ID, STREET_ADDRESS, POSTAL_CODE, CITY, STATE_PROVINCE, COUNTRY_ID " +
                                          "FROM LOCATIONS WHERE LOCATION_ID = :locationId";

    private static final String DELETE_SQL = "DELETE LOCATIONS WHERE LOCATION_ID = :locationId";

    private static final String UPDATE_SQL = "UPDATE LOCATIONS SET STREET_ADDRESS = :streetAddress, POSTAL_CODE=:postalCode, " +
                                            "CITY = :city, STATE_PROVINCE = :stateProvince, COUNTRY_ID = :countryId " +
                                            "WHERE LOCATION_ID = :locationId";

    @Inject private NamedParameterJdbcOperations jdbcTemplate;
    @Inject private LocationRowMapper locationRowMapper;

    @Override
    public void createLocation(Location location) {
        SqlParameterSource params = new MapSqlParameterSource()
                .addValue("streetAddress", location.getStreetAddress())
                .addValue("postalCode", location.getPostalCode())
                .addValue("city", location.getCity())
                .addValue("stateProvince", location.getStateProvince())
                .addValue("countryId", location.getCountryId());
        jdbcTemplate.update(CREATE_SQL, params);
    }

    @Override
    public List<Location> getLocations() {
        return jdbcTemplate.query(GET_ALL_SQL, new HashMap<String, Object>(), locationRowMapper);
    }

    @Override
    public Location getLocation(Long locationId) {
        SqlParameterSource params = new MapSqlParameterSource()
                .addValue("locationId", locationId);
        List<Location> locations = jdbcTemplate.query(GET_SQL, params, locationRowMapper);
        return locations.isEmpty()?null:locations.get(0);
    }

    @Override
    public void updateLocation(Location location) {
        SqlParameterSource params = new MapSqlParameterSource()
                .addValue("locationId", location.getLocationId())
                .addValue("streetAddress", location.getStreetAddress())
                .addValue("postalCode", location.getPostalCode())
                .addValue("city", location.getCity())
                .addValue("stateProvince", location.getStateProvince())
                .addValue("countryId", location.getCountryId());
        jdbcTemplate.update(UPDATE_SQL, params);
    }

    @Override
    public void deleteLocation(Long locationId) {
        jdbcTemplate.update(DELETE_SQL, new MapSqlParameterSource("locationId",locationId));
    }
}

Notes:
- Notice how we inject the JdbcTemplate and not fetching it from this class directly
- Notice how we inject the RowMapper and we don’t anonymous-class-it from this class directly
- The CRUD operations are setup parameterized in the top of the file as private static finals
- In all the CRUD operations we are using either jdbcTemplate.update() or jdbcTemplate.query() methods

Here’s the Github repo of the project

Oracle XE JDBC Example with Sample Data

This quick tutorial demonstrates basic JDBC connectivity to the HR database which is already setup in Oracle XE and is part of the Sample Data. This database is small, filled with data, easy to grasp and ideal to quickly put some prototype code together without worrying about DDLs and other initialisation scripts.

Please first refer to my previous post on how to get Oracle XE installed on any version of Mac OS that it also applies for any OS given that the correct version of VirtualBox gets installed.

Given that we have Oracle XE now installed and communication via TCP port 1521 is allowed we are good to go.

By using IntelliJ datasource capabilities we can quickly test connectivity to the Oracle’s Sample HR database (username: hr, password: oracle (if the DB is installed via the VM methodology described) otherwise password: hr (if the DB is natively installed) ):

Data Source Properties

while testing the connection yields success:

IntelliJ IDEA-1

.HR.EMPLOYEES - ScalaProj - [~_Dimitris_ScalaProjects_ScalaProj]

and for completeness here’s the UML of the sample database as it appears from IntelliJ:

DATABASE_1f59cfcd-b0bc-4ab3-a0ca-fd6402de2165.schema_HR - ScalaProj - [~_Dimitris_ScalaProjects_ScalaProj]

and also how it appears from Oracle Modeler:

Oracle Developer Days [Running]

Oracle Developer Days [Running]-1

Maven install ojdbc6

I really wished the Oracle driver jar was part of any (legal) publicly available Maven repo, but it’s not. So we’ll have to take matters on our hands and install it in our local repo once and for all so we can effortlessly thereafter summon it via our pom file:

       <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.3</version>
        </dependency>

Steps:

  • Download the jdbc6.jar from the Oracle website. I tried to automate this step via a Groovy script but this pesky agreement radio-button gets in the way (which is there for a reason to be fair)
  • Supposing mvn is already setup in your path:
  • mvn install:install-file -Dfile=ojdbc6.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.3 -Dpackaging=jar -DgeneratePom=true
    

How to install Oracle Database on Mac OS (Any Version)

Introduction

Installing Oracle DB on any Mac OS version is not an easy task. Official support was dropped from 10g onwards around the early days of Mac OS X and since then there has been endless questions online of how to go about later versions like Leopard (10.5), Snow Leopard (10.6), Lion (10.7) or Mountain Lion (10.8).

I have yet to find a consistent resource online of how to natively install the database and I have also tried my hands on binaries compilation and package transfers along all the previous versions with various, inconsistent results. I have to admit that this long-winded process gets too complicated for my taste and patience.

The people at Oracle have acknowledged this problem and have provided a neat solution abstracting all the complicated noise, packing up all the required tools and needed configurations in a single image file readily to be hosted as a VM in VirtualBox.

This is old news and although VirtualBox is well documented I haven’t again found a single resource that is describing the process from top to bottom for my setup which is a Macbook Pro using WiFi therefore this detailed tutorial.

*General Note: As the creators suggest Oracle XE should be used for testing purposes only. Also the majority of passwords on the VM have been setup by default to oracle and should be changed for obvious security reasons.

Step 1: Getting VirtualBox

This is as simple as any other installation on a Mac. All we have to do is grab our x86 version (assuming an Intel CPU) for Mac from the official download page.

Step 2: Getting the VM file

This is the download page and the download instructions are clear. The ova VM file is big ~4G so better start the download process on a browser that has an integrated download manager like Firefox if you have a slow connection or are frequently experiencing dropped connections.

Apparently this VM has been initially created for a developer’s workshop but gets frequently updated with the latest and greatest of Oracle Client, Oracle SQL Developer and other tools. Various walkthroughs and other interesting tutorials are loaded-up on the VM awaiting to be discovered but all we care about is the Oracle 11gr2 DB which will be by default up and running when the VM is loaded into memory.

Step 3: Installing the Guest VM

Our host OS is apparently Mac OS and the guest VM is Oracle Linux 5 which is a branch off Red Hat Linux.

From the VirtualBox Menu we select File > Import Appliance

Then we make it point to the VM file we’ve just downloaded:

Import Virtual Applicance-2

VirtualBox-1

Import Virtual Applicance-3

After the import gets completed we are ready to start the VM:

Oracle VM VirtualBox Manager

Step 4: Starting the VM

Starting up the VM is as easy as inserting oracle/oracle when we are prompted for username/password:

Skitch

When the OS boots up we are ready to go:

Skitch-1

Step 5: Making Oracle visible from Mac OS

That’s where things start getting tricky. By default VirtualBox > Devices > Network Adapters is attached to an internal NAT that should hopefully give you access to Internet.

Oracle Developer Days - Network

My setup is a MacBook Pro that is getting Internet via WiFi therefore I’ve tried to get the Bridged Adapter via WiFi to work that is initiating a more direct connection between the Host and Guest VM but to no avail. I’ve tried several things suggested out there such as reducting the MTU to 1496 or downgrading to IPv4 but without luck.

The solution lies in the Port Forwarding option under the Network Adapters picture above:

VirtualBox VM

Here we define external requests coming from localhost (127.0.0.1) to the standard Oracle communication default 1521 TCP port to be forwarded to our Guest VM with IP address 10.0.2.15 on the same port. The IP of the Guest VM is communicated by just opening a terminal window:

Oracle Developer Days [Running]

Step 6: Testing external connectivity

From Mac OS we can test that we can connect to localhost on port 1521:

Katie — telnet — 80×43

Also by using IntelliJ datasource capabilities we can successfully connect to the Oracle’s Sample HR database (username: hr, password: oracle):

Data Source Properties

while testing the connection yields success:

IntelliJ IDEA-1

Conclusion

That’s a quick, clean and bulletproof way of having the most recent Oracle DB running on a Guest VM not only on Mac OS but on any OS.

Scala, Stripes simple example

Here’s the sample Stripes application using Scala.

The skeletal implementation of Stripes ActionBean for the purposes of our project holding the context:

package com.dimitrisli.scalastripeswebapp.controller

import net.sourceforge.stripes.action.{ActionBeanContext, ActionBean}
import reflect.BeanProperty


class BaseActionBean extends ActionBean {

  @BeanProperty var context: ActionBeanContext = _

}

The calculator represented as a Stripe action bean:

package com.dimitrisli.scalastripeswebapp.controller

import net.sourceforge.stripes.action._
import net.sourceforge.stripes.validation.{SimpleError, ValidationErrors, ValidationMethod, Validate}
import reflect.BeanProperty


class CalculatorActionBean extends BaseActionBean {

  @BeanProperty @Validate(required=true) var numberOne: Double = _
  @BeanProperty @Validate(required=true) var numberTwo: Double = _
  @BeanProperty var result: Double = _

  @DefaultHandler
  def addition: Resolution = {
    result = getNumberOne + getNumberTwo
    new ForwardResolution("/index.jsp");
  }

  def division: Resolution = {
    result = getNumberOne / getNumberTwo
    new ForwardResolution("/index.jsp");
  }

  @ValidationMethod(on=Array("division"))
  def avoidDevideByZero(errors: ValidationErrors): Unit =
    if (getNumberTwo == 0)
      errors.add("numberTwo", new SimpleError("Dividing by zero is not allowed."))
}

Our view represented by a JSP will be excluded due to formatting issues in WordPress (look below for the Github repository).

The web.xml setting up the Stripe’s dispatcher servlet, filter and all the necessary mappings will also not be presented due to the same xml formatting issues (look below for the Github repository).

This project’s code can be found in this Github repository

Install Java 6,7,8 on Mac OS X

Here’s a quick guide to have Java versions 6,7,8 installed on Mac OS X above and beyond.

Java 6

Java 6 is the last supported version provided by Apple. Therefore we’ll follow the Apple way to install the JDK although Java 1.6 can be branched out from Oracle or the OpenJDK project.

Successful installation will place Java 6 under /Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/. Following that you can mark JAVA_HOME or point your IDE towards /Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Home/. Also to browse the JDK under an IDE point your editor to the JDK sources found in /Library/Java/JavaVirtualMachines/1.6.0_37-b06-434.jdk/Contents/Home/src.jar

Java 7

We need to go out in the wild to get JDK 7 installed on Mac OS X since mother-Apple doesn’t support it. We can download it either from Oracle or OpenJDK:

Successful installation will place Java 7 under /Library/Java/JavaVirtualMachines/jdk1.7.0_07.jdk/. Following that you can mark JAVA_HOME or point your IDE towards /Library/Java/JavaVirtualMachines/jdk1.7.0_07.jdk/Contents/Home/. Also to browse the JDK under an IDE point your editor to the JDK sources found in /Library/Java/JavaVirtualMachines/jdk1.7.0_07.jdk/Contents/Home/src.jar

Java 8

We can get a copy of the latest snapshot of JDK 8 to play around with the lambda expressions (natively supported on IntelliJ IDEA) if you haven’t tried already closures in Groovy, Scala or just Predicates/Functions in Google Guava from this download resource

Successful installation will place Java 8 under /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/. Following that you can mark JAVA_HOME or point your IDE towards /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/. Also to browse the JDK under an IDE point your editor to the JDK sources found in /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/src.jar

Groovy, Scala closures demonstration

This is a quick demo of closures usage for Groovy and Scala side-by-side.

Let’s get an easy study case where we are trying to identify whether a string contains unique characters. Starting with Java we would have:

Java

public class StringAllUniqueChars {

    public static boolean hasStringAllUniqueChars(String str){

        //cache data structure
        final HashSet<Character> stackConfinedCache = new HashSet<Character>();
        //imperative iteration
        for(Character c : str.toCharArray()){
            if(stackConfinedCache.remove(c))
                //fail fast
                return false;
            else
                stackConfinedCache.add(c);
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println("hello\t" + StringAllUniqueChars.hasStringAllUniqueChars("hello"));
        System.out.println("helo\t" + StringAllUniqueChars.hasStringAllUniqueChars("helo"));
    }
}

Keypoints:

  • We create a data structure to store the findings along the way and fail fast in case of the first dup char found
  • We iterate over the chars of the string using a for loop

Groovy

def hasStringAllUniqueChars(str){

    str.collect {         //in a collection
            str.count(it)    //the occurrences of each char
        }
        .findAll {
            it>1    //filter those with more than one occurrences
        }
        .size()==0  //make sure they don't exist
}

def hasStringAllUniqueChars2(str){
    !   //if we don't
    str.any{       //find any
        str.count(it)>1    //character occurrence in string more than once
    }
}

println "hello\t" + hasStringAllUniqueChars2("hello")
println "hello\t" + hasStringAllUniqueChars("helo")

Keypoints:

  • We are running it in a form of Groovy script
  • We are making use of the default it reference while being on a closure
  • In the first implementation we are first transforming the string characters into a collection of corresponding character sizes. Then we are filtering only duplicate characters and finally we are taking the decision based on whether we have any dups across all chars.
  • In the second implementation we are taking a shortcut using Groovy’s any method hand-picking in its closure only dup characters

Scala

object StringAllUniqueChars {

  def hasStringAllUniqueChars(str: String) =

    !str.exists{  //if we don't find any case where
      c =>    //each character's
        str.count(_==c)>1       //count in the string is greater than 1
    }

  def main(args: Array[String]){
    println("hello\t"+hasStringAllUniqueChars("hello"))
    println("helo\t"+hasStringAllUniqueChars("helo"))
  }

}

Keypoints:

  • We are using an Object since we want to host our main method somewhere. It’s Scala’s way to address static and normally the so-called companion object is grouping all the static content of its corresponding class.
  • We are employing closures in a similar way as the second Groovy implementation using Groovy’s exists and count methods

For a matter of completeness this is how Scala, Groovy and Java are co-existing happily together during compile/run time under the Maven umbrella:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ScalaGroovyClosures</groupId>
    <artifactId>ScalaGroovyClosures</artifactId>
    <version>1.0</version>

    <build>
        <plugins>
            <!--java compiler-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>

            <!--scala compiler-->
            <plugin>
                <groupId>org.scala-tools</groupId>
                <artifactId>maven-scala-plugin</artifactId>
                <version>2.15.2</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!--groovy compiler-->
            <plugin>
                <groupId>org.codehaus.groovy.maven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <version>1.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>testCompile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.groovy.maven.runtime</groupId>
            <artifactId>gmaven-runtime-1.6</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

Java 7 in Maven Project

If you have both jdk6 and jdk7 installed and you would want to interchange between the two compilers in a maven project, this can be easily done by the maven-compiler-plugin and its source and target parameters.

Assuming that we have created a JAVA_7_HOME environment variable we can point the maven-compiler-plugin to the jdk7 compiler as follows:

  		<plugin>
  			<groupId>org.apache.maven.plugins</groupId>
  			<artifactId>maven-compiler-plugin</artifactId>
  			<version>2.3.2</version>
  			<configuration>
  				<source>1.7</source>
  				<target>1.7</target>
  				<encoding>${project.build.sourceEncoding}</encoding>			
  				<executable>${env.JAVA_7_HOME}</executable>
  			</configuration>
  		</plugin>

I have also created a 2-module Maven project one for each jdk that you can find in this Github repository.