Skip to content

Commit

Permalink
Merge pull request #1061 from ZakarFin/custom-migration
Browse files Browse the repository at this point in the history
Allow customization for db migration
  • Loading branch information
ZakarFin authored Oct 17, 2024
2 parents 19986aa + bd24a11 commit db879d4
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 36 deletions.
8 changes: 8 additions & 0 deletions MigrationGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@

## 2.14.0

### Frontend

The AntD component library has been upgraded from version 4 to 5. You might need to update application specific components. See details in: https://ant.design/docs/react/migration-v5

Frontend package.json scripts need to be updated due to webpack-cli upgrade. The scripts like start, build previously passed variables to build process like this `--env.appdef=applications`. These need to be modified by changing the dot to a space like this `--env appdef=applications`. Passing similar env-variables from command line also need to be passed without the dot.

### service-webapp / WebappHelper

Moved `fi.nls.oskari.servlet.WebappHelper` to new path `org.oskari.init.OskariInitializer`. This file is usually not customized so the change shouldn't have any effect on most instances. However if you have an override for the WebappHelper OR for example the `SpringInitializer` (that calls the WebappHelper) on your app you will need to update the references (it's a drop-in replacement). The new OskariInitializer allows overriding the database migration code with your own. See https://github.com/oskariorg/oskari-server/pull/1061 for details.

## 2.13.0

### GeoServer dependency removed
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.oskari.init;

/**
* Interface to implement customization for overriding the built-in migration process
*/
public interface CustomMigration {
void migrateDB();
}
74 changes: 45 additions & 29 deletions ...a/fi/nls/oskari/servlet/WebappHelper.java → ...va/org/oskari/init/OskariInitializer.java
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package fi.nls.oskari.servlet;
package org.oskari.init;

import fi.nls.oskari.cache.JedisManager;
import fi.nls.oskari.db.DatasourceHelper;
import fi.nls.oskari.service.ServiceRuntimeException;
import org.oskari.helpers.FlywaydbMigrator;
import fi.nls.oskari.log.LogFactory;
import fi.nls.oskari.log.Logger;
Expand All @@ -11,22 +12,18 @@

import javax.naming.Context;


