Creating an update patch notification

Hi all,

I was wondering about adding an update notification to my app that notifies people when I upload a new version of the solution to the server. I’m using the servoy security module which starts a headless client on startup which I thought might be the best way to do this. I’m not sure whether there is any way to run code on application upload so I was thinking of just having a version++ around where the code for the headless client startup is. Is there a better way of doing this as I don’t really like messing with the svy modules. I can’t really create another client either because it’s already pretty limited.

Thanks,
Alasdair

Hi Alasdair,

This is typically done in a post-import module.
Servoy supports 2 hooks at deployment: pre-import and post-import

The pre-import solution runs standalone and before anything else is loaded
This would be the place where you can make schema changes (column type changes, column drops, table drops) to your database if this is required for a particular update.

After that the solution is imported, where you can let Servoy create new tables/columns (remember Servoy only does incremental changes, no drops/type changes > this is why you would need a pre-import solution)

At the end of solution import, Servoy will trigger the post-import module.
Typically the place where you compare the version of your solution against the version stored in a table in your database.
Whatever steps (data conversion, notifications, copy report files from media to disk) are needed between these versions can be done at this point.

Last step would be to update the version in the database with the version of your solution.

Hope this helps

Yeah, that helps a lot.

So I just need to create a post-import module, and have it increment the version in the database and send that through a toastr? I was just going to have it use the release number and manually set it at the beginning.

Thanks!

Also would the function be set to the onOpen of the module?

alasdairs:
Also would the function be set to the onOpen of the module?

Yes

But… remember onPostImport is a headless client, so UI stuff can not be used.
I think quite ease would be to catch the onBroadCast event in the NG clients and check for the table that holds your version.
If an update is pushed on that table, compare version in code (because that is still old) against the version in the database.
If these versions are different show toastr/dialog/FID with release notes or whatever you can think off.

In order to have above working there are limitations.
Deploying your application through .servoy files will work, because there will be no downtime
Deploying through .war files will only work when you use Tomcat parallel deployment (which will need RabbitMQ to make these instances aware of databroadcast from the other)

If you are replacing the .war file completely the application will relaunch, users will be disconnected, so the ‘live’ new version notification will not be necessary.
You can notify users on next launch though.

Yeah that’s what I had in mind. I only ever import using a .servoy file so should be good.

I created it and set everything up but can’t seem to export it with the solution. Whenever I try referencing it from the global scope it’s not accessable.

It’s selected in the ‘add module’ dropdown item under modules so not really sure whats going wrong.

The module should be a part of your solution, and the solutionType has to be set to “post-import hook module” (or pre…).
You need a function to be set as “onSolutionOpen” and there you can do what you want to happen after import.

I think you cold check the version of the new application (if you set it in the export-options or the solution-properties, you can get the version via a simple application.getVersionInfo()[‘<your_solution_name>’] and broadcast this information.

Marc did a talk about the client manager plugin and broadcasting, you could look here: https://www.servoyu.com/courses/servoy- … rc-boegem/

If I understood hin correctly, you basically create a channel, listen to version-infos and display a message to the user.

Yeah, I created the module while in my main solution as a post-import hook module, have a function set as the onSolutionOpen, but I cant seem to reference the module’s scope in my main solution as if it weren’t connected to the project.

When I import the solution into the servoy application server, the module doesn’t pop up as one of the solutions activated. On export I have the ‘Export referenced modules’ selected, but can’t actually reference the module in my solution, so it’s not exported with the rest.

Also not sure if its related, but it has a ‘?’ where the git symbol usually is.

robert.edelmann:
Marc did a talk about the client manager plugin and broadcasting, you could look here: https://www.servoyu.com/courses/servoy- … rc-boegem/

If I understood hin correctly, you basically create a channel, listen to version-infos and display a message to the user.

Correct, it is another possibility, but in this case I wouldn’t waste this broadcaster, as you can use the ‘onDataBroadcast’ event in your main solution
This will have a function attached with ‘dataSource’ as first parameter

function onDataBroadcast(dataSource, action, pks, cached) {
	// TODO Auto-generated method stub
}

In case ‘dataSource’ is pointing to the table where you store your version, just compare that version with the one in your code.
If the database is higher/different version, then show the notification.

Hi Alasdair,

We have a table in our framework DB called solutions and there is a field in there called version. Our post-import module updates this version number when a new version is imported and this causes a message to be displayed to the currently logged in users that notifies them to log out, close their browser and then log back in. We use the Tomcat parallel deployment model which needs the user to close the browser tab in order to create a new session on the Tomcat server.

This is our version of the onDataBroadcast method that does exactly what your are attempting:

/**
 * Callback method for data broadcast.
 *
 * @param {String} dataSource table data source
 * @param {Number} action see SQL_ACTION_TYPES constants
 * @param {JSDataSet} pks affected primary keys
 * @param {Boolean} cached data was cached
 *
 * @author Steve Hawes
 * @since  2022-03-07
 *
 * @public
 *
 * @properties={typeid:24,uuid:"16CAF2FD-13C3-4E3A-B706-586C79DC9DD0"}
 */
function onDataBroadcast(dataSource, action, pks, cached) {
	switch (dataSource) {
		case datasources.db.ews_framework.solutions.getDataSource():
			if (pks.getValue(1, 1) == activeSolutionName) {
				/** @type {JSRecord<db:/ews_framework/solutions>} */
				const recSolution = scopes.svyDataUtils.getRecord(dataSource, pks.getColumnAsArray(1));
				if (recSolution.version != scopes.ewsSystem$properties.appVersion) {
					plugins.dialogs.showWarningDialog(scopes.ewsSystem$messages.i18nMessage.generic.title.warning, i18n.getI18NMessage(i18nMessage.dialog.newVersion.message, [recSolution.version]), scopes.ewsSystem$messages.ok)
				}
			}
			break;

		case datasources.db.ews_framework.downloads.getDataSource():
			scopes.svyEventManager.fireEvent(scopes.ewsNavigation.NAVIGATION_EVENTS.UPDATE_NAVBAR_ITEMS, scopes.ewsNavigation.NAVIGATION_EVENTS.UPDATE_NAVBAR_ITEMS);
			break;
	}
}

And this is the code in the post-import hook onSolutionOpen method that handles the version number update:

		/** @type {String} */
		const activeSolutionName = "<your main solution name>"
		/** @type {JSRecord<db:/ews_framework/solutions>} */
		const recSolution = scopes.svyDataUtils.getRecord(datasources.db.ews_framework.solutions.getDataSource(), activeSolutionName);
		if (recSolution) {
			recSolution.version = application.getVersionInfo()[activeSolutionName];
			databaseManager.saveData(recSolution);
		}

Hope this helps
Steve