Oskari applications

Oskari applications are generated by selecting a combination of functionalities (bundles). These combinations are called application setups (appsetup). You can think of them as a shopping list or feature toggles for items you want your application to have. As Oskari was born from a geoportal platform and is mostly used as a solution for web-mapping software the one thing most applications have on their shopping list is the map-functionality (mapfull bundle). Other features that you can include in your application include features like search, layer listing, thematic maps functionalities and of course you can implement and include application specific features for your application.

Frontend

When building a customized application the main.js on the customized app determines what functionalities can be used with that app (what code is packaged to be used in the app). When starting the app the frontend usually makes a GetAppSetup XHR-request to the server asking what functionalities will be used on that app and for that user. The response is then constructed by the server based on what the uuid parameter was in the request (this matches the uuid column on oskari_appsetup database table) and who the user is or what roles the user has (guest, user, admin etc). The UUID parameter has a default and is optional but it is used to construct a listing of bundles that are linked to that application on the database table oskari_appsetup_bundles.

After the frontend receives the response for GetAppSetup it will try to start the bundles referenced in the response with the configuration and initial state received as part of the response. If the server response references a bundle that is NOT packed in the applications main.js the developer console will show a warning about this. Also worth noting is that everything referenced in main.js might not be used by the application. In this case it's best to use the lazy-loader option when referencing bundles in main.js so bundles that are not used with all users don't need to be loaded by users that don't see them (like the admin bundles that are only used by users with the admin role).

Database

On the database these application setups are saved on the oskari_appsetup table. The setups can be named and they have a type to separate between the default geoportal application, an embedded map application (users can create these with the publisher functionality bundle), applications that the users have saved as their own personalized starting "views" etc. The setups reference the frontend application code with the application column and the HTML-template (JSP-page) with the page column.

The selection of functionalities for applications are stored on the database table oskari_appsetup_bundles. A row on the table is a bundle in the application with possible configuration and state information. For example most applications have the map as functionality. You can see that the mapfull bundle is repeated on the table multiple times with the appsetup_id column pointing to the application where the map is used, state has information like what are the coordinates and zoom level the map is initially set and what map layers are on the map when the application is shown. The config column holds configuration like what feature toggles are activated for the user on that bundle. For the mapfull bundle the config are toggles from supporting wms-layers (usually always enabled) to supporting adding markers on the map and enabling adding vector features to the map programmatically. The difference between state and config is that state usually changes during runtime on the client (user moves the map and coordinates are changed) and config doesn't (the user either has the ability use a feature or not). Both config and state options are described for bundles on the API documentation. The seqno column is used to set the order in which the functionalities are started. Map is usually near the start of the sequence with a low value in seqno. The bundle_id column references the oskari_bundle database table where name is the "bundle id" that is recognized by the frontend.

Role based functionalities

The user roles can be used to inject more bundles for the frontend to start on top of the ones that match the application based on the database. This configuration is done in the oskari-ext.properties file on the server. It is usually used to inject administrative functionalities (bundles) for users with the admin role, but it can be used for other role based injection as well.

# bundles that are added on runtime to view if user has one of configured role
actionhandler.GetAppSetup.dynamic.bundles = admin-layereditor, admin-users

# Linking dynamic bundles based on user roles
# Properties are named 'actionhandler.GetAppSetup.dynamic.[BUNDLE ID].roles'
#   with value as comma-separated list of role names that should be served the bundle
actionhandler.GetAppSetup.dynamic.bundle.admin-layereditor.roles = Admin
actionhandler.GetAppSetup.dynamic.bundle.admin-users.roles = Admin

Oskari instance initial applications

The initial applications can be described as JSON-files on the server code and inserted to the database with Flyway-migrations. You can see these on the sample-server-extension that you can use as a template to build your own Oskari instance.

More information about Flyway and migrations:

The application specific migrations can of course be done however you want but this is a built-in option to use for migrating the database and can be used to modify the content on the database like adding or removing bundles from oskari_appsetup_bundles. Notice that these migrations are only run once so when it has been run, modifying the code doesn't get the migration run again. You will need to delete rows on the oskari_status_[your apps module] to the migrations to run again on a given database.

Modifying applications after the initial database population

Here's an example Flyway-migration that you can add on your server-extension code. Note that the order in which migrations are run is determined by the version number on the filename (the below would be 3.0.3). When you want to add a new migration after one has been run, you need to bump the version to a higher number like 3.0.4, 3.1.0, 4.0.0. So take a note a consider a versioning strategy for your Oskari instance. For best practices the version on the frontend codes package.json, the version on the server Maven modules pom.xml and the version on the Flyway migration should be tied to each other someway. Also note that the package reads [your apps module]. This is example on our sample-server-extension but can and should be changed to something that describes your app. (Not sure why we didn't call it "app" instead of "example" as that would have been more generic to use without renaming/might change this later). Note that you can also have multiple Flyway-modules on your app. The modules that are used when the server runs is set on oskari-ext.properties as db.additional.modules.

The migration name is after two underscores after the version. This can be anything you like on your application but it's easier to maintain if naming makes sense with the migration that is being run.

package flyway.[your apps module];

import org.flywaydb.core.api.migration.BaseJavaMigration;
import org.flywaydb.core.api.migration.Context;
import org.oskari.helpers.AppSetupHelper;
import org.oskari.helpers.BundleHelper;

import java.sql.Connection;

/**
 * Adds a bundle to all default/user appsetups
 */
public class V3_0_3__add_mybundle_to_apps extends BaseJavaMigration {

    public void migrate(Context context) throws Exception {
        Connection connection = context.getConnection();

        // id for the bundle to be added
        String bundleID = "mybundle";

        // register a new bundle (for example application specific bundle to the database "oskari_bundle" table)
        // this can be skipped when adding a "built-in" functionality to apps
        BundleHelper.registerBundle(connection, bundleID);

        // add the bundle to  
        AppSetupHelper.addBundleToApps(connection, bundleID);
    }
}

For removing bundles after they have been added you can see the other methods available on the AppSetupHelper class. You also don't need to use these helpers and can modify the tables with for example SQL. These are just common operations so we have helpers for them to make it as easy as it can be.

Last modified: Thu Nov 12 2020 16:56:48 GMT+0200 (Eastern European Standard Time)