/**
* Created by SMAKINEN on 8.7.2015.
*/
public class WebappHelper {
public class OskariInitializer {

private static final DatasourceHelper DS_HELPER = DatasourceHelper.getInstance();

private static final String STR_LOG_LINE = "#########################################################";


private static Logger log = LogFactory.getLogger(WebappHelper.class);
private static Logger LOG = LogFactory.getLogger(OskariInitializer.class);
private static SchedulerService schedulerService;
private static boolean propsLoaded = false;

private WebappHelper() {}
private OskariInitializer() {}

public static void loadProperties() {
// populate properties
Expand All @@ -35,7 +32,7 @@ public static void loadProperties() {
System.out.println("- loading /oskari-ext.properties");
PropertyUtil.loadProperties("/oskari-ext.properties");
// init logger after the properties so we get the correct logger impl
log = LogFactory.getLogger(WebappHelper.class);
LOG = LogFactory.getLogger(OskariInitializer.class);
propsLoaded = true;
}

Expand All @@ -45,17 +42,17 @@ public static void init() {
loadProperties();
}
// catch all so we don't get mysterious listener start errors
log.info(STR_LOG_LINE);
log.info("Oskari-map context is being initialized");
LOG.info(STR_LOG_LINE);
LOG.info("Oskari-map context is being initialized");
initializeOskariContext();

// init jedis
log.info("Initializing Redis connections");
LOG.info("Initializing Redis connections");
JedisManager.connect();
log.info("Oskari-map context initialization done");
log.info(STR_LOG_LINE);
LOG.info("Oskari-map context initialization done");
LOG.info(STR_LOG_LINE);
} catch (Exception ex) {
log.error(ex, "!!! Error initializing context for Oskari !!!");
LOG.error(ex, "!!! Error initializing context for Oskari !!!");
}

migrateDB();
Expand All @@ -64,7 +61,7 @@ public static void init() {
try {
schedulerService.initializeScheduler();
} catch (final SchedulerException e) {
log.error(e, "Failed to start up the Oskari scheduler");
LOG.error(e, "Failed to start up the Oskari scheduler");
}
}

Expand All @@ -73,36 +70,42 @@ public static void init() {
*/
public static void initializeOskariContext() {

log.info("- checking default DataSource");
LOG.info("- checking default DataSource");
final Context ctx = DS_HELPER.getContext();
if(!DS_HELPER.checkDataSource(ctx)) {
log.error("Couldn't initialize default DataSource");
LOG.error("Couldn't initialize default DataSource");
}

// loop "db.additional.pools" to see if we need any more pools configured
log.info("- checking additional DataSources");
LOG.info("- checking additional DataSources");
final String[] additionalPools = DatasourceHelper.getAdditionalModules();
for(String pool : additionalPools) {
if(!DS_HELPER.checkDataSource(ctx, pool)) {
log.error("Couldn't initialize DataSource for module:", pool);
LOG.error("Couldn't initialize DataSource for module:", pool);
}
}
}

private static void migrateDB() {
if(PropertyUtil.getOptional("db.flyway", true) == false) {
log.warn("Skipping flyway migration! Remove 'db.flyway' property or set it to 'true' to enable migration");
if (PropertyUtil.getOptional("db.flyway", true) == false) {
LOG.warn("Skipping flyway migration! Remove 'db.flyway' property or set it to 'true' to enable migration");
return;
}
boolean ignoreMigrationFailures = PropertyUtil.getOptional("db.ignoreMigrationFailures", false);
CustomMigration customMigration = getCustomMigration();
if (customMigration != null) {
LOG.warn("Running custom migration instead of built-in");
customMigration.migrateDB();
return;
}

// upgrade database structure with http://flywaydb.org/
log.info("Oskari-map checking DB status");
LOG.info("Oskari-map checking DB status");
try {
FlywaydbMigrator.migrate(DS_HELPER.getDataSource());
log.info("Oskari core DB migrated successfully");
LOG.info("Oskari core DB migrated successfully");
} catch (Exception e) {
log.error(e, "DB migration for Oskari core failed!");
LOG.error(e, "DB migration for Oskari core failed!");
if(!ignoreMigrationFailures) {
throw e;
}
Expand All @@ -112,26 +115,39 @@ private static void migrateDB() {
final String poolName = DS_HELPER.getOskariDataSourceName(module);
try {
FlywaydbMigrator.migrate(DS_HELPER.getDataSource(poolName), module);
log.info(module + " DB migrated successfully");
LOG.info(module + " DB migrated successfully");
} catch (Exception e) {
log.error(e, "DB migration for module", module, "failed!");
LOG.error(e, "DB migration for module", module, "failed!");
if(!ignoreMigrationFailures) {
throw e;
}
}
}
}

public static CustomMigration getCustomMigration() {
String className = PropertyUtil.getOptional("db.flyway.migrationCls");
if (className == null) {
return null;
}
try {
final Class clazz = Class.forName(className);
return (CustomMigration) clazz.newInstance();
} catch (Exception e) {
throw new ServiceRuntimeException("Error initializing migration class from 'db.flyway.migrateCls='" + className, e);
}
}

public static void teardown() {
if (schedulerService != null) {
try {
schedulerService.shutdownScheduler();
} catch (final SchedulerException e) {
log.error(e, "Failed to shut down the Oskari scheduler");
LOG.error(e, "Failed to shut down the Oskari scheduler");
}
}
DS_HELPER.teardown();
JedisManager.shutdown();
log.info("Context destroy");
LOG.info("Context destroy");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import fi.nls.oskari.control.ActionControl;
import fi.nls.oskari.log.LogFactory;
import fi.nls.oskari.log.Logger;
import fi.nls.oskari.servlet.WebappHelper;
import fi.nls.oskari.spring.extension.OskariParamMethodArgumentResolver;
import fi.nls.oskari.spring.extension.OskariViewResolver;
import fi.nls.oskari.util.PropertyUtil;
import org.oskari.init.OskariInitializer;
import org.springframework.context.ApplicationListener;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -55,7 +55,7 @@ public void setServletContext(ServletContext context) {
@PostConstruct
public void oskariInit() {
// check DB connections/content
WebappHelper.init();
OskariInitializer.init();
}

// --------- locale handling -------------
Expand Down Expand Up @@ -135,7 +135,7 @@ public ViewResolver getDefaultsViewResolver() {
public void tearDown() {
LOG.info("Teardown");
ActionControl.teardown();
WebappHelper.teardown();
OskariInitializer.teardown();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,16 @@

import fi.nls.oskari.log.LogFactory;
import fi.nls.oskari.log.Logger;
import fi.nls.oskari.servlet.WebappHelper;
import fi.nls.oskari.spring.session.RedisSessionConfig;
import fi.nls.oskari.util.PropertyUtil;
import org.oskari.init.OskariInitializer;
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

/**
Expand All @@ -26,7 +24,7 @@ public class SpringInitializer extends AbstractHttpSessionApplicationInitializer
@Override
public void onStartup(ServletContext servletContext) {
// IMPORTANT! read properties at startup - needed for profile selection
WebappHelper.loadProperties();
OskariInitializer.loadProperties();
// re-init logger so we get the one configured in properties
log = LogFactory.getLogger(SpringInitializer.class);
final WebApplicationContext context = getContext();
Expand Down

0 comments on commit db879d4

Please sign in to comment.