Merge pull request #1079 from vorburger/SpringBootAndMariaDB4j
MIFOSX-1552 Spring Boot + MariaDB4j
This commit is contained in:
-3
@@ -1,3 +0,0 @@
|
|||||||
UPDATE m_permission
|
|
||||||
SET action_name = CONCAT(action_name,'_CHECKER')
|
|
||||||
WHERE code LIKE "%_CHECKER";
|
|
||||||
@@ -11,13 +11,15 @@ buildscript {
|
|||||||
dependencies {
|
dependencies {
|
||||||
classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:1.0',
|
classpath 'org.gradle.api.plugins:gradle-tomcat-plugin:1.0',
|
||||||
'nl.javadude.gradle.plugins:license-gradle-plugin:0.11.0',
|
'nl.javadude.gradle.plugins:license-gradle-plugin:0.11.0',
|
||||||
'org.zeroturnaround:gradle-jrebel-plugin:1.1.2'
|
'org.zeroturnaround:gradle-jrebel-plugin:1.1.2',
|
||||||
|
'org.springframework.boot:spring-boot-gradle-plugin:1.1.6.RELEASE' // also change springDataJpaVersion below
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: 'rebel'
|
apply plugin: 'rebel'
|
||||||
apply plugin: 'license'
|
apply plugin: 'license'
|
||||||
apply plugin: 'war'
|
apply plugin: 'war'
|
||||||
|
apply plugin: 'spring-boot'
|
||||||
apply plugin: 'eclipse'
|
apply plugin: 'eclipse'
|
||||||
apply plugin: 'idea'
|
apply plugin: 'idea'
|
||||||
apply plugin: 'tomcat'
|
apply plugin: 'tomcat'
|
||||||
@@ -25,14 +27,13 @@ apply plugin: 'project-report'
|
|||||||
|
|
||||||
/* define the valid syntax level for source files */
|
/* define the valid syntax level for source files */
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_7
|
sourceCompatibility = JavaVersion.VERSION_1_7
|
||||||
/* define binary compatiblity version */
|
/* define binary compatibility version */
|
||||||
targetCompatibility = JavaVersion.VERSION_1_7
|
targetCompatibility = JavaVersion.VERSION_1_7
|
||||||
|
|
||||||
project.ext.springVersion = '4.0.4.RELEASE'
|
project.ext.springBootVersion = '1.1.6.RELEASE'
|
||||||
project.ext.springSecurityVersion = '3.2.3.RELEASE'
|
project.ext.springVersion = '4.0.7.RELEASE'
|
||||||
project.ext.hibernateCoreVersion = '4.1.9.Final'
|
|
||||||
project.ext.jerseyVersion = '1.17'
|
project.ext.jerseyVersion = '1.17'
|
||||||
project.ext.springDataJpaVersion = '1.4.1.RELEASE'
|
project.ext.springDataJpaVersion = '1.7.0.RELEASE' // also change spring-boot-gradle-plugin version above
|
||||||
|
|
||||||
project.ext.mysqlUser='root'
|
project.ext.mysqlUser='root'
|
||||||
project.ext.mysqlPassword='mysql'
|
project.ext.mysqlPassword='mysql'
|
||||||
@@ -43,11 +44,13 @@ group = 'org.mifosplatform'
|
|||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
maven {
|
maven {
|
||||||
url "http://repository.pentaho.org/artifactory/pentaho/"
|
url "http://repository.pentaho.org/artifactory/pentaho/"
|
||||||
}
|
}
|
||||||
|
// mavenLocal() // useful for local dev using MariaDB4j SNAPSHOTs (not needed for real-world non-SNAPHOT builds)
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
|
providedRuntime // needed for Spring Boot executable WAR
|
||||||
providedCompile
|
providedCompile
|
||||||
compile
|
compile
|
||||||
runtime
|
runtime
|
||||||
@@ -55,32 +58,28 @@ configurations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
def tomcatVersion = '7.0.47'
|
def tomcatVersion = '7.0.54'
|
||||||
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
|
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
|
||||||
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
|
"org.apache.tomcat.embed:tomcat-embed-logging-log4j:${tomcatVersion}" // NOT tomcat-embed-logging-juli (http://stackoverflow.com/questions/23963049/classcircularityerror-java-util-logging-logrecord-running-gradle-webapp-with-ja)
|
||||||
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
|
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
|
||||||
exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
|
exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
|
||||||
}
|
}
|
||||||
tomcat "org.apache.tomcat:tomcat-dbcp:${tomcatVersion}"
|
tomcat "org.apache.tomcat:tomcat-dbcp:${tomcatVersion}"
|
||||||
|
|
||||||
|
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
|
||||||
|
|
||||||
providedCompile(
|
providedCompile(
|
||||||
[group: 'javax.servlet', name: 'servlet-api', version: '2.5'],
|
// [group: 'javax.servlet', name: 'servlet-api', version: '2.5'],
|
||||||
)
|
)
|
||||||
|
|
||||||
compile(
|
compile(
|
||||||
[group: 'org.springframework', name: 'spring-core', version: springVersion],
|
[group: 'ch.vorburger.mariaDB4j', name: 'mariaDB4j', version: '2.1.0'],
|
||||||
[group: 'org.springframework', name: 'spring-context-support', version: springVersion],
|
|
||||||
[group: 'org.springframework', name: 'spring-aspects', version: springVersion],
|
|
||||||
[group: 'org.springframework', name: 'spring-web', version: springVersion],
|
|
||||||
[group: 'org.springframework', name: 'spring-test', version: springVersion],
|
|
||||||
[group: 'org.springframework.security', name: 'spring-security-core', version: springSecurityVersion],
|
|
||||||
[group: 'org.springframework.security', name: 'spring-security-web', version: springSecurityVersion],
|
|
||||||
[group: 'org.springframework.security', name: 'spring-security-config', version: springSecurityVersion],
|
|
||||||
[group: 'org.aspectj', name: 'aspectjrt', version: '1.7.0.RELEASE'],
|
|
||||||
|
|
||||||
[group: 'org.hibernate', name: 'hibernate-core', version: hibernateCoreVersion],
|
[group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion],
|
||||||
[group: 'org.hibernate', name: 'hibernate-entitymanager', version: hibernateCoreVersion],
|
[group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: springBootVersion],
|
||||||
[group: 'org.hibernate.javax.persistence', name: 'hibernate-jpa-2.0-api', version: '1.0.1.Final'],
|
[group: 'org.springframework.boot', name: 'spring-boot-starter-security', version: springBootVersion],
|
||||||
|
|
||||||
|
[group: 'org.springframework', name: 'spring-context-support', version: springVersion],
|
||||||
|
|
||||||
[group: 'javax.ws.rs', name: 'jsr311-api', version: '1.1.1'],
|
[group: 'javax.ws.rs', name: 'jsr311-api', version: '1.1.1'],
|
||||||
[group: 'com.sun.jersey', name: 'jersey-core', version: jerseyVersion],
|
[group: 'com.sun.jersey', name: 'jersey-core', version: jerseyVersion],
|
||||||
@@ -98,21 +97,15 @@ dependencies {
|
|||||||
[group: 'com.google.code.gson', name: 'gson', version: '2.2.4'],
|
[group: 'com.google.code.gson', name: 'gson', version: '2.2.4'],
|
||||||
[group: 'com.google.guava', name: 'guava', version: '15.0'],
|
[group: 'com.google.guava', name: 'guava', version: '15.0'],
|
||||||
|
|
||||||
[group: 'org.springframework.data', name: 'spring-data-jpa', version: springDataJpaVersion],
|
[group: 'joda-time', name: 'joda-time', version: '2.4'],
|
||||||
|
|
||||||
[group: 'joda-time', name: 'joda-time', version: '2.3'],
|
|
||||||
[group: 'net.sourceforge.javacsv', name: 'javacsv', version: '2.0'],
|
[group: 'net.sourceforge.javacsv', name: 'javacsv', version: '2.0'],
|
||||||
[group: 'org.apache.commons', name: 'commons-email', version: '1.3.1'],
|
[group: 'org.apache.commons', name: 'commons-email', version: '1.3.3'],
|
||||||
[group: 'org.apache.commons', name: 'commons-lang3', version: '3.1'],
|
[group: 'org.apache.commons', name: 'commons-lang3', version: '3.3.2'],
|
||||||
|
|
||||||
[group: 'org.slf4j', name: 'slf4j-api', version: '1.7.5'],
|
// no slf4j & logback here (anymore), as spring-boot-starter-logging already brings this now, better assembled (log4j-over-slf4j was originally forgotten here)
|
||||||
[group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.5'],
|
|
||||||
|
|
||||||
[group: 'ch.qos.logback', name: 'logback-core', version: '1.0.13'],
|
|
||||||
[group: 'ch.qos.logback', name: 'logback-classic', version: '1.0.13'],
|
|
||||||
|
|
||||||
[group: 'mysql', name: 'mysql-connector-java', version: '5.1.27'],
|
[group: 'mysql', name: 'mysql-connector-java', version: '5.1.27'],
|
||||||
[group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: '7.0.47'],
|
[group: 'org.apache.tomcat', name: 'tomcat-jdbc', version: tomcatVersion],
|
||||||
|
|
||||||
[group: 'pentaho-reporting-engine', name: 'pentaho-reporting-engine-classic-core', version: '3.9.1.1'],
|
[group: 'pentaho-reporting-engine', name: 'pentaho-reporting-engine-classic-core', version: '3.9.1.1'],
|
||||||
[group: 'pentaho-reporting-engine', name: 'pentaho-reporting-engine-classic-extensions', version: '3.9.1-GA'],
|
[group: 'pentaho-reporting-engine', name: 'pentaho-reporting-engine-classic-extensions', version: '3.9.1-GA'],
|
||||||
@@ -143,12 +136,17 @@ dependencies {
|
|||||||
[group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.2.1'],
|
[group: 'com.amazonaws', name: 'aws-java-sdk', version: '1.2.1'],
|
||||||
[group: 'net.sf.ehcache', name: 'ehcache', version: '2.7.2'],
|
[group: 'net.sf.ehcache', name: 'ehcache', version: '2.7.2'],
|
||||||
[group: 'com.github.spullara.mustache.java', name: 'compiler', version: '0.8.12'],
|
[group: 'com.github.spullara.mustache.java', name: 'compiler', version: '0.8.12'],
|
||||||
[group: 'com.jayway.jsonpath', name: 'json-path', version: '0.9.1'])
|
[group: 'com.jayway.jsonpath', name: 'json-path', version: '0.9.1'],
|
||||||
|
|
||||||
testCompile 'junit:junit:4.11',
|
// Although Mifos (at the time of writing) doesn't have any compile time dep. on this,
|
||||||
'junit:junit-dep:4.11',
|
// it's useful to have this for the Spring Boot TestRestTemplate http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-rest-templates-test-utility
|
||||||
'org.mockito:mockito-all:1.9.5',
|
[group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.2.3']
|
||||||
'com.jayway.restassured:rest-assured:1.7.2'
|
)
|
||||||
|
testCompile 'junit:junit:4.11',
|
||||||
|
'junit:junit-dep:4.11',
|
||||||
|
'org.mockito:mockito-core:1.9.5',
|
||||||
|
'com.jayway.restassured:rest-assured:1.7.2',
|
||||||
|
[group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: springBootVersion]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +177,7 @@ task dist(type:Zip){
|
|||||||
include '*.sql'
|
include '*.sql'
|
||||||
into('database')
|
into('database')
|
||||||
}
|
}
|
||||||
from('../mifosng-db/migrations') {
|
from('src/main/resources/sql/migrations') {
|
||||||
fileMode = 0755
|
fileMode = 0755
|
||||||
include '**/*'
|
include '**/*'
|
||||||
into('database/migrations')
|
into('database/migrations')
|
||||||
@@ -203,14 +201,11 @@ task deployPentahoReports() {
|
|||||||
|
|
||||||
war {
|
war {
|
||||||
it.dependsOn deployPentahoReports
|
it.dependsOn deployPentahoReports
|
||||||
from ('../mifosng-db/migrations/core_db') {
|
|
||||||
into "WEB-INF/classes/sql"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
license {
|
license {
|
||||||
header rootProject.file('../LICENSE.md')
|
header rootProject.file('../LICENSE.md')
|
||||||
excludes(["**/*.mustache"])
|
excludes(["**/*.mustache", "**/*.sql", "**/package-info.java", "**/keystore.jks"])
|
||||||
strictCheck true
|
strictCheck true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,7 +224,7 @@ tomcatRunWar {
|
|||||||
stopPort = 8081
|
stopPort = 8081
|
||||||
stopKey= 'stopKey'
|
stopKey= 'stopKey'
|
||||||
enableSSL = true
|
enableSSL = true
|
||||||
keystoreFile = file('../keystore.jks')
|
keystoreFile = file('src/main/resources/keystore.jks')
|
||||||
keystorePass = 'openmf'
|
keystorePass = 'openmf'
|
||||||
configFile = file('src/test/resources/META-INF/context.xml')
|
configFile = file('src/test/resources/META-INF/context.xml')
|
||||||
}
|
}
|
||||||
@@ -306,7 +301,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.github.ben-manes:gradle-flyway-plugin:0.2'
|
classpath "org.flywaydb:flyway-gradle-plugin:3.0" // version upgraded during Spring Boot & MariaDB4j work, as prev. used v0.2 didn't work well after *.sql moved from mifosng-db to mifosng-provider/src/main/resources (new version also has clearer errors, e.g. in case of missing DB)
|
||||||
classpath 'mysql:mysql-connector-java:5.1.22'
|
classpath 'mysql:mysql-connector-java:5.1.22'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,15 +311,12 @@ flyway {
|
|||||||
url = "jdbc:mysql://localhost:3306/mifostenant-default"
|
url = "jdbc:mysql://localhost:3306/mifostenant-default"
|
||||||
user = mysqlUser
|
user = mysqlUser
|
||||||
password = mysqlPassword
|
password = mysqlPassword
|
||||||
|
|
||||||
def filePath = "filesystem:$projectDir" + System.properties['file.separator'] + '..' + System.properties['file.separator'] + 'mifosng-db' + System.properties['file.separator'] + 'migrations'
|
|
||||||
locations = [filePath]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task migrateTenantDB<<{
|
task migrateTenantDB<<{
|
||||||
description="Migrates a Tenant DB. Optionally can pass dbName. Defaults to 'mifostenant-default' (Example: -PdbName=someTenantDBname)"
|
description="Migrates a Tenant DB. Optionally can pass dbName. Defaults to 'mifostenant-default' (Example: -PdbName=someTenantDBname)"
|
||||||
|
|
||||||
def filePath = "filesystem:$projectDir" + System.properties['file.separator'] + '..' + System.properties['file.separator'] + 'mifosng-db' + System.properties['file.separator'] + 'migrations/core_db'
|
def filePath = "filesystem:$projectDir" + '/src/main/resources/sql/migrations/core_db'
|
||||||
def tenantDbName = 'mifostenant-default';
|
def tenantDbName = 'mifostenant-default';
|
||||||
if (rootProject.hasProperty("dbName")) {
|
if (rootProject.hasProperty("dbName")) {
|
||||||
tenantDbName = rootProject.getProperty("dbName")
|
tenantDbName = rootProject.getProperty("dbName")
|
||||||
@@ -339,7 +331,7 @@ task migrateTenantDB<<{
|
|||||||
task showTenantDBInfo<<{
|
task showTenantDBInfo<<{
|
||||||
description="Shows the migration info for a Tenant DB. Optionally can pass dbName. Defaults to 'mifostenant-default' (Example: -PdbName=someTenantDBname)"
|
description="Shows the migration info for a Tenant DB. Optionally can pass dbName. Defaults to 'mifostenant-default' (Example: -PdbName=someTenantDBname)"
|
||||||
|
|
||||||
def filePath = "filesystem:$projectDir" + System.properties['file.separator'] + '..' + System.properties['file.separator'] + 'mifosng-db' + System.properties['file.separator'] + 'migrations/core_db'
|
def filePath = "filesystem:$projectDir" + '/src/main/resources/sql/migrations/core_db'
|
||||||
def tenantDbName = 'mifostenant-default';
|
def tenantDbName = 'mifostenant-default';
|
||||||
if (rootProject.hasProperty("dbName")) {
|
if (rootProject.hasProperty("dbName")) {
|
||||||
tenantDbName = rootProject.getProperty("dbName")
|
tenantDbName = rootProject.getProperty("dbName")
|
||||||
@@ -354,7 +346,7 @@ task showTenantDBInfo<<{
|
|||||||
task migrateTenantListDB<<{
|
task migrateTenantListDB<<{
|
||||||
description="Migrates a Tenant List DB. Optionally can pass dbName. Defaults to 'mifosplatform-tenants' (Example: -PdbName=someDBname)"
|
description="Migrates a Tenant List DB. Optionally can pass dbName. Defaults to 'mifosplatform-tenants' (Example: -PdbName=someDBname)"
|
||||||
|
|
||||||
def filePath = "filesystem:$projectDir" + System.properties['file.separator'] + '..' + System.properties['file.separator'] + 'mifosng-db' + System.properties['file.separator'] + 'migrations/list_db'
|
def filePath = "filesystem:$projectDir" + '/src/main/resources/sql/migrations/list_db'
|
||||||
def tenantsDbName = 'mifosplatform-tenants';
|
def tenantsDbName = 'mifosplatform-tenants';
|
||||||
if (rootProject.hasProperty("dbName")) {
|
if (rootProject.hasProperty("dbName")) {
|
||||||
tenantsDbName = rootProject.getProperty("dbName")
|
tenantsDbName = rootProject.getProperty("dbName")
|
||||||
@@ -369,7 +361,7 @@ task migrateTenantListDB<<{
|
|||||||
task showTenantListDBInfo<<{
|
task showTenantListDBInfo<<{
|
||||||
description="Shows the migration info for a List DB. Optionally can pass dbName. Defaults to 'mifosplatform-tenants' (Example: -PdbName=someDBname)"
|
description="Shows the migration info for a List DB. Optionally can pass dbName. Defaults to 'mifosplatform-tenants' (Example: -PdbName=someDBname)"
|
||||||
|
|
||||||
def filePath = "filesystem:$projectDir" + System.properties['file.separator'] + '..' + System.properties['file.separator'] + 'mifosng-db' + System.properties['file.separator'] + 'migrations/list_db'
|
def filePath = "filesystem:$projectDir" + '/src/main/resources/sql/migrations/list_db'
|
||||||
def tenantsDbName = 'mifosplatform-tenants';
|
def tenantsDbName = 'mifosplatform-tenants';
|
||||||
if (rootProject.hasProperty("dbName")) {
|
if (rootProject.hasProperty("dbName")) {
|
||||||
tenantsDbName = rootProject.getProperty("dbName")
|
tenantsDbName = rootProject.getProperty("dbName")
|
||||||
@@ -383,7 +375,7 @@ task showTenantListDBInfo<<{
|
|||||||
task repairTenantDB<<{
|
task repairTenantDB<<{
|
||||||
description="repair migrate"
|
description="repair migrate"
|
||||||
|
|
||||||
def filePath = "filesystem:$projectDir" + System.properties['file.separator'] + '..' + System.properties['file.separator'] + 'mifosng-db' + System.properties['file.separator'] + 'migrations/list_db'
|
def filePath = "filesystem:$projectDir" + '/src/main/resources/sql/migrations/list_db'
|
||||||
def tenantsDbName = 'mifosplatform-tenants';
|
def tenantsDbName = 'mifosplatform-tenants';
|
||||||
if (rootProject.hasProperty("dbName")) {
|
if (rootProject.hasProperty("dbName")) {
|
||||||
tenantsDbName = rootProject.getProperty("dbName")
|
tenantsDbName = rootProject.getProperty("dbName")
|
||||||
@@ -412,3 +404,9 @@ def qualifyVersionIfNecessary(version) {
|
|||||||
return version
|
return version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
springBoot {
|
||||||
|
mainClass = 'org.mifosplatform.ServerWithMariaDB4jApplication'
|
||||||
|
}
|
||||||
|
bootRepackage {
|
||||||
|
mainClass = 'org.mifosplatform.ServerWithMariaDB4jApplication'
|
||||||
|
}
|
||||||
+6
-1
@@ -23,6 +23,11 @@ import com.jayway.restassured.path.json.JsonPath;
|
|||||||
import com.jayway.restassured.specification.RequestSpecification;
|
import com.jayway.restassured.specification.RequestSpecification;
|
||||||
import com.jayway.restassured.specification.ResponseSpecification;
|
import com.jayway.restassured.specification.ResponseSpecification;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Util for RestAssured tests.
|
||||||
|
* This class here in src/integrationTest is copy/pasted to src/test; please keep them in sync.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
@@ -33,7 +38,7 @@ public class Utils {
|
|||||||
public static void initializeRESTAssured() {
|
public static void initializeRESTAssured() {
|
||||||
RestAssured.baseURI = "https://localhost";
|
RestAssured.baseURI = "https://localhost";
|
||||||
RestAssured.port = 8443;
|
RestAssured.port = 8443;
|
||||||
RestAssured.keystore("../keystore.jks", "openmf");
|
RestAssured.keystore("src/main/resources/keystore.jks", "openmf");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String loginIntoServerAndGetBase64EncodedAuthenticationKey() {
|
public static String loginIntoServerAndGetBase64EncodedAuthenticationKey() {
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.AbstractApplicationConfiguration;
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.ApplicationExitUtil;
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.EmbeddedTomcatWithSSLConfiguration;
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.db.DataSourceConfiguration;
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.db.DataSourceProperties;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mifos main() application which launches Mifos X in an embedded Tomcat HTTP
|
||||||
|
* (using Spring Boot).
|
||||||
|
*
|
||||||
|
* The DataSource used is a to a "normal" external database (not use MariaDB4j).
|
||||||
|
* This DataSource can be configured with parameters, see {@link DataSourceProperties}.
|
||||||
|
*
|
||||||
|
* You can easily launch this via Debug as Java Application in your IDE -
|
||||||
|
* without needing command line Gradle stuff, no need to build and deploy a WAR,
|
||||||
|
* remote attachment etc.
|
||||||
|
*
|
||||||
|
* It's the old/classic Mifos (non-X) Workspace 2.0 reborn for Mifos X! ;-)
|
||||||
|
*
|
||||||
|
* @see DataSourceProperties about how to configure the DataSource used
|
||||||
|
* @see ServerWithMariaDB4jApplication for an alternative with an embedded DB
|
||||||
|
*/
|
||||||
|
public class ServerApplication {
|
||||||
|
|
||||||
|
@Import({ DataSourceConfiguration.class, EmbeddedTomcatWithSSLConfiguration.class })
|
||||||
|
private static class Configuration extends AbstractApplicationConfiguration { }
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ConfigurableApplicationContext ctx = SpringApplication.run(Configuration.class, args);
|
||||||
|
ApplicationExitUtil.waitForKeyPressToCleanlyExit(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.AbstractApplicationConfiguration;
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.ApplicationExitUtil;
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.EmbeddedTomcatWithSSLConfiguration;
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.db.MariaDB4jDataSourceConfiguration;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mifos main() application which launches Mifos X in an embedded Tomcat HTTP
|
||||||
|
* server (using Spring Boot), as well as an embedded database (using
|
||||||
|
* MariaDB4j).
|
||||||
|
*
|
||||||
|
* You can easily launch this via Debug as Java Application in your IDE -
|
||||||
|
* without needing command line Gradle stuff, no need to build and deploy a WAR,
|
||||||
|
* remote attachment etc.
|
||||||
|
*
|
||||||
|
* It's the old/classic Mifos (non-X) Workspace 2.0 reborn for Mifos X! ;-)
|
||||||
|
*
|
||||||
|
* @see ServerApplication for the same without the embedded MariaDB4j database
|
||||||
|
*/
|
||||||
|
public class ServerWithMariaDB4jApplication {
|
||||||
|
|
||||||
|
@Import({ MariaDB4jDataSourceConfiguration.class, EmbeddedTomcatWithSSLConfiguration.class })
|
||||||
|
public static class Configuration extends AbstractApplicationConfiguration { }
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ConfigurableApplicationContext ctx = SpringApplication.run(Configuration.class, args);
|
||||||
|
ApplicationExitUtil.waitForKeyPressToCleanlyExit(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.context.annotation.ImportResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Spring Configuration with what's common to all Configuration subclasses.
|
||||||
|
*
|
||||||
|
* Notably the EnableAutoConfiguration excludes relevant for (and often adjusted
|
||||||
|
* when upgrading versions of) Spring Boot, the "old" (pre. Spring Boot &
|
||||||
|
* MariaDB4j) Mifos X appContext.xml which all configurations need, and the
|
||||||
|
* web.xml successor WebXmlConfiguration.
|
||||||
|
*
|
||||||
|
* Should NOT include Configuration related to embedded Tomcat, data sources,
|
||||||
|
* and MariaDB4j (because those differ in the subclasses).
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Import({ WebXmlConfiguration.class })
|
||||||
|
@ImportResource({ "classpath*:META-INF/spring/appContext.xml" })
|
||||||
|
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,
|
||||||
|
HibernateJpaAutoConfiguration.class,
|
||||||
|
DataSourceTransactionManagerAutoConfiguration.class,
|
||||||
|
FlywayAutoConfiguration.class })
|
||||||
|
public abstract class AbstractApplicationConfiguration {
|
||||||
|
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
|
public abstract class ApplicationExitUtil {
|
||||||
|
|
||||||
|
private ApplicationExitUtil() {}
|
||||||
|
|
||||||
|
public static void waitForKeyPressToCleanlyExit(ConfigurableApplicationContext ctx) throws IOException {
|
||||||
|
|
||||||
|
// NOTE: In Eclipse, the Shutdown Hooks are not invoked on exit (red
|
||||||
|
// button).. In the case of MariaDB4j that's a problem because then the
|
||||||
|
// mysqld won't be stopped, so:
|
||||||
|
// (@see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38016)
|
||||||
|
System.out.println("\nHit Enter to quit...");
|
||||||
|
// NOTE: In Eclipse, System.console() is not available.. so:
|
||||||
|
// (@see https://bugs.eclipse.org/bugs/show_bug.cgi?id=122429)
|
||||||
|
BufferedReader d = new BufferedReader(new InputStreamReader(System.in));
|
||||||
|
d.readLine();
|
||||||
|
|
||||||
|
ctx.stop();
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.apache.catalina.connector.Connector;
|
||||||
|
import org.apache.commons.io.FileUtils;
|
||||||
|
import org.apache.coyote.http11.Http11NioProtocol;
|
||||||
|
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||||
|
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class EmbeddedTomcatWithSSLConfiguration {
|
||||||
|
|
||||||
|
// http://docs.spring.io/spring-boot/docs/1.1.5.RELEASE/reference/htmlsingle/#howto-enable-multiple-connectors-in-tomcat
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public EmbeddedServletContainerFactory servletContainer() {
|
||||||
|
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
|
||||||
|
tomcat.setContextPath(getContextPath());
|
||||||
|
tomcat.addAdditionalTomcatConnectors(createSslConnector());
|
||||||
|
return tomcat;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getContextPath() {
|
||||||
|
return "/mifosng-provider";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Connector createSslConnector() {
|
||||||
|
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
|
||||||
|
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
|
||||||
|
try {
|
||||||
|
File keystore = getFile(getKeystore());
|
||||||
|
File truststore = keystore;
|
||||||
|
connector.setScheme("https");
|
||||||
|
connector.setSecure(true);
|
||||||
|
connector.setPort(getHTTPSPort());
|
||||||
|
protocol.setSSLEnabled(true);
|
||||||
|
protocol.setKeystoreFile(keystore.getAbsolutePath());
|
||||||
|
protocol.setKeystorePass(getKeystorePass());
|
||||||
|
protocol.setTruststoreFile(truststore.getAbsolutePath());
|
||||||
|
protocol.setTruststorePass(getKeystorePass());
|
||||||
|
// ? protocol.setKeyAlias("apitester");
|
||||||
|
return connector;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new IllegalStateException("can't access keystore: [" + "keystore" + "] or truststore: [" + "keystore" + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getHTTPSPort() {
|
||||||
|
// TODO This shouldn't be hard-coded here, but configurable
|
||||||
|
return 8443;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getKeystorePass() {
|
||||||
|
return "openmf";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Resource getKeystore() {
|
||||||
|
return new ClassPathResource("/keystore.jks");
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getFile(Resource resource) throws IOException {
|
||||||
|
try {
|
||||||
|
return resource.getFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Uops.. OK, try again (below)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
URL url = resource.getURL();
|
||||||
|
// If this creates filenames that are too long on Win,
|
||||||
|
// then could just use resource.getFilename(),
|
||||||
|
// even though not unique, real risk prob. min.bon
|
||||||
|
String tempDir = System.getProperty("java.io.tmpdir");
|
||||||
|
tempDir = tempDir + "/" + getClass().getSimpleName() + "/";
|
||||||
|
String path = url.getPath();
|
||||||
|
String uniqName = path.replace("file:/", "").replace('!', '_');
|
||||||
|
String tempFullPath = tempDir + uniqName;
|
||||||
|
// instead of File.createTempFile(prefix?, suffix?);
|
||||||
|
File targetFile = new File(tempFullPath);
|
||||||
|
long len = resource.contentLength();
|
||||||
|
if (!targetFile.exists() || targetFile.length() != len) { // Only copy new files
|
||||||
|
FileUtils.copyURLToFile(url, targetFile);
|
||||||
|
}
|
||||||
|
return targetFile;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Uops.. erm, give up:
|
||||||
|
throw new IOException("Cannot obtain a File for Resource: "
|
||||||
|
+ resource.toString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot;
|
||||||
|
|
||||||
|
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||||
|
import org.springframework.boot.context.web.SpringBootServletInitializer;
|
||||||
|
import org.springframework.context.annotation.ImportResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required to still have a working legacy "classic" WAR.
|
||||||
|
*
|
||||||
|
* Configuration just adds the JNDI-based DataSource lookup to its
|
||||||
|
* AbstractApplicationConfiguration.
|
||||||
|
*
|
||||||
|
* This (intentionally) only configures the original (pre-Spring Boot &
|
||||||
|
* MariaDB4j) Mifos X Spring Beans, and does NOT include the embedded Tomcat
|
||||||
|
* (incl. TomcatSSLConfiguration) nor the MariaDB4jSetupService or
|
||||||
|
* MariaDB4jDataSourceConfiguration, and not even the DataSourceConfiguration
|
||||||
|
* (as it uses "classic" JNDI) - we want the WAR to "work like before".
|
||||||
|
*
|
||||||
|
* @see <a
|
||||||
|
* href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-convert-an-existing-application-to-spring-boot">#howto-convert-an-existing-application-to-spring-boot</a>
|
||||||
|
*/
|
||||||
|
public class WarWebApplicationInitializer extends SpringBootServletInitializer {
|
||||||
|
|
||||||
|
@ImportResource({ "classpath*:META-INF/spring/jndi.xml" })
|
||||||
|
private static class Configuration extends AbstractApplicationConfiguration {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SpringApplicationBuilder configure(
|
||||||
|
SpringApplicationBuilder application) {
|
||||||
|
// let's share Spring Boot Love, so no showBanner(false)
|
||||||
|
return application.sources(Configuration.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot;
|
||||||
|
|
||||||
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.Servlet;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.filters.ResponseCorsFilter;
|
||||||
|
import org.springframework.boot.context.embedded.ServletRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||||
|
|
||||||
|
import com.sun.jersey.spi.spring.container.servlet.SpringServlet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Configuration replaces what formerly was in web.xml.
|
||||||
|
*
|
||||||
|
* @see <a
|
||||||
|
* href="http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-convert-an-existing-application-to-spring-boot">#howto-convert-an-existing-application-to-spring-boot</a>
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class WebXmlConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Filter springSecurityFilterChain() {
|
||||||
|
return new DelegatingFilterProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ServletRegistrationBean jersey() {
|
||||||
|
Servlet jerseyServlet = new SpringServlet();
|
||||||
|
ServletRegistrationBean jerseyServletRegistration = new ServletRegistrationBean();
|
||||||
|
jerseyServletRegistration.setServlet(jerseyServlet);
|
||||||
|
jerseyServletRegistration.addUrlMappings("/api/v1/*");
|
||||||
|
jerseyServletRegistration.setName("jersey-servlet");
|
||||||
|
jerseyServletRegistration.setLoadOnStartup(1);
|
||||||
|
jerseyServletRegistration.addInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
|
||||||
|
jerseyServletRegistration.addInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters",
|
||||||
|
ResponseCorsFilter.class.getName());
|
||||||
|
// debugging for development:
|
||||||
|
// jerseyServletRegistration.addInitParameter("com.sun.jersey.spi.container.ContainerRequestFilters",
|
||||||
|
// LoggingFilter.class.getName());
|
||||||
|
return jerseyServletRegistration;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot.db;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.apache.tomcat.jdbc.pool.PoolConfiguration;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration for a DataSource.
|
||||||
|
* @see DataSourceProperties about how to configure this DS
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class DataSourceConfiguration {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(DataSourceConfiguration.class);
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataSourceProperties dataSourceProperties() {
|
||||||
|
return new DataSourceProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataSource tenantDataSourceJndi() {
|
||||||
|
PoolConfiguration p = getProperties();
|
||||||
|
org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource(p);
|
||||||
|
logger.info("Created new DataSource; url=" + p.getUrl());
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DataSourceProperties getProperties() {
|
||||||
|
return dataSourceProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+146
@@ -0,0 +1,146 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot.db;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
import org.apache.tomcat.jdbc.pool.PoolProperties;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configurable DataSource. Properties have sensible defaults, but end-users can
|
||||||
|
* override those via the Spring Values listed below; i.e. via -D Java System
|
||||||
|
* properties, or main() command line arguments, OS environment variables, from
|
||||||
|
* JNDI, or application.properties (thanks Spring Boot). For example:
|
||||||
|
* -Dmifos.datasource.port=3307.
|
||||||
|
*/
|
||||||
|
// NOT a @Component - we do not want this to picked up by component scan, only explicitly declared in DataSourceConfiguration (if that's active)
|
||||||
|
public class DataSourceProperties extends PoolProperties {
|
||||||
|
|
||||||
|
public final static String PORT = "mifos.datasource.port";
|
||||||
|
public final static String HOST = "mifos.datasource.host";
|
||||||
|
public final static String DB = "mifos.datasource.db";
|
||||||
|
public final static String UID = "mifos.datasource.username";
|
||||||
|
public final static String PWD = "mifos.datasource.password";
|
||||||
|
public final static String PROTOCOL = "mifos.datasource.protocol";
|
||||||
|
public final static String SUBPROTOCOL = "mifos.datasource.subprotocol";
|
||||||
|
|
||||||
|
@Value("${" + PORT + ":3306}")
|
||||||
|
private volatile @NotNull int port;
|
||||||
|
|
||||||
|
@Value("${" + HOST + ":localhost}")
|
||||||
|
private volatile @NotNull String hostname;
|
||||||
|
|
||||||
|
@Value("${" + DB + ":mifosplatform-tenants}")
|
||||||
|
private volatile @NotNull String dbName;
|
||||||
|
|
||||||
|
@Value("${" + UID + ":root}")
|
||||||
|
private volatile @NotNull String username;
|
||||||
|
|
||||||
|
@Value("${" + PWD + ":mysql}")
|
||||||
|
private volatile @NotNull String password;
|
||||||
|
|
||||||
|
@Value("${" + PROTOCOL + ":jdbc}")
|
||||||
|
private volatile @NotNull String jdbcProtocol;
|
||||||
|
|
||||||
|
@Value("${" + SUBPROTOCOL + ":mysql}")
|
||||||
|
private volatile @NotNull String jdbcSubprotocol;
|
||||||
|
|
||||||
|
|
||||||
|
public DataSourceProperties() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// default to save us from re-specifying this; note that it can still be
|
||||||
|
// overridden
|
||||||
|
setDriverClassName(com.mysql.jdbc.Driver.class.getName());
|
||||||
|
|
||||||
|
setMifosDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* as per (some of..) INSTALL.md and
|
||||||
|
* org.mifosplatform.infrastructure.core.service
|
||||||
|
* .TomcatJdbcDataSourcePerTenantService
|
||||||
|
* .createNewDataSourceFor(MifosPlatformTenant)
|
||||||
|
*/
|
||||||
|
protected void setMifosDefaults() {
|
||||||
|
setInitialSize(3);
|
||||||
|
// setMaxIdle(6); -- strange, why?
|
||||||
|
// setMinIdle(3); -- JavaDoc says default is initialSize.. so shouldn't
|
||||||
|
// be needed
|
||||||
|
if (getValidationQuery() == null) setValidationQuery("SELECT 1");
|
||||||
|
setTestOnBorrow(true);
|
||||||
|
setTestOnReturn(true);
|
||||||
|
setTestWhileIdle(true);
|
||||||
|
setTimeBetweenEvictionRunsMillis(30000);
|
||||||
|
setTimeBetweenEvictionRunsMillis(60000);
|
||||||
|
setLogAbandoned(true);
|
||||||
|
setSuspectTimeout(60);
|
||||||
|
|
||||||
|
setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
|
||||||
|
+ "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReport");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUrl(@SuppressWarnings("unused") String url) {
|
||||||
|
throw new UnsupportedOperationException("Use setHost/Port/DB() instead of setURL()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUrl() {
|
||||||
|
String url = super.getUrl();
|
||||||
|
if (StringUtils.hasText(url)) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
return jdbcProtocol + ":" + jdbcSubprotocol + "://" + getHost() + ":" + getPort() + "/" + getDBName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDBName() {
|
||||||
|
return dbName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHost(String hostname) {
|
||||||
|
this.hostname = hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDBName(String dbName) {
|
||||||
|
this.dbName = dbName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return this.username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return this.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot.db;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import ch.vorburger.mariadb4j.springframework.MariaDB4jSpringService;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class MariaDB4jDataSourceConfiguration extends DataSourceConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MariaDB4jSetupService mariaDB4jSetUp() {
|
||||||
|
return new MariaDB4jSetupService(mariaDB4j().getDB());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MariaDB4jSpringService mariaDB4j() {
|
||||||
|
MariaDB4jSpringService mariaDB4jSpringService = new MariaDB4jSpringService();
|
||||||
|
mariaDB4jSpringService.setDefaultBaseDir("build/db/bin");
|
||||||
|
mariaDB4jSpringService.setDefaultDataDir("build/db/data");
|
||||||
|
return mariaDB4jSpringService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// NOT @Bean @Override dataSourceProperties() - doesn't work :(
|
||||||
|
protected DataSourceProperties getProperties() {
|
||||||
|
DataSourceProperties p = super.getProperties();
|
||||||
|
String dbName = mariaDB4jSetUp().getTenantDBName();
|
||||||
|
// Do not use p.setUrl(mariaDB4j().getConfiguration().getURL(dbName));
|
||||||
|
// Because TenantDataSourcePortFixService needs separate
|
||||||
|
// host/port/db/uid/pwd:
|
||||||
|
// (DataSourceProperties getUrl() creates the correct JDBC URL from it)
|
||||||
|
// This intentionally overrides any mifos.datasource.* settings, because
|
||||||
|
// in this configuration, logically the mariaDB4j settings take
|
||||||
|
// precedence:
|
||||||
|
p.setHost("localhost");
|
||||||
|
p.setPort(mariaDB4j().getConfiguration().getPort());
|
||||||
|
p.setDBName(dbName);
|
||||||
|
// TODO p.setUsername(mariaDB4j().getConfiguration().getUsername());
|
||||||
|
// TODO p.setPassword(mariaDB4j().getConfiguration().getPassword());
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot.db;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.PreDestroy;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import ch.vorburger.exec.ManagedProcessException;
|
||||||
|
import ch.vorburger.mariadb4j.DB;
|
||||||
|
|
||||||
|
public class MariaDB4jSetupService {
|
||||||
|
|
||||||
|
private DB db;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public MariaDB4jSetupService(DB db) {
|
||||||
|
this.db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
protected void setUpMifosDBs() throws ManagedProcessException {
|
||||||
|
db.createDB(getTenantDBName());
|
||||||
|
db.createDB("mifostenant-default");
|
||||||
|
// Note that we don't need to initialize the DBs, because
|
||||||
|
// the TenantDatabaseUpgradeService will do this in just a moment.
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTenantDBName() {
|
||||||
|
return "mifosplatform-tenants";
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreDestroy
|
||||||
|
protected void stop() throws ManagedProcessException {
|
||||||
|
db = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+83
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
package org.mifosplatform.infrastructure.core.boot.db;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service which "fixes up" the schemaServerPort in the tenants table of the
|
||||||
|
* mifosplatform-tenants schema. It sets it to the actual current port of
|
||||||
|
* MariaDB4j, instead of the default 3306 which is hard-coded in the initial
|
||||||
|
* set-up SQL script (V1__mifos-platform-shared-tenants.sql).
|
||||||
|
*
|
||||||
|
* This service is called by the TenantDatabaseUpgradeService
|
||||||
|
* "just at the right time" during start-up, that is AFTER the initialization of
|
||||||
|
* the mifosplatform-tenants but BEFORE Flyway runs on all tenant schemas.
|
||||||
|
*
|
||||||
|
* It's difficult to achieve the same goal elsewhere, because we cannot do this
|
||||||
|
* e.g. in MariaDB4jSetupService, as that's too early
|
||||||
|
* (TenantDatabaseUpgradeService has not yet run), nor e.g. in
|
||||||
|
* TomcatJdbcDataSourcePerTenantService because in there we do not have access
|
||||||
|
* to and should not depend on MariaDB4j configuration.
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class TenantDataSourcePortFixService {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(TenantDataSourcePortFixService.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* While what this class does is convenient in 96% you may would like to
|
||||||
|
* completely disable it if you've hand tuned your tenants table for an
|
||||||
|
* advanced configuration and use e.g. different databases maybe on
|
||||||
|
* different hosts for different tenants.
|
||||||
|
*/
|
||||||
|
public final static String ENABLED = "mifos.tenantdb.fixup";
|
||||||
|
@Value("${" + ENABLED + ":true}")
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
// required=false is important here, because in
|
||||||
|
// WebApplicationInitializerConfiguration for classic WAR there
|
||||||
|
// is (intentionally) no MariaDB4j nor a DataSourceProperties
|
||||||
|
// bean (because in the WAR we're using a DS from JNDI)
|
||||||
|
private @Autowired(required = false) DataSourceProperties dsp;
|
||||||
|
|
||||||
|
private JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public TenantDataSourcePortFixService(@Qualifier("tenantDataSourceJndi") final DataSource dataSource) {
|
||||||
|
this.jdbcTemplate = new JdbcTemplate(dataSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fixUpTenantsSchemaServerPort() {
|
||||||
|
if (!enabled) {
|
||||||
|
logger.info("No schema_server_port UPDATE made to tenants table of the mifosplatform-tenants schema, because " + ENABLED + " = false");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (dsp == null) {
|
||||||
|
// we don't have any generic mechanism to know the DB port, given just a tenant DataSource
|
||||||
|
logger.debug("No schema_server_port UPDATE made to tenants table of the mifosplatform-tenants schema (because neither MariaDB4j nor our own Spring Boot DataSourceConfiguration is used in a traditional WAR)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int r = jdbcTemplate
|
||||||
|
.update("UPDATE tenants SET schema_server = ?, schema_server_port = ?, schema_username = ?, schema_password = ?",
|
||||||
|
dsp.getHost(), dsp.getPort(), dsp.getUsername(), dsp.getPassword());
|
||||||
|
if ( r == 0 )
|
||||||
|
logger.warn("UPDATE tenants SET ... did not update ANY rows - something is probably wrong");
|
||||||
|
else
|
||||||
|
logger.info("Upated "
|
||||||
|
+ r
|
||||||
|
+ " rows in the tenants table of the mifosplatform-tenants schema to the real current host: "
|
||||||
|
+ dsp.getHost() + ", port: " + dsp.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+7
-3
@@ -12,18 +12,22 @@ import java.util.Enumeration;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.context.event.ContextStoppedEvent;
|
import org.springframework.context.event.ContextClosedEvent;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.mysql.jdbc.AbandonedConnectionCleanupThread;
|
import com.mysql.jdbc.AbandonedConnectionCleanupThread;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class AbandonedConnectionCleanupShutdownListener implements ApplicationListener<ContextStoppedEvent> {
|
public class AbandonedConnectionCleanupShutdownListener implements ApplicationListener<ContextClosedEvent> {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(AbandonedConnectionCleanupShutdownListener.class);
|
private final static Logger logger = LoggerFactory.getLogger(AbandonedConnectionCleanupShutdownListener.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see JobRegisterServiceImpl#onApplicationEvent(ContextClosedEvent) doc
|
||||||
|
* re. why we use ContextClosedEvent instead of ContextStoppedEvent
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(@SuppressWarnings("unused") ContextStoppedEvent event) {
|
public void onApplicationEvent(@SuppressWarnings("unused") ContextClosedEvent event) {
|
||||||
shutDowncleanUpThreadAndDeregisterJDBCDriver();
|
shutDowncleanUpThreadAndDeregisterJDBCDriver();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+36
-3
@@ -8,13 +8,17 @@ package org.mifosplatform.infrastructure.core.service;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.mifosplatform.infrastructure.core.boot.db.TenantDataSourcePortFixService;
|
||||||
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
|
import org.mifosplatform.infrastructure.core.domain.MifosPlatformTenant;
|
||||||
import org.mifosplatform.infrastructure.security.service.TenantDetailsService;
|
import org.mifosplatform.infrastructure.security.service.TenantDetailsService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.googlecode.flyway.core.Flyway;
|
import com.googlecode.flyway.core.Flyway;
|
||||||
|
import com.googlecode.flyway.core.api.FlywayException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service that picks up on tenants that are configured to auto-update their
|
* A service that picks up on tenants that are configured to auto-update their
|
||||||
@@ -24,23 +28,52 @@ import com.googlecode.flyway.core.Flyway;
|
|||||||
public class TenantDatabaseUpgradeService {
|
public class TenantDatabaseUpgradeService {
|
||||||
|
|
||||||
private final TenantDetailsService tenantDetailsService;
|
private final TenantDetailsService tenantDetailsService;
|
||||||
|
protected final DataSource tenantDataSource;
|
||||||
|
protected final TenantDataSourcePortFixService tenantDataSourcePortFixService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public TenantDatabaseUpgradeService(final TenantDetailsService detailsService) {
|
public TenantDatabaseUpgradeService(
|
||||||
|
final TenantDetailsService detailsService,
|
||||||
|
@Qualifier("tenantDataSourceJndi") final DataSource dataSource,
|
||||||
|
TenantDataSourcePortFixService tenantDataSourcePortFixService)
|
||||||
|
{
|
||||||
this.tenantDetailsService = detailsService;
|
this.tenantDetailsService = detailsService;
|
||||||
|
this.tenantDataSource = dataSource;
|
||||||
|
this.tenantDataSourcePortFixService = tenantDataSourcePortFixService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void upgradeAllTenants() {
|
public void upgradeAllTenants() {
|
||||||
|
upgradeTenantDB();
|
||||||
final List<MifosPlatformTenant> tenants = this.tenantDetailsService.findAllTenants();
|
final List<MifosPlatformTenant> tenants = this.tenantDetailsService.findAllTenants();
|
||||||
for (final MifosPlatformTenant tenant : tenants) {
|
for (final MifosPlatformTenant tenant : tenants) {
|
||||||
if (tenant.isAutoUpdateEnabled()) {
|
if (tenant.isAutoUpdateEnabled()) {
|
||||||
final Flyway flyway = new Flyway();
|
final Flyway flyway = new Flyway();
|
||||||
flyway.setDataSource(tenant.databaseURL(), tenant.getSchemaUsername(), tenant.getSchemaPassword());
|
flyway.setDataSource(tenant.databaseURL(), tenant.getSchemaUsername(), tenant.getSchemaPassword());
|
||||||
flyway.setLocations("sql");
|
flyway.setLocations("sql/migrations/core_db");
|
||||||
flyway.setOutOfOrder(true);
|
flyway.setOutOfOrder(true);
|
||||||
flyway.migrate();
|
try {
|
||||||
|
flyway.migrate();
|
||||||
|
} catch (FlywayException e) {
|
||||||
|
String betterMessage = e.getMessage()
|
||||||
|
+ "; for Tenant DB URL: " + tenant.databaseURL()
|
||||||
|
+ ", username: " + tenant.getSchemaUsername();
|
||||||
|
throw new FlywayException(betterMessage, e.getCause());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes, and if required upgrades (using Flyway) the Tenant DB itself.
|
||||||
|
*/
|
||||||
|
private void upgradeTenantDB() {
|
||||||
|
final Flyway flyway = new Flyway();
|
||||||
|
flyway.setDataSource(tenantDataSource);
|
||||||
|
flyway.setLocations("sql/migrations/list_db");
|
||||||
|
flyway.setOutOfOrder(true);
|
||||||
|
flyway.migrate();
|
||||||
|
|
||||||
|
tenantDataSourcePortFixService.fixUpTenantsSchemaServerPort();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+2
@@ -64,6 +64,8 @@ public class TomcatJdbcDataSourcePerTenantService implements RoutingDataSourceSe
|
|||||||
// see
|
// see
|
||||||
// http://www.tomcatexpert.com/blog/2010/04/01/configuring-jdbc-pool-high-concurrency
|
// http://www.tomcatexpert.com/blog/2010/04/01/configuring-jdbc-pool-high-concurrency
|
||||||
|
|
||||||
|
// see also org.mifosplatform.DataSourceProperties.setMifosDefaults()
|
||||||
|
|
||||||
final String jdbcUrl = tenant.databaseURL();
|
final String jdbcUrl = tenant.databaseURL();
|
||||||
|
|
||||||
final PoolConfiguration poolConfiguration = new PoolProperties();
|
final PoolConfiguration poolConfiguration = new PoolProperties();
|
||||||
|
|||||||
+9
-3
@@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ApplicationListener;
|
import org.springframework.context.ApplicationListener;
|
||||||
import org.springframework.context.event.ContextStoppedEvent;
|
import org.springframework.context.event.ContextClosedEvent;
|
||||||
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
|
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
|
||||||
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
|
import org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean;
|
||||||
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
|
||||||
@@ -48,7 +48,7 @@ import org.springframework.stereotype.Service;
|
|||||||
* {@link CronTriggerFactoryBean}
|
* {@link CronTriggerFactoryBean}
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class JobRegisterServiceImpl implements JobRegisterService, ApplicationListener<ContextStoppedEvent> {
|
public class JobRegisterServiceImpl implements JobRegisterService, ApplicationListener<ContextClosedEvent> {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger(JobRegisterServiceImpl.class);
|
private final static Logger logger = LoggerFactory.getLogger(JobRegisterServiceImpl.class);
|
||||||
|
|
||||||
@@ -230,8 +230,14 @@ public class JobRegisterServiceImpl implements JobRegisterService, ApplicationLi
|
|||||||
return !this.schedularWritePlatformService.retriveSchedulerDetail().isSuspended();
|
return !this.schedularWritePlatformService.retriveSchedulerDetail().isSuspended();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Need to use ContextClosedEvent instead of ContextStoppedEvent because in
|
||||||
|
* case Spring Boot fails to start-up (e.g. because Tomcat port is already
|
||||||
|
* in use) then org.springframework.boot.SpringApplication.run(String...)
|
||||||
|
* does a context.close(); and not a context.stop();
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onApplicationEvent(@SuppressWarnings("unused") ContextStoppedEvent event) {
|
public void onApplicationEvent(@SuppressWarnings("unused") ContextClosedEvent event) {
|
||||||
this.stopAllSchedulers();
|
this.stopAllSchedulers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-5
@@ -28,14 +28,12 @@ public class PlatformRequestLog {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final String url;
|
private final String url;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private final Map<String, String> parameters;
|
private final Map<String, String[]> parameters;
|
||||||
|
|
||||||
public static PlatformRequestLog from(final StopWatch task, final HttpServletRequest request) throws IOException {
|
public static PlatformRequestLog from(final StopWatch task, final HttpServletRequest request) throws IOException {
|
||||||
|
|
||||||
final String requestUrl = request.getRequestURL().toString();
|
final String requestUrl = request.getRequestURL().toString();
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
final Map<String, String[]> parameters = new HashMap<>(request.getParameterMap());
|
||||||
final Map<String, String> parameters = new HashMap<>(request.getParameterMap());
|
|
||||||
parameters.remove("password");
|
parameters.remove("password");
|
||||||
parameters.remove("_");
|
parameters.remove("_");
|
||||||
|
|
||||||
@@ -43,7 +41,7 @@ public class PlatformRequestLog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PlatformRequestLog(final long startTime, final long time, final String method, final String requestUrl,
|
private PlatformRequestLog(final long startTime, final long time, final String method, final String requestUrl,
|
||||||
final Map<String, String> parameters) {
|
final Map<String, String[]> parameters) {
|
||||||
this.startTime = startTime;
|
this.startTime = startTime;
|
||||||
this.totalTime = time;
|
this.totalTime = time;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
|||||||
@@ -45,6 +45,13 @@
|
|||||||
org.mifosplatform.batch">
|
org.mifosplatform.batch">
|
||||||
<context:exclude-filter expression="org.springframework.stereotype.Controller"
|
<context:exclude-filter expression="org.springframework.stereotype.Controller"
|
||||||
type="annotation" />
|
type="annotation" />
|
||||||
|
|
||||||
|
<!-- We do NOT want all @Configuration "beans" to be auto-detected by ComponentScan,
|
||||||
|
but we want to use / import them explicitly in Tests & Spring Boot applications,
|
||||||
|
or other import in other @Configuration, so that we could have mutually exclusive ones.
|
||||||
|
-->
|
||||||
|
<context:exclude-filter expression="org.springframework.context.annotation.Configuration"
|
||||||
|
type="annotation" />
|
||||||
</context:component-scan>
|
</context:component-scan>
|
||||||
|
|
||||||
<bean id="auditorAware"
|
<bean id="auditorAware"
|
||||||
@@ -63,9 +70,8 @@
|
|||||||
|
|
||||||
<import resource="infrastructure.xml" />
|
<import resource="infrastructure.xml" />
|
||||||
|
|
||||||
<!-- do NOT <import resource="jndi.xml" /> here;
|
<!-- do NOT <import resource="jndi.xml" /> here anymore;
|
||||||
because we want the TestDataSourceConfiguration to not have that;
|
we'll manually import jndi.xml where we still need it (MifosServletWebApplicationInitializerConfiguration)
|
||||||
we'll manually list jndi.xml in web.xml
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<import resource="securityContext.xml" />
|
<import resource="securityContext.xml" />
|
||||||
|
|||||||
-1
@@ -24,4 +24,3 @@ INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `c
|
|||||||
INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`, `task_priority`, `group_name`, `previous_run_start_time`, `next_run_time`, `job_key`, `initializing_errorlog`, `is_active`, `currently_running`, `updates_allowed`, `scheduler_group`, `is_misfired`) VALUES ('Transfer Fee For Loans From Savings', 'Transfer Fee For Loans From Savings', '0 1 0 1/1 * ? *', now(), 5, NULL, NULL, NULL, NULL, NULL, 1, 0, 1, 0, 0);
|
INSERT INTO `job` (`name`, `display_name`, `cron_expression`, `create_time`, `task_priority`, `group_name`, `previous_run_start_time`, `next_run_time`, `job_key`, `initializing_errorlog`, `is_active`, `currently_running`, `updates_allowed`, `scheduler_group`, `is_misfired`) VALUES ('Transfer Fee For Loans From Savings', 'Transfer Fee For Loans From Savings', '0 1 0 1/1 * ? *', now(), 5, NULL, NULL, NULL, NULL, NULL, 1, 0, 1, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-1
@@ -4,4 +4,3 @@ VALUES ('portfolio', 'PROPOSEANDACCEPTTRANSFER_CLIENT', 'CLIENT', 'PROPOSEANDACC
|
|||||||
|
|
||||||
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
INSERT INTO `m_permission` (`grouping`, `code`, `entity_name`, `action_name`, `can_maker_checker`)
|
||||||
VALUES ('portfolio', 'PROPOSEANDACCEPTTRANSFER_CLIENT_CHECKER', 'CLIENT', 'PROPOSEANDACCEPTTRANSFER', 0);
|
VALUES ('portfolio', 'PROPOSEANDACCEPTTRANSFER_CLIENT_CHECKER', 'CLIENT', 'PROPOSEANDACCEPTTRANSFER', 0);
|
||||||
|
|
||||||
+64
-64
@@ -44,41 +44,41 @@ begin
|
|||||||
|
|
||||||
open cursor1;
|
open cursor1;
|
||||||
LOOP1: loop
|
LOOP1: loop
|
||||||
fetch cursor1 into v_currency_code, v_withdrawal_fee_type_enum, v_withdrawal_fee_amount_charge_def;
|
fetch cursor1 into v_currency_code, v_withdrawal_fee_type_enum, v_withdrawal_fee_amount_charge_def;
|
||||||
if no_more_rows then
|
if no_more_rows then
|
||||||
close cursor1;
|
close cursor1;
|
||||||
leave LOOP1;
|
leave LOOP1;
|
||||||
end if;
|
end if;
|
||||||
-- set withdrawal fee name
|
-- set withdrawal fee name
|
||||||
if(v_withdrawal_fee_type_enum = 1) then
|
if(v_withdrawal_fee_type_enum = 1) then
|
||||||
set t_withdrawal_fee_name = CONCAT('Withdrawal fee-Flat-',v_currency_code);
|
set t_withdrawal_fee_name = CONCAT('Withdrawal fee-Flat-',v_currency_code);
|
||||||
else
|
else
|
||||||
set t_withdrawal_fee_name = CONCAT('Withdrawal fee-Percentage-',v_currency_code);
|
set t_withdrawal_fee_name = CONCAT('Withdrawal fee-Percentage-',v_currency_code);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- get charge id if already exists
|
-- get charge id if already exists
|
||||||
set t_charge_id = (select id from m_charge where name = t_withdrawal_fee_name);
|
set t_charge_id = (select id from m_charge where name = t_withdrawal_fee_name);
|
||||||
|
|
||||||
if t_charge_id is null then
|
if t_charge_id is null then
|
||||||
-- add withdrawal fee to charges
|
-- add withdrawal fee to charges
|
||||||
INSERT INTO `m_charge` (`name`, `currency_code`, `charge_applies_to_enum`, `charge_time_enum`, `charge_calculation_enum`, `charge_payment_mode_enum`, `amount`, `is_penalty`, `is_active`, `is_deleted`) VALUES (t_withdrawal_fee_name , v_currency_code, 2, 5, v_withdrawal_fee_type_enum, 0, v_withdrawal_fee_amount_charge_def, 0, 1, 0);
|
INSERT INTO `m_charge` (`name`, `currency_code`, `charge_applies_to_enum`, `charge_time_enum`, `charge_calculation_enum`, `charge_payment_mode_enum`, `amount`, `is_penalty`, `is_active`, `is_deleted`) VALUES (t_withdrawal_fee_name , v_currency_code, 2, 5, v_withdrawal_fee_type_enum, 0, v_withdrawal_fee_amount_charge_def, 0, 1, 0);
|
||||||
|
|
||||||
-- get inserted charge id
|
-- get inserted charge id
|
||||||
set t_charge_id = last_insert_id();
|
set t_charge_id = last_insert_id();
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
open cursor2;
|
open cursor2;
|
||||||
LOOP2: loop
|
LOOP2: loop
|
||||||
fetch cursor2 into v_account_id, v_withdrawal_fee_amount;
|
fetch cursor2 into v_account_id, v_withdrawal_fee_amount;
|
||||||
if no_more_rows then
|
if no_more_rows then
|
||||||
set no_more_rows := false;
|
set no_more_rows := false;
|
||||||
close cursor2;
|
close cursor2;
|
||||||
leave LOOP2;
|
leave LOOP2;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if (v_withdrawal_fee_type_enum=1) then
|
if (v_withdrawal_fee_type_enum=1) then
|
||||||
set t_calculation_percentage = NULL;
|
set t_calculation_percentage = NULL;
|
||||||
set t_calculation_on_amount = NULL;
|
set t_calculation_on_amount = NULL;
|
||||||
else
|
else
|
||||||
set t_calculation_percentage = v_withdrawal_fee_amount;
|
set t_calculation_percentage = v_withdrawal_fee_amount;
|
||||||
set v_withdrawal_fee_amount = 0;
|
set v_withdrawal_fee_amount = 0;
|
||||||
@@ -86,7 +86,7 @@ begin
|
|||||||
end if;
|
end if;
|
||||||
|
|
||||||
if not exists (select id from m_savings_account_charge sac where
|
if not exists (select id from m_savings_account_charge sac where
|
||||||
sac.savings_account_id=v_account_id and sac.charge_id=t_charge_id and sac.charge_time_enum=5) then
|
sac.savings_account_id=v_account_id and sac.charge_id=t_charge_id and sac.charge_time_enum=5) then
|
||||||
|
|
||||||
-- attach withdrawal charge to savings
|
-- attach withdrawal charge to savings
|
||||||
INSERT INTO `m_savings_account_charge` (`savings_account_id`, `charge_id`, `is_penalty`, `charge_time_enum`, `charge_due_date`, `fee_on_month`, `fee_on_day`, `charge_calculation_enum`, `calculation_percentage`, `calculation_on_amount`, `amount`, `amount_paid_derived`, `amount_waived_derived`, `amount_writtenoff_derived`, `amount_outstanding_derived`, `is_paid_derived`, `waived`, `is_active`) VALUES (v_account_id, t_charge_id, 0, 5, NULL, NULL, NULL, v_withdrawal_fee_type_enum, t_calculation_percentage, t_calculation_on_amount, v_withdrawal_fee_amount, NULL, NULL, NULL, 0.000000, 0, 0, 1);
|
INSERT INTO `m_savings_account_charge` (`savings_account_id`, `charge_id`, `is_penalty`, `charge_time_enum`, `charge_due_date`, `fee_on_month`, `fee_on_day`, `charge_calculation_enum`, `calculation_percentage`, `calculation_on_amount`, `amount`, `amount_paid_derived`, `amount_waived_derived`, `amount_writtenoff_derived`, `amount_outstanding_derived`, `is_paid_derived`, `waived`, `is_active`) VALUES (v_account_id, t_charge_id, 0, 5, NULL, NULL, NULL, v_withdrawal_fee_type_enum, t_calculation_percentage, t_calculation_on_amount, v_withdrawal_fee_amount, NULL, NULL, NULL, 0.000000, 0, 0, 1);
|
||||||
@@ -96,23 +96,23 @@ begin
|
|||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
set t_savings_charge_id = (select id from m_savings_account_charge sac where sac.savings_account_id=v_account_id and sac.charge_id=t_charge_id and sac.charge_time_enum=5);
|
set t_savings_charge_id = (select id from m_savings_account_charge sac where sac.savings_account_id=v_account_id and sac.charge_id=t_charge_id and sac.charge_time_enum=5);
|
||||||
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
|
|
||||||
open cursor3;
|
open cursor3;
|
||||||
LOOP3: loop
|
LOOP3: loop
|
||||||
fetch cursor3 into v_savings_transaction_id, v_transaction_amount;
|
fetch cursor3 into v_savings_transaction_id, v_transaction_amount;
|
||||||
|
|
||||||
if no_more_rows then
|
if no_more_rows then
|
||||||
set no_more_rows := false;
|
set no_more_rows := false;
|
||||||
close cursor3;
|
close cursor3;
|
||||||
leave LOOP3;
|
leave LOOP3;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if not exists (select id from m_savings_account_charge_paid_by sacp where
|
if not exists (select id from m_savings_account_charge_paid_by sacp where
|
||||||
sacp.savings_account_transaction_id=v_savings_transaction_id and sacp.savings_account_charge_id=t_savings_charge_id) then
|
sacp.savings_account_transaction_id=v_savings_transaction_id and sacp.savings_account_charge_id=t_savings_charge_id) then
|
||||||
|
|
||||||
-- insert a record into savings account charge paid by
|
-- insert a record into savings account charge paid by
|
||||||
INSERT INTO `m_savings_account_charge_paid_by` (`savings_account_transaction_id`, `savings_account_charge_id`, `amount`) VALUES(v_savings_transaction_id, t_savings_charge_id, v_transaction_amount);
|
INSERT INTO `m_savings_account_charge_paid_by` (`savings_account_transaction_id`, `savings_account_charge_id`, `amount`) VALUES(v_savings_transaction_id, t_savings_charge_id, v_transaction_amount);
|
||||||
@@ -159,41 +159,41 @@ begin
|
|||||||
|
|
||||||
open cursor1;
|
open cursor1;
|
||||||
LOOP1: loop
|
LOOP1: loop
|
||||||
fetch cursor1 into v_currency_code, v_annual_fee_amount_charge_def;
|
fetch cursor1 into v_currency_code, v_annual_fee_amount_charge_def;
|
||||||
|
|
||||||
if no_more_rows then
|
if no_more_rows then
|
||||||
close cursor1;
|
close cursor1;
|
||||||
leave LOOP1;
|
leave LOOP1;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- set annual fee name
|
-- set annual fee name
|
||||||
set t_annual_fee_name = CONCAT('Annual fee - ',v_currency_code);
|
set t_annual_fee_name = CONCAT('Annual fee - ',v_currency_code);
|
||||||
|
|
||||||
-- get charge id if already exists
|
-- get charge id if already exists
|
||||||
set t_charge_id = (select id from m_charge where name = t_annual_fee_name);
|
set t_charge_id = (select id from m_charge where name = t_annual_fee_name);
|
||||||
|
|
||||||
if t_charge_id is null then
|
if t_charge_id is null then
|
||||||
|
|
||||||
-- add annual fee to charges
|
-- add annual fee to charges
|
||||||
INSERT INTO `m_charge` (`name`, `currency_code`, `charge_applies_to_enum`, `charge_time_enum`, `charge_calculation_enum`, `charge_payment_mode_enum`, `amount`, `is_penalty`, `is_active`, `is_deleted`) VALUES (t_annual_fee_name, v_currency_code, 2, 6, 1, 0, v_annual_fee_amount_charge_def, 0, 1, 0);
|
INSERT INTO `m_charge` (`name`, `currency_code`, `charge_applies_to_enum`, `charge_time_enum`, `charge_calculation_enum`, `charge_payment_mode_enum`, `amount`, `is_penalty`, `is_active`, `is_deleted`) VALUES (t_annual_fee_name, v_currency_code, 2, 6, 1, 0, v_annual_fee_amount_charge_def, 0, 1, 0);
|
||||||
|
|
||||||
-- get inserted charge id
|
-- get inserted charge id
|
||||||
set t_charge_id = last_insert_id();
|
set t_charge_id = last_insert_id();
|
||||||
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
open cursor2;
|
open cursor2;
|
||||||
LOOP2: loop
|
LOOP2: loop
|
||||||
fetch cursor2 into v_account_id, v_annual_fee_amount, v_annual_fee_on_month, v_annual_fee_on_day, v_annual_fee_next_due_date;
|
fetch cursor2 into v_account_id, v_annual_fee_amount, v_annual_fee_on_month, v_annual_fee_on_day, v_annual_fee_next_due_date;
|
||||||
|
|
||||||
if no_more_rows then
|
if no_more_rows then
|
||||||
set no_more_rows := false;
|
set no_more_rows := false;
|
||||||
close cursor2;
|
close cursor2;
|
||||||
leave LOOP2;
|
leave LOOP2;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if not exists (select id from m_savings_account_charge sac where
|
if not exists (select id from m_savings_account_charge sac where
|
||||||
sac.savings_account_id=v_account_id and sac.charge_id=t_charge_id and sac.charge_time_enum=6) then
|
sac.savings_account_id=v_account_id and sac.charge_id=t_charge_id and sac.charge_time_enum=6) then
|
||||||
|
|
||||||
-- attach annual charge to savings
|
-- attach annual charge to savings
|
||||||
INSERT INTO `m_savings_account_charge` (`savings_account_id`, `charge_id`, `is_penalty`, `charge_time_enum`, `charge_due_date`, `fee_on_month`, `fee_on_day`, `charge_calculation_enum`, `calculation_percentage`, `calculation_on_amount`, `amount`, `amount_paid_derived`, `amount_waived_derived`, `amount_writtenoff_derived`, `amount_outstanding_derived`, `is_paid_derived`, `waived`, `is_active`) VALUES (v_account_id, t_charge_id, 0, 6, v_annual_fee_next_due_date, v_annual_fee_on_month, v_annual_fee_on_day, 1, NULL, NULL, v_annual_fee_amount, NULL, NULL, NULL, v_annual_fee_amount, 0, 0, 1);
|
INSERT INTO `m_savings_account_charge` (`savings_account_id`, `charge_id`, `is_penalty`, `charge_time_enum`, `charge_due_date`, `fee_on_month`, `fee_on_day`, `charge_calculation_enum`, `calculation_percentage`, `calculation_on_amount`, `amount`, `amount_paid_derived`, `amount_waived_derived`, `amount_writtenoff_derived`, `amount_outstanding_derived`, `is_paid_derived`, `waived`, `is_active`) VALUES (v_account_id, t_charge_id, 0, 6, v_annual_fee_next_due_date, v_annual_fee_on_month, v_annual_fee_on_day, 1, NULL, NULL, v_annual_fee_amount, NULL, NULL, NULL, v_annual_fee_amount, 0, 0, 1);
|
||||||
@@ -203,22 +203,22 @@ begin
|
|||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
set t_savings_charge_id = (select id from m_savings_account_charge sac where sac.savings_account_id=v_account_id and sac.charge_id=t_charge_id and sac.charge_time_enum=6);
|
set t_savings_charge_id = (select id from m_savings_account_charge sac where sac.savings_account_id=v_account_id and sac.charge_id=t_charge_id and sac.charge_time_enum=6);
|
||||||
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
open cursor3;
|
open cursor3;
|
||||||
LOOP3: loop
|
LOOP3: loop
|
||||||
fetch cursor3 into v_savings_transaction_id, v_transaction_amount;
|
fetch cursor3 into v_savings_transaction_id, v_transaction_amount;
|
||||||
|
|
||||||
if no_more_rows then
|
if no_more_rows then
|
||||||
set no_more_rows := false;
|
set no_more_rows := false;
|
||||||
close cursor3;
|
close cursor3;
|
||||||
leave LOOP3;
|
leave LOOP3;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
if not exists (select id from m_savings_account_charge_paid_by sacp where
|
if not exists (select id from m_savings_account_charge_paid_by sacp where
|
||||||
sacp.savings_account_transaction_id=v_savings_transaction_id and sacp.savings_account_charge_id=t_savings_charge_id) then
|
sacp.savings_account_transaction_id=v_savings_transaction_id and sacp.savings_account_charge_id=t_savings_charge_id) then
|
||||||
|
|
||||||
-- insert a record into savings account charge paid by
|
-- insert a record into savings account charge paid by
|
||||||
INSERT INTO `m_savings_account_charge_paid_by` (`savings_account_transaction_id`, `savings_account_charge_id`, `amount`) VALUES(v_savings_transaction_id, t_savings_charge_id, v_transaction_amount);
|
INSERT INTO `m_savings_account_charge_paid_by` (`savings_account_transaction_id`, `savings_account_charge_id`, `amount`) VALUES(v_savings_transaction_id, t_savings_charge_id, v_transaction_amount);
|
||||||
-3
@@ -22,6 +22,3 @@ Update loan transaction to add a link to transaction detail table
|
|||||||
ALTER TABLE `m_loan_transaction`
|
ALTER TABLE `m_loan_transaction`
|
||||||
ADD COLUMN `payment_detail_id` BIGINT(20) NULL AFTER `loan_id`,
|
ADD COLUMN `payment_detail_id` BIGINT(20) NULL AFTER `loan_id`,
|
||||||
ADD CONSTRAINT `FK_m_loan_transaction_m_payment_detail` FOREIGN KEY (`payment_detail_id`) REFERENCES `m_payment_detail` (`id`);
|
ADD CONSTRAINT `FK_m_loan_transaction_m_payment_detail` FOREIGN KEY (`payment_detail_id`) REFERENCES `m_payment_detail` (`id`);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-1
@@ -5,4 +5,3 @@ ADD COLUMN `max_cap` DECIMAL(19,6) NULL AFTER `min_cap`;
|
|||||||
ALTER TABLE `m_loan_charge`
|
ALTER TABLE `m_loan_charge`
|
||||||
ADD COLUMN `min_cap` DECIMAL(19,6) NULL AFTER `waived`,
|
ADD COLUMN `min_cap` DECIMAL(19,6) NULL AFTER `waived`,
|
||||||
ADD COLUMN `max_cap` DECIMAL(19,6) NULL AFTER `min_cap`;
|
ADD COLUMN `max_cap` DECIMAL(19,6) NULL AFTER `min_cap`;
|
||||||
|
|
||||||
-2
@@ -24,5 +24,3 @@ ALTER TABLE m_client
|
|||||||
|
|
||||||
ALTER TABLE m_group
|
ALTER TABLE m_group
|
||||||
ADD COLUMN `status_id` INT(5) NOT NULL DEFAULT 300 AFTER `is_deleted` ;
|
ADD COLUMN `status_id` INT(5) NOT NULL DEFAULT 300 AFTER `is_deleted` ;
|
||||||
|
|
||||||
|
|
||||||
-1
@@ -7,4 +7,3 @@ ALTER TABLE `acc_gl_journal_entry`
|
|||||||
UPDATE acc_gl_journal_entry je SET je.savings_transaction_id=je.transaction_id,je.transaction_id=Concat('S',je.transaction_id) WHERE je.entity_type_enum=2;
|
UPDATE acc_gl_journal_entry je SET je.savings_transaction_id=je.transaction_id,je.transaction_id=Concat('S',je.transaction_id) WHERE je.entity_type_enum=2;
|
||||||
|
|
||||||
UPDATE acc_gl_journal_entry je SET je.loan_transaction_id=je.transaction_id,je.transaction_id=Concat('L',je.transaction_id) WHERE je.entity_type_enum=1;
|
UPDATE acc_gl_journal_entry je SET je.loan_transaction_id=je.transaction_id,je.transaction_id=Concat('L',je.transaction_id) WHERE je.entity_type_enum=1;
|
||||||
|
|
||||||
-1
@@ -3,4 +3,3 @@ UPDATE m_client mc SET mc.submittedon_date=now() where mc.submittedon_date is NU
|
|||||||
|
|
||||||
UPDATE m_group mg SET mg.submittedon_date=mg.activation_date where mg.submittedon_date is NULL;
|
UPDATE m_group mg SET mg.submittedon_date=mg.activation_date where mg.submittedon_date is NULL;
|
||||||
UPDATE m_group mg SET mg.submittedon_date=now() where mg.submittedon_date is NULL;
|
UPDATE m_group mg SET mg.submittedon_date=now() where mg.submittedon_date is NULL;
|
||||||
|
|
||||||
-2
@@ -10,5 +10,3 @@ INSERT INTO `c_configuration` (
|
|||||||
VALUES (
|
VALUES (
|
||||||
NULL , 'penalty-wait-period', '2', '1'
|
NULL , 'penalty-wait-period', '2', '1'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
-2
@@ -28,5 +28,3 @@ INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `en
|
|||||||
INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `enum_value`, `enum_type`) VALUES ('savings_transaction_type_enum', 15, 'Reject Transfer', 'Reject Transfer', 0);
|
INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `enum_value`, `enum_type`) VALUES ('savings_transaction_type_enum', 15, 'Reject Transfer', 'Reject Transfer', 0);
|
||||||
INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `enum_value`, `enum_type`) VALUES ('savings_transaction_type_enum', 16, 'Written-Off', 'Written-Off', 0);
|
INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `enum_value`, `enum_type`) VALUES ('savings_transaction_type_enum', 16, 'Written-Off', 'Written-Off', 0);
|
||||||
INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `enum_value`, `enum_type`) VALUES ('savings_transaction_type_enum', 17, 'Overdraft Interest', 'Overdraft Interest', 0);
|
INSERT INTO `r_enum_value` (`enum_name`, `enum_id`, `enum_message_property`, `enum_value`, `enum_type`) VALUES ('savings_transaction_type_enum', 17, 'Overdraft Interest', 'Overdraft Interest', 0);
|
||||||
|
|
||||||
|
|
||||||
-1
@@ -716,4 +716,3 @@ VALUES ((select sr.id From stretchy_report sr where sr.report_name='Written-Off
|
|||||||
'endDate');
|
'endDate');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user