You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fineract.apache.org by ik...@apache.org on 2018/11/20 11:57:46 UTC

[fineract-cn-postgresql] branch develop created (now 3d72340)

This is an automated email from the ASF dual-hosted git repository.

ikamga pushed a change to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-postgresql.git.


      at 3d72340  Initial commit for fineract-cn-postgresql

This branch includes the following new commits:

     new 3d72340  Initial commit for fineract-cn-postgresql

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[fineract-cn-postgresql] 01/01: Initial commit for fineract-cn-postgresql

Posted by ik...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ikamga pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-postgresql.git

commit 3d72340c322176dd1b2f7201364396c1ffd29a0c
Author: Isaac Kamga <u2...@gmail.com>
AuthorDate: Thu Nov 15 02:17:42 2018 +0100

    Initial commit for fineract-cn-postgresql
---
 .gitignore                                         |  15 ++
 HEADER                                             |  16 ++
 NOTICE.txt                                         |   5 +
 README.md                                          |  38 +++++
 build.gradle                                       | 105 +++++++++++++
 gradle/wrapper/gradle-wrapper.jar                  | Bin 0 -> 54212 bytes
 gradle/wrapper/gradle-wrapper.properties           |   6 +
 gradlew                                            | 172 +++++++++++++++++++++
 gradlew.bat                                        |  84 ++++++++++
 settings.gradle                                    |  18 +++
 .../cn/postgresql/config/EnablePostgreSQL.java     |  38 +++++
 .../postgresql/config/MetaDataSourceWrapper.java   |  36 +++++
 .../config/PostgreSQLJavaConfiguration.java        | 137 ++++++++++++++++
 .../PostgreSQLJavaConfigurationImportSelector.java |  50 ++++++
 .../PostgreSQLTenantBasedJavaConfiguration.java    |  45 ++++++
 .../PostgreSQLTenantFreeJavaConfiguration.java     |  37 +++++
 .../domain/ContextAwareRoutingDataSource.java      | 119 ++++++++++++++
 .../cn/postgresql/domain/FlywayFactoryBean.java    |  44 ++++++
 .../fineract/cn/postgresql/domain/Tenant.java      |  79 ++++++++++
 .../cn/postgresql/util/JdbcUrlBuilder.java         |  99 ++++++++++++
 .../cn/postgresql/util/LocalDateConverter.java     |  50 ++++++
 .../cn/postgresql/util/LocalDateTimeConverter.java |  52 +++++++
 .../cn/postgresql/util/PostgreSQLConstants.java    |  50 ++++++
 .../cn/postgresql/util/JdbcUrlBuilderTest.java     | 108 +++++++++++++
 .../cn/postgresql/util/LocalDateConverterTest.java |  45 ++++++
 travis.yml                                         |  22 +++
 26 files changed, 1470 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5a0e819
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+.gradle
+.idea
+build/
+target/
+out/
+
+# Ignore Gradle GUI config
+gradle-app.setting
+
+# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
+!gradle-wrapper.jar
+
+*.iml
+
+*.log
\ No newline at end of file
diff --git a/HEADER b/HEADER
new file mode 100644
index 0000000..60b675e
--- /dev/null
+++ b/HEADER
@@ -0,0 +1,16 @@
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
diff --git a/NOTICE.txt b/NOTICE.txt
new file mode 100644
index 0000000..447871d
--- /dev/null
+++ b/NOTICE.txt
@@ -0,0 +1,5 @@
+Apache Fineract CN PostgreSQL
+Copyright [2017-2018] The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1692ac0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,38 @@
+# Apache Fineract CN PostgreSQL
+
+## Abstract
+Apache Fineract CN is an application framework for digital financial services, a system to support nationwide and cross-national financial transactions and help to level and speed the creation of an inclusive, interconnected digital economy for every nation in the world.
+
+## Prerequisites
+### Runtime
+Install Java 8 as described at https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html.
+
+### Installation
+Install PostgreSQL as described at 
+https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-16-04.
+
+After installation you need to create the meta database:
+
+    sudo -i -u postgres psql
+    CREATE DATABASE system_console;
+    
+## Multi-tenancy
+Multi-tenancy is reached by providing separate data storage on a per tenant basis.
+
+For every tenant a new database instance is created internally. A tenant aware component provides transparent access to these resources.
+
+## Versioning
+The version numbers follow the [Semantic Versioning](http://semver.org/) scheme.
+
+In addition to MAJOR.MINOR.PATCH the following postfixes are used to indicate the development state.
+
+* BUILD-SNAPSHOT - A release currently in development. 
+* RELEASE - _General availability_ indicates that this release is the best available version and is recommended for all usage.
+
+The versioning layout is {MAJOR}.{MINOR}.{PATCH}-{INDICATOR}[.{PATCH}]. Only milestones and release candidates can  have patch versions. Some examples:
+
+1.2.3-BUILD-SNAPSHOT  
+1.3.5-RELEASE
+
+## License
+See [LICENSE](LICENSE) file.
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..ac19102
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+buildscript {
+    repositories {
+        jcenter()
+    }
+}
+
+plugins {
+    id 'com.github.hierynomus.license' version '0.13.1'
+    id("org.nosphere.apache.rat") version "0.3.1"
+}
+
+group 'org.apache.fineract.cn'
+version '0.1.0-BUILD-SNAPSHOT'
+
+ext.versions = [
+        springcontext        : '4.3.3.RELEASE',
+        springboot           : '1.4.1.RELEASE',
+        findbugs             : '3.0.1',
+        frameworklang        : '0.1.0-BUILD-SNAPSHOT'
+]
+
+apply plugin: 'java'
+apply plugin: 'idea'
+apply plugin: 'maven'
+apply plugin: 'maven-publish'
+apply plugin: 'license'
+
+tasks.withType(JavaCompile) {
+    sourceCompatibility = JavaVersion.VERSION_1_8
+    targetCompatibility = JavaVersion.VERSION_1_8
+}
+
+repositories {
+    jcenter()
+    mavenLocal()
+}
+
+dependencies {
+    compile(
+            [group: 'org.springframework', name: 'spring-context', version: versions.springcontext],
+            [group: 'com.google.code.findbugs', name: 'jsr305', version: versions.findbugs],
+            [group: 'org.apache.fineract.cn', name: 'lang', version: versions.frameworklang],
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: versions.springboot],
+            [group: 'com.jolbox', name: 'bonecp', version: '0.8.0.RELEASE'],
+            [group: 'org.flywaydb', name: 'flyway-core', version: '4.0.1'],
+            [group: 'org.postgresql', name: 'postgresql', version: '42.2.5'],
+            [group: 'org.apache.openjpa', name: 'openjpa', version: '3.0.0']
+    )
+    testCompile(
+            [group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: versions.springboot]
+    )
+}
+
+jar {
+    from sourceSets.main.allSource
+}
+
+publishing {
+    publications {
+        postgresqlPublication(MavenPublication) {
+            from components.java
+            groupId project.group
+            artifactId project.name
+            version project.version
+        }
+    }
+}
+
+license {
+    header rootProject.file('HEADER')
+    strictCheck true
+    mapping {
+        java = 'SLASHSTAR_STYLE'
+    }
+}
+
+rat {
+    // List of exclude directives, defaults to ['**/.gradle/**']
+    excludes = [
+            ".idea/**",
+            ".gradle/**",
+            "gradle/**",
+            "build/**",
+            "gradlew",
+            "gradlew.bat",
+            "README.md"
+    ]
+}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..a84e6fd
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..ab59e12
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue Mar 14 10:20:00 CET 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..4453cce
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save ( ) {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..e95643d
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..cea748d
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,18 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+rootProject.name = 'postgresql'
\ No newline at end of file
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/config/EnablePostgreSQL.java b/src/main/java/org/apache/fineract/cn/postgresql/config/EnablePostgreSQL.java
new file mode 100644
index 0000000..b9f5de5
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/config/EnablePostgreSQL.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.config;
+
+import org.springframework.context.annotation.Import;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@SuppressWarnings({"WeakerAccess", "unused"})
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+@Import({PostgreSQLJavaConfigurationImportSelector.class})
+public @interface EnablePostgreSQL {
+  boolean forTenantContext() default true;
+}
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/config/MetaDataSourceWrapper.java b/src/main/java/org/apache/fineract/cn/postgresql/config/MetaDataSourceWrapper.java
new file mode 100644
index 0000000..9c8752a
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/config/MetaDataSourceWrapper.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.config;
+
+import com.jolbox.bonecp.BoneCPDataSource;
+
+/**
+ * @author Isaac Kamga
+ */
+public class MetaDataSourceWrapper {
+  private final BoneCPDataSource metaDataSource;
+
+  public MetaDataSourceWrapper(final BoneCPDataSource metaDataSource) {
+    this.metaDataSource = metaDataSource;
+  }
+
+  BoneCPDataSource getMetaDataSource() {
+    return metaDataSource;
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLJavaConfiguration.java b/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLJavaConfiguration.java
new file mode 100644
index 0000000..9e114dd
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLJavaConfiguration.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.config;
+
+import com.jolbox.bonecp.BoneCPDataSource;
+import org.apache.fineract.cn.postgresql.domain.FlywayFactoryBean;
+import org.apache.fineract.cn.postgresql.util.JdbcUrlBuilder;
+import org.apache.fineract.cn.lang.ApplicationName;
+import org.apache.fineract.cn.lang.config.EnableApplicationName;
+import org.apache.fineract.cn.postgresql.util.PostgreSQLConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
+import org.springframework.orm.jpa.JpaTransactionManager;
+import org.springframework.orm.jpa.JpaVendorAdapter;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+import org.springframework.orm.jpa.vendor.OpenJpaVendorAdapter;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.persistence.EntityManagerFactory;
+import javax.sql.DataSource;
+import java.util.Properties;
+
+@SuppressWarnings("WeakerAccess")
+@Configuration
+@ConditionalOnProperty(prefix = "postgresql", name = "enabled", matchIfMissing = true)
+@EnableTransactionManagement
+@EnableApplicationName
+public class PostgreSQLJavaConfiguration {
+
+  private final Environment env;
+
+  @Autowired
+  public PostgreSQLJavaConfiguration(final Environment env) {
+    super();
+    this.env = env;
+  }
+
+  @Bean(name = PostgreSQLConstants.LOGGER_NAME)
+  public Logger logger() {
+    return LoggerFactory.getLogger(PostgreSQLConstants.LOGGER_NAME);
+  }
+
+  @Bean
+  public LocalContainerEntityManagerFactoryBean entityManagerFactory(final DataSource dataSource) {
+    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
+    em.setPersistenceUnitName("metaPU");
+    em.setDataSource(dataSource);
+    em.setPackagesToScan("org.apache.fineract.cn.**.repository");
+
+    final JpaVendorAdapter vendorAdapter = new OpenJpaVendorAdapter();
+    em.setJpaVendorAdapter(vendorAdapter);
+    em.setJpaProperties(additionalProperties());
+
+    return em;
+  }
+
+  @Bean
+  public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
+    final JpaTransactionManager transactionManager = new JpaTransactionManager();
+    transactionManager.setEntityManagerFactory(emf);
+    return transactionManager;
+  }
+
+  @Bean
+  public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
+    return new PersistenceExceptionTranslationPostProcessor();
+  }
+
+  @Bean
+  public FlywayFactoryBean flywayFactoryBean(final ApplicationName applicationName) {
+    return new FlywayFactoryBean(applicationName);
+  }
+
+  @Bean
+  public MetaDataSourceWrapper metaDataSourceWrapper() {
+
+    final BoneCPDataSource boneCPDataSource = new BoneCPDataSource();
+    boneCPDataSource.setDriverClass(
+            this.env.getProperty(PostgreSQLConstants.POSTGRESQL_DRIVER_CLASS_PROP, PostgreSQLConstants.POSTGRESQL_DRIVER_CLASS_DEFAULT));
+    boneCPDataSource.setJdbcUrl(JdbcUrlBuilder
+            .create(JdbcUrlBuilder.DatabaseType.POSTGRESQL)
+            .host(this.env.getProperty(PostgreSQLConstants.POSTGRESQL_HOST_PROP, PostgreSQLConstants.POSTGRESQL_HOST_DEFAULT))
+            .port(this.env.getProperty(PostgreSQLConstants.POSTGRESQL_PORT_PROP, PostgreSQLConstants.POSTGRESQL_PORT_DEFAULT))
+            .instanceName(this.env.getProperty(PostgreSQLConstants.POSTGRESQL_DATABASE_NAME_PROP, PostgreSQLConstants.POSTGRESQL_DATABASE_NAME_DEFAULT))
+            .build());
+    boneCPDataSource.setUsername(
+            this.env.getProperty(PostgreSQLConstants.POSTGRESQL_USER_PROP, PostgreSQLConstants.POSTGRESQL_USER_DEFAULT));
+    boneCPDataSource.setIdleConnectionTestPeriodInMinutes(
+            Long.valueOf(this.env.getProperty(PostgreSQLConstants.BONECP_IDLE_CONNECTION_TEST_PROP, PostgreSQLConstants.BONECP_IDLE_CONNECTION_TEST_DEFAULT)));
+    boneCPDataSource.setIdleMaxAgeInMinutes(
+            Long.valueOf(this.env.getProperty(PostgreSQLConstants.BONECP_IDLE_MAX_AGE_PROP, PostgreSQLConstants.BONECP_IDLE_MAX_AGE_DEFAULT)));
+    boneCPDataSource.setMaxConnectionsPerPartition(
+            Integer.valueOf(this.env.getProperty(PostgreSQLConstants.BONECP_MAX_CONNECTION_PARTITION_PROP, PostgreSQLConstants.BONECP_MAX_CONNECTION_PARTITION_DEFAULT)));
+    boneCPDataSource.setMinConnectionsPerPartition(
+            Integer.valueOf(this.env.getProperty(PostgreSQLConstants.BONECP_MIN_CONNECTION_PARTITION_PROP, PostgreSQLConstants.BONECP_MIN_CONNECTION_PARTITION_DEFAULT)));
+    boneCPDataSource.setPartitionCount(
+            Integer.valueOf(this.env.getProperty(PostgreSQLConstants.BONECP_PARTITION_COUNT_PROP, PostgreSQLConstants.BONECP_PARTITION_COUNT_DEFAULT)));
+    boneCPDataSource.setAcquireIncrement(
+            Integer.valueOf(this.env.getProperty(PostgreSQLConstants.BONECP_ACQUIRE_INCREMENT_PROP, PostgreSQLConstants.BONECP_ACQUIRE_INCREMENT_DEFAULT)));
+    boneCPDataSource.setStatementsCacheSize(
+            Integer.valueOf(this.env.getProperty(PostgreSQLConstants.BONECP_STATEMENT_CACHE_PROP, PostgreSQLConstants.BONECP_STATEMENT_CACHE_DEFAULT)));
+
+    final Properties driverProperties = new Properties();
+    driverProperties.setProperty("useServerPrepStmts", "false");
+    boneCPDataSource.setDriverProperties(driverProperties);
+    return new MetaDataSourceWrapper(boneCPDataSource);
+  }
+
+  private Properties additionalProperties() {
+    final Properties properties = new Properties();
+    properties.setProperty("openjpa.jdbc.DBDictionary", "org.apache.openjpa.jdbc.sql.PostgresDictionary");
+    return properties;
+  }
+}
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLJavaConfigurationImportSelector.java b/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLJavaConfigurationImportSelector.java
new file mode 100644
index 0000000..557ba0c
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLJavaConfigurationImportSelector.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.config;
+
+import org.springframework.context.annotation.ImportSelector;
+import org.springframework.core.type.AnnotationMetadata;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Isaac Kamga
+ */
+class PostgreSQLJavaConfigurationImportSelector implements ImportSelector {
+  @Override
+  public String[] selectImports(AnnotationMetadata importingClassMetadata) {
+    final boolean forTenantContext = (boolean)importingClassMetadata
+            .getAnnotationAttributes(EnablePostgreSQL.class.getTypeName())
+            .get("forTenantContext");
+
+    final Set<Class> classesToImport = new HashSet<>();
+    final String prop = System.getProperty("postgresql.enabled");
+    if (prop == null || "true".equals(prop)) {
+      classesToImport.add(PostgreSQLJavaConfiguration.class);
+      if (forTenantContext) {
+        classesToImport.add(PostgreSQLTenantBasedJavaConfiguration.class);
+      }
+      else {
+        classesToImport.add(PostgreSQLTenantFreeJavaConfiguration.class);
+      }
+    }
+    return classesToImport.stream().map(Class::getCanonicalName).toArray(String[]::new);
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLTenantBasedJavaConfiguration.java b/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLTenantBasedJavaConfiguration.java
new file mode 100644
index 0000000..a11cd35
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLTenantBasedJavaConfiguration.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.config;
+
+import org.apache.fineract.cn.postgresql.domain.ContextAwareRoutingDataSource;
+import org.apache.fineract.cn.postgresql.util.JdbcUrlBuilder;
+import org.apache.fineract.cn.postgresql.util.PostgreSQLConstants;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+import java.util.HashMap;
+
+@SuppressWarnings("WeakerAccess")
+@Configuration
+@ConditionalOnProperty(prefix = "postgresql", name = "enabled", matchIfMissing = true)
+public class PostgreSQLTenantBasedJavaConfiguration {
+  public DataSource dataSource(@Qualifier(PostgreSQLConstants.LOGGER_NAME) final Logger logger,
+                               final MetaDataSourceWrapper metaDataSource) {
+
+  final ContextAwareRoutingDataSource dataSources = new ContextAwareRoutingDataSource(logger, JdbcUrlBuilder.DatabaseType.POSTGRESQL);
+  dataSources.setMetaDataSource(metaDataSource.getMetaDataSource());
+  final HashMap<Object, Object> targetDataSources = new HashMap<>();
+  dataSources.setTargetDataSources(targetDataSources);
+  return dataSources;
+  }
+}
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLTenantFreeJavaConfiguration.java b/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLTenantFreeJavaConfiguration.java
new file mode 100644
index 0000000..a5310a5
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/config/PostgreSQLTenantFreeJavaConfiguration.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import javax.sql.DataSource;
+
+/**
+ * @author Isaac Kamga
+ */
+@SuppressWarnings("WeakerAccess")
+@Configuration
+@ConditionalOnProperty(prefix = "postgresql", name = "enabled", matchIfMissing = true)
+public class PostgreSQLTenantFreeJavaConfiguration {
+  @Bean
+  public DataSource dataSource(final MetaDataSourceWrapper metaDataSource) {
+    return metaDataSource.getMetaDataSource();
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/domain/ContextAwareRoutingDataSource.java b/src/main/java/org/apache/fineract/cn/postgresql/domain/ContextAwareRoutingDataSource.java
new file mode 100644
index 0000000..d3df26f
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/domain/ContextAwareRoutingDataSource.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.domain;
+
+import com.jolbox.bonecp.BoneCPDataSource;
+import org.apache.fineract.cn.postgresql.util.JdbcUrlBuilder;
+import org.apache.fineract.cn.postgresql.util.PostgreSQLConstants;
+import org.apache.fineract.cn.lang.TenantContextHolder;
+import org.apache.fineract.cn.postgresql.util.JdbcUrlBuilder.DatabaseType;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.concurrent.ConcurrentHashMap;
+
+public final class ContextAwareRoutingDataSource extends AbstractRoutingDataSource {
+
+  private final Logger logger;
+  private final DatabaseType type;
+  private final ConcurrentHashMap<String, DataSource> dynamicDataSources;
+  private DataSource metaDataSource;
+
+  public ContextAwareRoutingDataSource(@Qualifier(PostgreSQLConstants.LOGGER_NAME) final Logger logger,
+                                       final DatabaseType type) {
+    super();
+    this.logger = logger;
+    this.type = type;
+    this.dynamicDataSources = new ConcurrentHashMap<>();
+  }
+
+  public void setMetaDataSource(final DataSource metaDataSource) {
+    this.metaDataSource = metaDataSource;
+    super.setDefaultTargetDataSource(metaDataSource);
+  }
+
+  @Override
+  protected Object determineCurrentLookupKey() {
+    return TenantContextHolder.checkedGetIdentifier();
+  }
+
+  @Override
+  protected DataSource determineTargetDataSource() {
+    if (!TenantContextHolder.identifier().isPresent()) {
+      this.logger.warn("Tenant context not available.");
+      return super.determineTargetDataSource();
+    }
+
+    final String currentLookupKey = this.determineCurrentLookupKey().toString();
+
+    this.dynamicDataSources.computeIfAbsent(currentLookupKey, (key) -> {
+      this.logger.info("Creating new dynamic data source for {}.", key);
+      final Tenant tenant = new Tenant(key);
+      this.readAdditionalTenantInformation(tenant);
+      final BoneCPDataSource tenantDataSource = new BoneCPDataSource();
+      tenantDataSource.setDriverClass(tenant.getDriverClass());
+      tenantDataSource.setJdbcUrl(JdbcUrlBuilder
+          .create(this.type)
+          .host(tenant.getHost())
+          .port(tenant.getPort())
+          .instanceName(tenant.getDatabaseName())
+          .build());
+      tenantDataSource.setUsername(tenant.getUser());
+
+      final BoneCPDataSource boneCpMetaDataSource = (BoneCPDataSource) this.metaDataSource;
+      tenantDataSource.setIdleConnectionTestPeriodInMinutes(boneCpMetaDataSource.getIdleConnectionTestPeriodInMinutes());
+      tenantDataSource.setIdleMaxAgeInMinutes(boneCpMetaDataSource.getIdleMaxAgeInMinutes());
+      tenantDataSource.setMaxConnectionsPerPartition(boneCpMetaDataSource.getMaxConnectionsPerPartition());
+      tenantDataSource.setMinConnectionsPerPartition(boneCpMetaDataSource.getMinConnectionsPerPartition());
+      tenantDataSource.setPartitionCount(boneCpMetaDataSource.getPartitionCount());
+      tenantDataSource.setAcquireIncrement(boneCpMetaDataSource.getAcquireIncrement());
+      tenantDataSource.setStatementsCacheSize(boneCpMetaDataSource.getStatementsCacheSize());
+      return tenantDataSource;
+    });
+
+    return this.dynamicDataSources.get(currentLookupKey);
+  }
+
+  private void readAdditionalTenantInformation(final Tenant tenant) {
+    this.logger.info("Reading additional information for {}.", tenant.getIdentifier());
+    @SuppressWarnings({"SqlDialectInspection", "SqlNoDataSourceInspection"})
+    final String query = "SELECT driver_class, database_name, host, port, a_user FROM seshat.tenants WHERE identifier = ?";
+    try (final Connection connection = this.metaDataSource.getConnection()) {
+      try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
+        preparedStatement.setString(1, tenant.getIdentifier());
+        final ResultSet resultSet = preparedStatement.executeQuery();
+        if (resultSet.next()) {
+          tenant.setDriverClass(resultSet.getString("driver_class"));
+          tenant.setDatabaseName(resultSet.getString("database_name"));
+          tenant.setHost(resultSet.getString("host"));
+          tenant.setPort(resultSet.getString("port"));
+          tenant.setUser(resultSet.getString("a_user"));
+        }
+      }
+    } catch (SQLException ex) {
+      throw new IllegalArgumentException("Could not fetch information for tenant '" + tenant.getIdentifier() + "'", ex);
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/domain/FlywayFactoryBean.java b/src/main/java/org/apache/fineract/cn/postgresql/domain/FlywayFactoryBean.java
new file mode 100644
index 0000000..144961a
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/domain/FlywayFactoryBean.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.domain;
+
+import org.apache.fineract.cn.lang.ApplicationName;
+import org.flywaydb.core.Flyway;
+
+import javax.sql.DataSource;
+
+public class FlywayFactoryBean {
+
+  private final ApplicationName applicationName;
+
+  public FlywayFactoryBean(final ApplicationName applicationName) {
+    super();
+    this.applicationName = applicationName;
+  }
+
+  public Flyway create(final DataSource dataSource) {
+    final Flyway flyway = new Flyway();
+    flyway.setDataSource(dataSource);
+    flyway.setLocations("db/migrations/postgresql");
+    flyway.setTable(this.applicationName.getServiceName() + "_schema_version");
+    flyway.setBaselineOnMigrate(true);
+    flyway.setBaselineVersionAsString("0");
+    return flyway;
+  }
+}
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/domain/Tenant.java b/src/main/java/org/apache/fineract/cn/postgresql/domain/Tenant.java
new file mode 100644
index 0000000..3bb7ef0
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/domain/Tenant.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.domain;
+
+@SuppressWarnings("WeakerAccess")
+public final class Tenant {
+
+  private final String identifier;
+  private String driverClass;
+  private String databaseName;
+  private String host;
+  private String port;
+  private String user;
+
+  public Tenant(final String identifier) {
+    super();
+    this.identifier = identifier;
+  }
+
+  public String getIdentifier() {
+    return identifier;
+  }
+
+  public String getDriverClass() {
+    return driverClass;
+  }
+
+  public void setDriverClass(String driverClass) {
+    this.driverClass = driverClass;
+  }
+
+  public String getDatabaseName() {
+    return databaseName;
+  }
+
+  public void setDatabaseName(String databaseName) {
+    this.databaseName = databaseName;
+  }
+
+  public String getHost() {
+    return host;
+  }
+
+  public void setHost(String host) {
+    this.host = host;
+  }
+
+  public String getPort() {
+    return port;
+  }
+
+  public void setPort(String port) {
+    this.port = port;
+  }
+
+  public String getUser() {
+    return user;
+  }
+
+  public void setUser(String user) {
+    this.user = user;
+  }
+}
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/util/JdbcUrlBuilder.java b/src/main/java/org/apache/fineract/cn/postgresql/util/JdbcUrlBuilder.java
new file mode 100644
index 0000000..d7b6d7b
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/util/JdbcUrlBuilder.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.util;
+
+public final class JdbcUrlBuilder {
+
+  private final DatabaseType type;
+  private String host;
+  private String port;
+  private String instanceName;
+
+  private JdbcUrlBuilder(final DatabaseType type) {
+    super();
+    this.type = type;
+  }
+
+  public static JdbcUrlBuilder create(final DatabaseType type) {
+    return new JdbcUrlBuilder(type);
+  }
+
+  public JdbcUrlBuilder host(final String host) {
+    this.host = host;
+    return this;
+  }
+
+  public JdbcUrlBuilder port(final String port) {
+    this.port = port;
+    return this;
+  }
+
+  public JdbcUrlBuilder instanceName(final String instanceName) {
+    this.instanceName = instanceName;
+    return this;
+  }
+
+  public String build() {
+    switch (this.type) {
+      case POSTGRESQL:
+        final StringBuilder jdbcUrl = new StringBuilder(this.type.getSubProtocol());
+        if (this.host == null){
+          if (this.instanceName == null){
+            jdbcUrl.append("/");
+          }
+          else
+            jdbcUrl.append(instanceName);
+        }
+        else {
+          if (this.port == null){
+            if (this.instanceName == null){
+              jdbcUrl.append("//").append(this.host).append("/");
+            }
+            else
+              jdbcUrl.append("//").append(this.host).append("/").append(this.instanceName);
+          }
+          else {
+            if (this.instanceName == null){
+              jdbcUrl.append("//").append(this.host).append(":").append(this.port).append("/");
+            }
+            else {
+              jdbcUrl.append("//").append(this.host).append(":").append(this.port).append("/").append(instanceName);
+            }
+          }
+        }
+        return jdbcUrl.toString();
+      default:
+        throw new IllegalArgumentException("Unknown database type '" + this.type.name() + "'");
+    }
+  }
+
+  public enum DatabaseType {
+    POSTGRESQL("jdbc:postgresql:");
+
+    private final String subProtocol;
+
+    DatabaseType(final String subProtocol) {
+      this.subProtocol = subProtocol;
+    }
+
+    String getSubProtocol() {
+      return this.subProtocol;
+    }
+  }
+}
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/util/LocalDateConverter.java b/src/main/java/org/apache/fineract/cn/postgresql/util/LocalDateConverter.java
new file mode 100644
index 0000000..29ea090
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/util/LocalDateConverter.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.util;
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import java.sql.Date;
+import java.time.LocalDate;
+
+@Converter
+public class LocalDateConverter implements AttributeConverter<LocalDate, Date> {
+
+  public LocalDateConverter() {
+    super();
+  }
+
+  @Override
+  public Date convertToDatabaseColumn(final LocalDate attribute) {
+    if (attribute == null) {
+      return null;
+    } else {
+      return Date.valueOf(attribute);
+    }
+  }
+
+  @Override
+  public LocalDate convertToEntityAttribute(final Date dbData) {
+    if (dbData == null) {
+      return null;
+    } else {
+      return dbData.toLocalDate();
+    }
+  }
+}
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/util/LocalDateTimeConverter.java b/src/main/java/org/apache/fineract/cn/postgresql/util/LocalDateTimeConverter.java
new file mode 100644
index 0000000..47fb20e
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/util/LocalDateTimeConverter.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.util;
+
+
+import javax.persistence.AttributeConverter;
+import javax.persistence.Converter;
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+import org.apache.fineract.cn.lang.DateConverter;
+
+@Converter
+public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
+
+  public LocalDateTimeConverter() {
+    super();
+  }
+
+  @Override
+  public Timestamp convertToDatabaseColumn(final LocalDateTime attribute) {
+    if (attribute == null) {
+      return null;
+    } else {
+      return new Timestamp(DateConverter.toEpochMillis(attribute));
+    }
+  }
+
+  @Override
+  public LocalDateTime convertToEntityAttribute(final Timestamp dbData) {
+    if (dbData == null) {
+      return null;
+    } else {
+      return DateConverter.fromEpochMillis(dbData.getTime());
+    }
+  }
+}
diff --git a/src/main/java/org/apache/fineract/cn/postgresql/util/PostgreSQLConstants.java b/src/main/java/org/apache/fineract/cn/postgresql/util/PostgreSQLConstants.java
new file mode 100644
index 0000000..5ed5aa0
--- /dev/null
+++ b/src/main/java/org/apache/fineract/cn/postgresql/util/PostgreSQLConstants.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.util;
+
+public interface PostgreSQLConstants {
+
+  String LOGGER_NAME = "postgresql-logger";
+
+  String POSTGRESQL_DRIVER_CLASS_PROP = "postgresql.driverClass";
+  String POSTGRESQL_DRIVER_CLASS_DEFAULT = "org.postgresql.jdbc.Driver";
+  String POSTGRESQL_DATABASE_NAME_PROP = "postgresql.database";
+  String POSTGRESQL_DATABASE_NAME_DEFAULT = "seshat";
+  String POSTGRESQL_HOST_PROP = "postgresql.host";
+  String POSTGRESQL_HOST_DEFAULT = "localhost";
+  String POSTGRESQL_PORT_PROP = "postgresql.port";
+  String POSTGRESQL_PORT_DEFAULT = "5432";
+  String POSTGRESQL_USER_PROP = "postgresql.user";
+  String POSTGRESQL_USER_DEFAULT = "postgres";
+
+  String BONECP_IDLE_MAX_AGE_PROP = "bonecp.idleMaxAgeInMinutes";
+  String BONECP_IDLE_MAX_AGE_DEFAULT = "240";
+  String BONECP_IDLE_CONNECTION_TEST_PROP = "bonecp.idleConnectionTestPeriodInMinutes";
+  String BONECP_IDLE_CONNECTION_TEST_DEFAULT = "60";
+  String BONECP_MAX_CONNECTION_PARTITION_PROP = "bonecp.maxConnectionsPerPartition";
+  String BONECP_MAX_CONNECTION_PARTITION_DEFAULT = "16";
+  String BONECP_MIN_CONNECTION_PARTITION_PROP = "bonecp.minConnectionsPerPartition";
+  String BONECP_MIN_CONNECTION_PARTITION_DEFAULT = "4";
+  String BONECP_PARTITION_COUNT_PROP = "bonecp.partitionCount";
+  String BONECP_PARTITION_COUNT_DEFAULT = "2";
+  String BONECP_ACQUIRE_INCREMENT_PROP = "bonecp.acquireIncrement";
+  String BONECP_ACQUIRE_INCREMENT_DEFAULT = "4";
+  String BONECP_STATEMENT_CACHE_PROP = "bonecp.statementsCacheSize";
+  String BONECP_STATEMENT_CACHE_DEFAULT = "128";
+}
diff --git a/src/test/java/org/apache/fineract/cn/postgresql/util/JdbcUrlBuilderTest.java b/src/test/java/org/apache/fineract/cn/postgresql/util/JdbcUrlBuilderTest.java
new file mode 100644
index 0000000..b78a0b4
--- /dev/null
+++ b/src/test/java/org/apache/fineract/cn/postgresql/util/JdbcUrlBuilderTest.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/*
+ * PostgreSQL URL Formats
+ * https://jdbc.postgresql.org/documentation/head/connect.html
+ */
+
+public class JdbcUrlBuilderTest {
+
+  public JdbcUrlBuilderTest() {
+    super();
+  }
+
+  @Test
+  public void shouldCreatePostgresqlUrlNeitherHostNorPort() {
+    final String expectedJdbcUrl = "jdbc:postgresql:comp_test";
+
+    final String postgresqlJdbcUrl = JdbcUrlBuilder
+            .create(JdbcUrlBuilder.DatabaseType.POSTGRESQL)
+            .instanceName("comp_test")
+            .build();
+
+    Assert.assertEquals(expectedJdbcUrl, postgresqlJdbcUrl);
+  }
+
+  @Test
+  public void shouldCreatePostgresqlUrlNeitherHostNorInstance() {
+    final String expectedJdbcUrl = "jdbc:postgresql:/";
+
+    final String postgresqlJdbcUrl = JdbcUrlBuilder
+            .create(JdbcUrlBuilder.DatabaseType.POSTGRESQL)
+            .build();
+
+    Assert.assertEquals(expectedJdbcUrl, postgresqlJdbcUrl);
+  }
+
+  @Test
+  public void shouldCreatePostgresqlUrlWithHostAndInstance() {
+    final String expectedJdbcUrl = "jdbc:postgresql://localhost/comp_test";
+
+    final String postgresqlJdbcUrl = JdbcUrlBuilder
+        .create(JdbcUrlBuilder.DatabaseType.POSTGRESQL)
+        .host("localhost")
+        .instanceName("comp_test")
+        .build();
+
+    Assert.assertEquals(expectedJdbcUrl, postgresqlJdbcUrl);
+  }
+
+  @Test
+  public void shouldCreatePostgresqlUrlNoPort() {
+    final String expectedJdbcUrl = "jdbc:postgresql://localhost/";
+
+    final String postgresqlJdbcUrl = JdbcUrlBuilder
+        .create(JdbcUrlBuilder.DatabaseType.POSTGRESQL)
+        .host("localhost")
+        .build();
+
+    Assert.assertEquals(expectedJdbcUrl, postgresqlJdbcUrl);
+  }
+
+  @Test
+  public void shouldCreatePostgresqlUrl() {
+    final String expectedJdbcUrl = "jdbc:postgresql://localhost:5432/comp_test";
+
+    final String postgresqlJdbcUrl = JdbcUrlBuilder
+        .create(JdbcUrlBuilder.DatabaseType.POSTGRESQL)
+        .host("localhost")
+        .port("5432")
+        .instanceName("comp_test")
+        .build();
+
+    Assert.assertEquals(expectedJdbcUrl, postgresqlJdbcUrl);
+  }
+
+  @Test
+  public void shouldCreatePostgresqlUrlNoInstance() {
+    final String expectedJdbcUrl = "jdbc:postgresql://localhost:5432/";
+
+    final String postgresqlJdbcUrl = JdbcUrlBuilder
+        .create(JdbcUrlBuilder.DatabaseType.POSTGRESQL)
+        .host("localhost")
+        .port("5432").build();
+
+    Assert.assertEquals(expectedJdbcUrl, postgresqlJdbcUrl);
+  }
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/fineract/cn/postgresql/util/LocalDateConverterTest.java b/src/test/java/org/apache/fineract/cn/postgresql/util/LocalDateConverterTest.java
new file mode 100644
index 0000000..263ca57
--- /dev/null
+++ b/src/test/java/org/apache/fineract/cn/postgresql/util/LocalDateConverterTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.cn.postgresql.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.sql.Date;
+import java.time.LocalDate;
+
+public class LocalDateConverterTest {
+
+  public LocalDateConverterTest() {
+    super();
+  }
+
+  @Test
+  public void shouldConvertLocalDate() {
+    final LocalDateConverter converter = new LocalDateConverter();
+
+    final LocalDate expected = LocalDate.of(2017, 1, 1);
+
+    final Date dbDate = converter.convertToDatabaseColumn(expected);
+
+    final LocalDate result = converter.convertToEntityAttribute(dbDate);
+
+    Assert.assertEquals(expected, result);
+  }
+}
diff --git a/travis.yml b/travis.yml
new file mode 100644
index 0000000..5cc5893
--- /dev/null
+++ b/travis.yml
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+language: java
+jdk:
+ - oraclejdk8
\ No newline at end of file