Title: Release Notes For Version 11.0.8
To run Calpendo version 11.0, you should use:
If you are upgrading from version 9.0.x or earlier, then:
If you are upgrading from version 10.0.x, 10.1.x or 10.2.x to 11.0, then:
Note that this version drops support for the WebDAV protocol. See API Changes for more details.
Note that this version drops support for properties called ‘count’. Such properties cause parsing problems and are no longer allowed. See Count Properties Prohibited for more details.
Upgrading from any version to the latest (including applying bug fix updates) should be done with the following procedure:
Stop tomcat
For major upgrades, you must create a backup of your database before proceeding. For minor upgrades, it is recommended to create a backup, but it is less important. After having stopped tomcat, the typical command required is:
mysqldump -u USERNAME -p calpendo > calpendo.sql
or, depending on your system:
sudo mysqldump calpendo > calpendo.sql
Save the hibernate.cfg.xml and log4j.properties files from your existing webapps/Calpendo/WEB-INF/classes directory
Take the Calpendo directory from the tar.gz download, and replace your existing webapps/Calpendo with it.
Put the saved hibernate.cfg.xml and log4j.properties files into the new directory.
Modify your saved hibernate.cfg.xml following the directions below.
If you do not make the required changes to hibernate.cfg.xml, and run 11.0 against your old hibernate.cfg.xml file, then Calpendo will fail to boot. It will not make any changes to your database at all, and it will show an error message in your browser similar to this:
Failed to boot: java.lang.RuntimeException: Failed to boot database upgrades. ExprodoHibernateConfig class in use=com.springsolutions.calpendo.server.CalpendoHibernateConfig: Unable to create requested service [org.hibernate.cache.spi.RegionFactory]
Make sure you do not have both old and new versions in the webapps directory at the same time, unless they point to a different database. Booting multiple versions of Calpendo that point to the same database will cause problems and is best avoided.
Restart tomcat
Exprodo Software use MariaDB for all our production and development databases. We use test systems using both MariaDB and MySQL. You will need to make modifications to your hibernate.cfg.xml file regardless of which flavour of database you use, but the changes required differ.
For use with MariaDB, you will need to change:
Change the line that reads:
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
so that it reads:
<property name="hibernate.cache.region.factory_class">ehcache</property>
Change the line that looks like this:
<property name="hibernate.dialect">com.springsolutions.exprodo.core.server.persistence.ExprodoMySQL5InnoDBDialect</property>
and change it so it says this:
<property name="hibernate.dialect">com.springsolutions.exprodo.core.server.persistence.ExprodoMariaDBDialect</property>
Look for the line that starts like this:
<property name="hibernate.connection.url">jdbc:mysql://
and change the “mysql” to “mariadb” so that it starts:
<property name="hibernate.connection.url">jdbc:mariadb://
and finally, look for the line that starts:
<property name="hibernate.connection.driver_class">
and make sure that it reads:
<property name="hibernate.connection.driver_class">org.mariadb.jdbc.Driver</property>
For use with MySQL, you will need to change:
but it’s also worth verifying the correct values for:
Change the line that reads:
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
so that it reads:
<property name="hibernate.cache.region.factory_class">ehcache</property>
If you are using MySQL for your database, then it is recommended that you should use MySQL Connector/J which can be downloaded from dev.mysql.com/downloads/connector/j/. We do not distribute the MySQL driver, only the MariaDB driver. This is due to the MySQL Connector/J licence.
The jar file for MySQL Connector/J needs to be placed either in $CATALINA_HOME/lib or in the Calpendo/WEB-INF/lib directory, alongside all the other jar files we include in the distribution. It is generally better in $CATALINA_HOME/lib to make it easier to install new versions of Calpendo.
From version 8.0 onwards, the driver class name has changed. The old driver still works (at the time of writing) but is deprecated and may stop working. You should therefore switch to the new name. This is a setting in hibernate.cfg.xml that looks like this:
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
and if using version 8.0 or later of the driver, you should use the new driver class:
<property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
The settings for hibernate.dialect and hibernate.connection.url that you are currently using should not need changing. They should look like this:
<property name="hibernate.dialect">com.springsolutions.exprodo.core.server.persistence.ExprodoMariaDBDialect</property>
<property name="hibernate.connection.url">jdbc:mysql://HOSTNAME/DBNAME?useUnicode=true&characterEncoding=UTF-8&</property>
where the URL will have appropriate values for HOSTNAME and DBNAME, and you may have different settings for the URL after the ‘?’.
If something goes wrong during an upgrade, and you want to downgrade to a previous version, then it is important that you follow the right method.
If you are downgrading across patch versions, for example from 11.0.x to 11.0.y, then you can generally do that without making any changes to the database. Just change the program files to the version you want, and it will automatically handle any database changes required.
However, if you are downgrading across major or minor versions, for example from 11.0.x to 10.1.x, or from 11.0.x to 9.0.x, then it is very important that you follow the sequence described below.
If an upgrade fails for some reason, then the database may well be partially upgraded. Automatic recovery from a partial upgrade is not supported.
The general procedure for downgrading is:
As you can see, for this procedure it is essential that you took a backup of the database before the upgrade began, otherwise downgrading in the event of a failure may not be possible or may be difficult.
Examples of sequences for downgrading that are not supported and likely to result in a broken system are:
Don’t bother loading a backup of the database. Just change the program files to an old version and reboot.
Don’t bother dropping the database and recreate it. Just load a backup of the old database on top of an upgraded or partially upgraded database and run an old Calpendo.
Recovery from these kind of errors can be difficult and possibly labour intensive. Please avoid this by following the prescribed downgrade procedure as laid out above.
Workflows contain a “Database Workflow Event” which allow you to take actions when something is created, updated or deleted in the database. Previously, there was an option on the event called “Vetoable”, which was probably mostly ignored and not very well understood.
This has been replaced in version 11.0 with a new drop-down letting you choose which “phase” of the database change your workflow should execute in.
There are three phases, which are called:
Before version 11.0, there were only two phases available, and they were controlled by the “vetoable” flag. If you selected “vetoable”, then your workflow would run in what is now called the “during transaction” phase. Otherwise, it would run in the “after transaction” phase.
So what are these three phases, and when would you use each of them?
First, consider what happens when a change is made to the database as a result of a user request. First, the request arrives, and, in some cases, it has some changes made automatically to the request. For example, by incrementing a version number on the biskit being changed. Then, a new transaction is started with the database, and the biskit is saved to the database. Workflows are then triggered, and they may make other changes that are saved in the same database transaction.
If nothing goes wrong, the transaction is “committed”, and at this point everybody will see all the changes made in that transaction.
If something goes wrong during the processing, such as a rule deciding a booking cannot be allowed, or if a workflow issues a “veto” action, then the transaction is “rolled back”. In this case, everything that was saved in the transaction is reverted to its prior state.
If you create a Database Workflow Event and choose that it should operate in the “Before transaction” phase, that means:
Since changes made are not written to the database and do not trigger other workflows, it means it is much faster to execute workflows in the before-transaction phase that any other phase.
After all before-transaction updates have been made, then the whole set of changes made are merged into one. From this point on, it will then appear as if the user had requested the whole set of changes to be made themselves.
A transaction is then started, and all the merged changes are written to the database.
Any database workflow events marked for executing in the during-transaction phase will then run.
Once the during-transaction updates have completed, the transaction is committed and then after-transaction database workflow events will be executed.
For example, suppose the user creates a new booking. Suppose further that:
In this case, the before-transaction event will be triggered by the booking creation. The workflow updates the booking. However, the booking update is rolled in to the booking creation so that other events only see that the booking was created with a price already on it.
The after-transaction event would run once in this scenario, for the booking creation. Before version 11.0, this event would have been triggered twice: once for a booking create, and another for a booking update.
Some general rules of thumb about when to use which database update phase:
The way repeats are handled in version 11.0 has radically changed, with the code behind it being completely rewritten.
Previously, when you created a repeat booking, a single row would be created in the bookings table. It would include columns to say how the booking should repeat. When you ran a report or looked at the bookings calendar, the repeats would be automatically expanded so that it displayed “virtual” bookings for the later repeats.
Whenever the next repeating instance fell into the past, then a new non-repeat booking would be created, and the repeat booking would be modified so that it indicated the start date was whatever was the next instance of the repeat.
This resulted in various difficulties:
This has now all changed. When you create a repeat booking, then there are multiple rows inserted into the bookings table, one for each repeating instance up to a configurable time into the future. There’s also a single row added to a new “repeats” table, and all repeat bookings reference that repeat.
When a repeating instance falls into the past, nothing is done. There are no changes at that time. Instead, there is a process of extending the repeating sequence into the future to maintain the expansion out to the configured time into the future.
From a user’s perspective, this will be the same as before. Except that:
A “custom” repeat type is one which allows a sequence of bookings to be associated with one another without a prescribed way of identifying when the repeats should be. Instead, the dates on which repeats occur are manually assigned.
In previous versions, when a repeat instance fell into the past and a new non-repeat bookings was created, then it was assigned a value to a “sequenceId” property. This was the ID of the original repeat booking, and was a way in which one could tell that historical bookings came from a repeat.
Such bookings no longer record whether they were daily or weekly etc. Consequently, the process of upgrading to version 11.0 will automatically associate all bookings with the same sequenceId with a new repeat instance set to a “Custom” type.
Some other details of changes related to repeat bookings:
There’s a new global preferences option “repeatableExpansionDays”. This is the number of days into the future that repeats should be automatically expanded in the database.
The global preferences option “bookingRepeatsDaysToCheck” has been removed. This said how far into the future repeats should be expanded and have rules checked. This is no longer meaningful, since bookings are expanded in the database. The option “repeatableExpansionDays” effectively replaces this one.
Bookings and templates no longer have a “sequenceId” property. This is no longer required now that historical bookings retain a reference to their repeat instance.
Bookings and templates have a new property called “ephemeral”. This indicates whether a booking or template that you’re viewing is one that is stored in the database, or it’s a short-lived version created on-the-fly to show you what it will be when the repeat is expanded. By default, repeats are expanded in the database for 90 days. That means the repeat bookings for the next 90 days are not ephemeral. Beyond those 90 days, repeat bookings you see in the calendar are created on-the-fly and are ephemeral. Non-repeat bookings are always not ephemeral.
Linked Repeat Bookings
We now support linked repeat bookings. Previously, if you set up linked bookings, and allowed a linked booking to be created from a repeat booking, then the results were not good. However, this will now work, almost exactly as one would expect. Some things to note when a repeat booking caused child linked bookings:
Actual Usage (aka Resource Usage)
When recording actual usage, normally if there is a booking that the usage relates to, then the usage record would link to the booking. It was not recommended to link an actual usage record to a repeat booking, as the repeat booking’s date would continually change over its lifetime.
However, following the change to repeat bookings, it is now perfectly acceptable and sensible for an actual usage record to link to a repeat booking. Usage records should always be in the past, and historical repeat bookings are no longer modified as they used to be.
These are the workflow functions that have been introduced with version 11.0:
As mentioned in previous release notes, there are again many changes behind the scenes in support of Calpendo Enterprise. This is the ability to have a federation of Calpendo instances that work together.
Calpendo Enterprise is not yet available for general use in version 11.0, but is now available for limited use and circumstances.
With Enterprise, you can:
Further details will come later, when Calpendo Enterprise is on general release in version 12.0.
We now support the ability for a user to log in, and then switch identity so that they can appear to be a secondary user.
This is here so that somebody providing support (such as Exprodo Software or a local admin person) can investigate problems reported by somebody else by seeing things from their perspective.
To support this, there’s a new permissions action called “Switch User”. You will only be able to masquerade as another user if you have “Switch user” permission.
Here’s how it works:
System events account for the biggest part of disk space usage within Calpendo. However, once system events are old enough, they generally become completely uninteresting. For this reason, we have introduced and automatic system event deletion system.
In global preferences, you choose the retention period on the “General” tab, where you can find an item labelled “System Event Retention (Days)”.
This defaults to 190 days, roughly 6 months.
The properties Booking.lastRepeat and Template.lastRepeat have been removed with no exact replacement. This become necessary following the changes to the way repeats work in version 11.0.
lastRepeat was a DateRange property that told you when the last instance of a repeating sequence would be. This was similar to what you get from the date property Booking.repeat.finish, but it’s not the same for two reasons:
Repeat bookings and templates are now enumerated in the database, up to a controllable time limit which defaults to 90 days. This means there are multiple rows in the database, with each row being a particular instance of the repeat. The last instance in the database is like a “promise to repeat”, and is the template for how additional future repeat instances should be.
Since each repeating sequence results in multiple bookings being enumerated in the database, it no longer makes sense for all of them to store information about when the last repeating instance would be, and so this property has been removed.
The repeat does not store the date when the last repeating instance will occur, although it is possible a future version could provide it. However, it could not store any time or duration information since that belongs to the booking or template.
In the top-right corner of every page there were separate items that showed:
These have now all been replaced by a single item that shows who you are logged in as, but clicking it produces a drop-down with all the items that used to be separately displayed (as listed above).
If you are running an Enterprise system, then there will be an additional item labelled “Account Status” which will take you to the new Account Status page.
The cookie that Calpendo creates to record your session ID has changed. Every Calpendo has a “shard number” baked into it that is a number from 1 to 1023. This number is now part of the session ID. This change has been made so that when you are using the new Calpendo Enterprise version, then browsers can record a different cookie for each shard you log in to. This helps to make the process of logging in to different Calpendo instances within the federation a seamless process.
A typical session ID cookie might now be:
449571389971457-paul-54-mSjf3a0DrbPekWBa-76
where the different parts of this are:
There’s now a new shardNumber biskit pseudo-property that you can select in any place where you could previously select both a biskit’s id and biskitType properties.
This property provides the number (valued from 1 to 1023) that is baked in to every Calpendo instance. In an Enterprise system, this can be used to tell whether a biskit was created in your local Calpendo, or whether it’s been imported from elsewhere. You can do this with a condition like:
Value of shardNumber not equal to MetaProperties shard.number
This means you could have different permissions apply to biskits that are imported from a foreign Calpendo.
Occasionally there are problems when somebody configures multiple Calpendo instances to point at the same database. This usually happens when copying the Calpendo installation while testing out a new version, and forgetting to modify the hibernate.cfg.xml file that specifies which database to connect to.
It is not supported to have multiple Calpendos using the same database, as they tend to get in each other’s way.
When this does happen though, the evidence can be somewhat confusing.
To help with this, every system event now records an additional property called “jvmid”. This is a text string that is likely to be unique for every Calpendo instance, even those within the same Tomcat instance. If you now see different values of jvmid intermingled in the system events, this is a sure sign that there are multiple Calpendos using the same database.
Global Preferences is the name used to describe the page that stores the settings that govern how everything works.
However, with the advent of Calpendo Enterprise, which allows a federation of Calpendos to work together, the settings on a single Calpendo are not “global”, since they only affect the local system.
Hence the new name “System Settings”.
New Calpendos have the System Settings menu option appear in alphabetical order on the Admin menu. Existing customers will leave the menu option in the same place it was before, but renamed.
There are many changes behind the scenes in support of Calpendo Enterprise. This is the ability to have a federation of Calpendo instances that work together.
Calpendo Enterprise is not yet available in version 11.0.
With Enterprise, you will be able to:
Further details will come later, when Calpendo Enterprise is ready to be used.
CTMS is a Calpendo “Clinical Trials Management System” module.
One can use this to help schedule subjects on multiple studies, and to link this with the rest of Calpendo so that required resources can be automatically booked.
If one configures a complicated study, where there are many visits per subject, and many tasks required within each visit, then there can be a very large number of bookings required when enrolling a subject into a new study. We have seen a real life study with 1500 bookings required.
Calpendo was not designed to handle that kind of scale, and so it handled them very inefficiently. Consequently, there has now been a rewrite for the way updates are handled so that this can be done much faster than before.
For a long time, you’ve been able to add an item to the menu that will show a search page for a biskit of your choice, and to customise it to have search widgets as required.
For example, it can provide drop-downs for choosing some value a property on the target biskit must have.
You can also choose the report type. Typically, this would be a list report, group report or Kanban report.
When choosing a group report, you were not previously able to choose which columns should be shown by default on the report. Now you can select the columns you require.
A custom tree page is one that shows a tree of options on the left, where it automatically expands to show nodes in the tree for biskits that it finds.
For example, you could configure it to show projects by their status, or perhaps by status and owner.
The facilities offered by this dynamic expansion of nodes in the tree has been updated:
You can optionally have the tree create nodes in the tree that should be empty. For example, if you show projects by status, and there are no projects whose status is “Denied”, then if you turn on empty nodes, there would be a node for all the “Denied” projects. It would show the number of projects with that status (which would be zero in this case).
Sometimes you want to build the tree from one biskit, but then display a different one when you click on the leaf nodes. For example, suppose you create a custom tree page to show instances of Project Resource Settings. Then you might group those by project.status and resource. Or perhaps by project.status, resource and cost per hour. But when you click on one of the leaf nodes, instead of showing the ProjectResourceSettings, you might instead prefer to show the project. You can now do this by setting up the tree to build from ProjectResourceSettings, and then choosing to “Show editor for biskit at path”. In this example, the path would be “project” since that’s the property on ProjectResourceSettings that references the project.
Suppose you show ProjectResourceSettings by project.status and resource. Then the nodes for each status and resource are known as “grouping” nodes. When you click on a grouping node, you could previously have that show a search page for the biskits that generate the tree (ProjectResourceSettings in this example), run a workflow or do nothing. There are now two other options:
When a custom tree page starts a search, and you configure that to be a group report, you can now choose the columns to show by default.
When you sort a list of biskits, it’s not unreasonable that you’d then want to extract the first or last one. This is now provided automatically with the first and last biskit available in the Sort Workflow Action’s output.
When you search for something in a workflow, you can apply conditions to the thing you want to search for. So if you’re looking for bookings, you might have a condition to find bookings with a particular resource, and maybe filter by the booking’s date/time.
Previously, the conditions you can use were only those that look at values of the biskit you’re searching for or values of other biskits in scope, and you can’t use MetaProperties conditions, which would allow you to use values from the general environment.
This has now changed so that MetaProperties conditions are allowed in this context.
There are some circumstances where this allows you to write more succinct workflows rather than having to use different actions depending on the value of MetaProperties.
There are some messages sent by the server to the browser that contained information in an unnecessarily vociferous format. Sometimes this was repeated information, and others it was using longer names for things that it needed to.
These have now been changed so that the messages contain the same information, but in much less space. As well as saving on the time to transfer the message over the network, it also save considerably in the time it takes to parse the message.
This helps to make things faster.
The file import utility used to give timeouts when the import took too long. The import would continue in the background, but the user had no way to know that.
We have now change the way this works so that there will be no timeouts, no matter how long the import takes.
It also means that while an import is running, you can change your page to look at something else, and then when you come back to the import page, it will show you the status of the import that’s in progress.
The licence stored in Calpendo is managed differently in 11.0 from how it used to be. Previously, one would install the licence by going to global preferences (now called system settings) and adding it there.
However, when you have many systems to licence, for example as part of Calpendo Enterprise, then upgrading licences could be quite time consuming.
So licences are now managed centrally via a licence server.
Each Calpendo will send a request to the licence server at boot time and at regular intervals asking if there is an update to its licence. When somebody pays for an updated licence, Exprodo Software employees generate a new licence, and install it into the licence server. Your Calpendo will then automatically pick up the new licence.
By default, Calpendo must be able to contact the licence server at least once every 14 days to continue operating. If you are self-hosting Calpendo, and your network environment does not allow outbound https traffic, then you will need to let us know so that we can make alternative arrangements for you.
When the licence has been updated on the licence server, Calpendo will automatically fetch it when it next checks, which is done every 24 hours. If you require a licence to be pulled in immediately, there’s a new button on the system settings page for that on the licence tab labelled ‘Refresh From Licence Server’.
For those that host Calpendo on their own servers, it should be noted that this means some information is sent to Exprodo Software on a daily basis. This information includes:
The fingerprint is composed of the following items:
This data is collected for two reasons:
If you have privacy concerns relating to this data, then please contact us to discuss options.
When you look at a workflow now, there are icons added to each event and action to indicate when each one:
This helps to see where there are interesting things that may help somebody trying to understand what a workflow is doing.
The CSV import facility now has a setting that allows you to disable all database workflow events for the duration of the import.
This means that, when disabled, all database events will be ignored. This applies to ALL database events and not only those that are related to the import.
As such, this option must be used with great care and only root users are allowed to use this option.
This is being provided because there are sometimes occasions when workflows are not wanted. For example, when you are importing historical data. It may not conform to current restrictions that are implemented in workflows, or you may not want any changes made by workflows to these historical items.
These are the workflow functions that have been modified with version 11.0:
We have had the following APIs:
In our documentation, we have published behaviour available at /webdav/b and /webdav/q, without particularly pushing the fact that a generic WebDAV client could also connect to Calpendo.
We are now dropping support for the WebDAV protocol, while retaining support for the published behaviour on the above APIs.
Since we are dropping support for WebDAV, we are also changing the URLs to access the APIs to the following:
In order to aid transitioning to these new URLs, the old ones will continue to be supported, but we would encourage everybody to move to the new URLs as we may drop support for the old ones at some point in the future.
We have made this change mostly because our WebDAV support relied on a very old third party library that incorporated other third party libraries that had security vulnerabilities. We are also unaware of anybody using the WebDAV protocol with Calpendo, and so the most expedient solution was to remove WebDAV support while retaining the published API support.
We no longer support properties whose name is ‘count’, or whose column is named ‘count’.
If there are any such properties, then when you you first boot into the upgraded version, it will automatically stop before any changes are made to the database. A message in the log will indicate that it relates to properties called ‘count’ and to seek help.
If there are any properties called count or with a column name of count, then they would need to be renamed before the upgrade takes place. You are advised to seek help from support@exprodo.com if this applies to you.
Properties defined as a set of tags could not be modified by a CSV import. However, they are now fully supported by using a field with comma separated values.
Changes
Add support for server-side booking filtering for mobile app to use in booking search
Add code to help debug CreateVariables bug
Prevent the system user from being added to permission ‘Applies To’ tab
Bug Fixes
If you reduce the number of days that repeats should be expanded, and then create a new repeat booking, then the new repeat booking will be expanded out to the number of days you asked for.
But - since the system previously had expanded further, then it thinks everything is fully expanded out to a further date.
This causes some problems where expansion does not happen where it should.
Issue: 3705
Every time any Exprodo app boots or the system settings are modified, it creates an instance of the biskit “ExprodoLicence”.
These then track what the licensing limits were at each point in time.
It also tracks the version of the program installed and so it provides a good way to see when upgrades have been performed.
However, if in version 11.0.0 you try to view an ExprodoLicence that was created in 10.1 or earlier, then it generates an exception.
The message given is:
"Null value was assigned to a property of primitive type setter of
com.springsolutions.exprodo.core.domain.ExprodoLicence.licenceServerInactivityGracePeriod"
Issue: 3712
In the bakery, you can indicate which properties are required, and what the min/max value of each property is (where appropriate).
These limitations are checked after all automated properties have their values assigned.
For example, if you specify the creator of a biskit should be stored in a particular property, then that would happen before the validation is performed.
However, the validation was also being performed at an earlier stage, before these automated properties were set.
Consequently, if you specify that the creator of a biskit is to be automated, and you indicate that it is required, then creating such a biskit would fail validation because it is checked before the creator is set up.
Issue: 3713
If you configure a permission so that either the ‘Applies To’ or ‘Does Not Apply To’ tabs contain the system, then it causes mayhem.
Only root users can log in, and the root user only sees an error when trying to view the permissions page.
Issue: 3715
Calpendo only uses one cookie, and it holds the user’s session ID.
However, in an Enterprise system, each separate Calpendo shard within the federation has a different cookie name so that you can be logged in separately to each one.
This means the format for the name of the cookie has changed in version 11.0, as it now includes the shard number in the cookie name.
The name is now something like this:
session_id-407-Calpendo
Most people won’t notice this change, although it does present a problem for anybody using the same API that our desktop app uses to log in and make direct calls.
So there’s now an API call that will tell you the name of the cookie it’s using.
The scripts at https://github.com/exprodo/api have been updated to use this new API method call (and are backwards-compatible if connecting to a Calpendo without it).
Issue: 3718
Bug Fixes
Bug Fixes
BUGFIX: Booking Display Flag not working correctly for Ephemeral bookings
BUGFIX: CustomTreePage shallow exception if click on uncached biskit
BUGFIX: Linked Booking not use available child when another child unavailable
BUGFIX: Report columns lost when biskit type being searched for is changed
BUGFIX: Cannot attach file more than 5MB even with larger allowed size
BUGFIX: Workflow subroutine calls forget arguments after restart
BUGFIX: Starter & Lite licence complains about linked bookings but allows them to be created and they function
BUGFIX: User “nobody” can be deleted using checked-deletion
BUGFIX: Custom message for expired accounts is ignored
BUGFIX: Upgrade from 10.1 to 11.0 fails on MySQL 8.0.35
BUGFIX: Database upgrade for 10.4.9/19/1 gives error upgrading to 11.0
BUGFIX: Booking flags on ephemeral repeats show multiple times
BUGFIX: Remove duplıcates function gives lazy initialization exception with custom user field
BUGFIX: Cannot view or edit calendar if booking is missing a required project
Suppose you configure a resource so that it does not require a project, and then create a booking for it. Then, modify the resource to indicate that it does require a project. This will mean that pre-existing bookings are missing the required project.
In this condition, the calendar does not behave very well, giving an exception when displaying the booking with missing project.
This problem affects both week view and month view.
Issue: 3838
Changes
When you create a report from the bookings search page, Calpendo generates some conditions for the things you want the report to include.
These conditions include a part that covers the start and finish date/time that you specify on the report.
The conditions used for the start/finish times were complicated, with multiple conditions working together, and not at all intuitive.
These have now been replaced with a single condition that will say something like:
Value of dateRange includes time between May 1, 2024 and May 8, 2024
This condition is then converted behind the scenes to something that handles the complexity involved with repeat bookings so that it finds all the things it should.
This makes conditions on a report much more comprehensible.
The new “includes time between” relation is also available for users to use directly in their own reports, along with the inverse “does not include time between”.
Issue: 3892
When you use the general search page and search for Resource Usage, it now defaults to using the new “Includes time between” relation to provide a default filter.
It does this over the same period as before, from 14 days ago to 14 days from now, but it now calculates when those dates are and explicitly uses them rather than using “now plus 14 days” which is not (yet) supported by the “Includes time between”.
When you use the general search page and search for Booking, this does exactly the same thing as for Resource Usage.
The old default of searching for bookings from 14 days ago to 14 days from now did not correctly find repeat bookings, whereas the new “Includes time between” does.
Issue: 3900,3925
This allows a URL like this to search for bookings between certain dates:
https://mysystem.calpendo.com/api/q/Calpendo.Booking/dateRange/includes_time_between/20250430.105900-20250614.180000/
Note that other API relations for searching for bookings do not take into account repeats and how they work.
Anybody attempting to obtain bookings or templates within a set period is encouraged to use this new includes-time-between method.
Note also that the format of the two dates for an includes-time-between in the URL is much stricter than the query API generally supports.
The syntax is like this:
/includes_time_between/yyyymmdd.hhmmss-yyyymmdd.hhmmss/
Each of the date-time values are like this:
yyyymmdd.hhmmss
but can alternatively miss out the seconds:
yyyymmdd.hhmm
or can simply be the string:
now
Issue: 3936
Bug Fixes
On the system settings page’s Licence tab, there’s a button that lets you request that the licence be updated by fetching from the licence server right now.
This always fails on a production server as it does not send the required information in the request to the licence server.
Issue: 3841
The upgrade from 10.1 to 11.0 does a lot of manipulation of bookings and templates due to the way repeats are now handled differently.
There’s now a repeats table that stores all the repeat information, and bookings and templates both store a reference to the repeats table.
The way the data is converted from the old format to the new format was failing in some circumstances.
Specifically, when the sequence_id column on the templates table includes at least one non-zero value that matches the sequence_id in the bookings table.
Issue: 3842
If you have a group report of bookings that includes any child of a linked booking, then adding a column to the report to show linkedBookingParent gives an exception.
Issue: 3851
The sequenceId property was removed in the upgrade from 10.1 to 11.0 from Booking and Template as a part of the rewrite of the way repeats work.
However, reports referencing the sequenceId property were not modified.
Any columns referencing sequenceId directly are now removed.
If there are any indirect references to it (for example from a Booking a path like linkedBookingParent.sequenceId) then those are not modified, but instead they generate a warning when the upgrade is done.
Issue: 3856
If you generate a database dump using Calpendo 11.0.0 to 11.0.4.2, then the result cannot be loaded into MySQL.
It complains that it cannot assign a value to a generated column.
Issue: 3889
One can configure a resource in Calpendo to contain bookings that come in from an external system. For example, from a Google Calendar or other system, you can generate a URL that you can give to Calpendo, so Calpendo will create a booking to represent every item found on the Google calendar.
This worked in 10.1, but in 11.0 it fails to import anything.
Issue: 3927
If you set up an iCal import, then all the imported bookings should have a unique iCal ID stored on each booking (property name is iCalUid).
This ID is generated by the remote system that is the source of the iCal feed.
We store the ID so that when we synchronise with the remote system, we know which of the bookings in our database relates to the items in the feed.
However, the iCal unique ID was not being written to the database due to the changes that happened between 10.1 and 11.0.
This meant that the first import would work okay, but the second time it would fail.
That’s because the incoming bookings could not be matched to any pre-existing bookings, since none of them stored the iCal unique ID.
But every incoming iCal item was at the same time as the booking created when we first imported the iCal feed, and this would then generate an error as it failed a double booking rule.
Issue: 3947
When an iCal import takes place, then the idea is that the bookings in Calpendo should be a reflection of the items that exist in the remote calendar.
If the remote calendar includes historical items, then that’s what should be created in Calpendo.
If the remote calendar has items that are at the same time, then that’s what should happen in Calpendo.
However, all booking rules and limits on historical bookings were being applied to bookings imported via iCal, which doesn’t make sense.
Issue: 3948
Suppose you create a group report of bookings, and add a column for project.type.
Add a condition to show only bookings with no project.
Then clicking on the row in the group report gives an exception saying
"Cannot read properties of null"
Issue: 3949
Security Fixes
Any user that can see the template calendar can click on a template, and click the “Duplicate Across Resources” option.
This happens even if permissions say the user cannot create templates.
This security hole only applies to users with access to the template calendar and only allows an existing template to be duplicated; users cannot choose anything at all about the newly created template apart from the resource it applies to.
No other changes to data are in any way affected by this - it’s limited to duplicating templates across resources.
Issue: 3908
Bug Fixes
If you set a fixed value for a property on the “child properties” tab of a linked booking link, then that value will usually (although not always) be lost by the user interface.
When you first set up such a property, then it will be saved properly, even if after the save the value is not displayed.
However, from that point, if you edit the linked booking link again, then the value would be lost.
Issue: 3976
This is here in particular because version 11.0 has removed properties Booking.lastRepeat and Template.lastRepeat, with no alternative properties to replace them.
This is a breaking change, and any reports that referenced those properties will no longer work.
Consequently, when you now try to look at such a report or permission, it will show an error telling you about the properties it does not recognise.
Issue: 3981
Changes
Security Fixes
Bug Fixes
BUGFIX: API query fails to find a match when a search condition string value includes a space
If an API query is submitted to find a biskit that matches a specified string value for one of its properties, then no match is found if the string specified contains a space.
For example, an API query to search for a bookable Resource whose name contains a space will not find a match even if you get the name right in the condition.
Issue: 3921
BUGFIX: Before transaction workflow event overwrites old value of a property
Suppose you set up a workflow so that a database event runs before-transaction when a booking is updated, and it changes the description on the booking.
Suppose further that there’s another database event, but this one is triggered during-transaction. In this event, set up a templated text to show the old value of the booking start time and the new value.
Then if you edit a booking and change its start time, the second workflow should see the old and new value of the start time as being different. But instead, it shows them as the same, and equal to the new value.
Issue: 3964
BUGFIX: Conditions in a URL that take a DateRange value only accept a prefix of ‘R’ but should also accept ‘r’
The documentation here: https://docs.exprodo.com/railroad/conditions-url-11.0.4.html describes how you can use a link directly to a search page, and put conditions in the URL that will choose what the search will find.
For example:
https://demo.calpendo.com/#search&searchType=Calpendo.Booking&action=view&condition=dateRange.start/includes_time_between/R20240528.120000-20240528.230000/to-the/hour
This query is perfectly valid, and works. The documentation indicates that when putting a DateRange value in the URL, it must be prefixed with ‘R’ or ‘r’.
In the above example, it appears as: R20240528.120000-20240528.230000
However, while ‘r’ should be accepted, it isn’t. Only ‘R’ works. If you use ‘r’, then it causes an exception.
Issue: 3974
BUGFIX: Annual Repeat Bookings are assigned incorrect dates beyond the second instance
BUGFIX: Search for references to property sometimes gives exception with illegal report
Suppose:
Then when you click on the property “x” in the bakery and search for references to it, you get an exception.
Issue: 3984
BUGFIX: Specifying an invalid API resource looks like server down
BUGFIX: Errors sent from API give illegal content type
BUGFIX: Using API in browser shows raw HTML instead of interpreting it as HTML
BUGFIX: Cancelling last non-ephemeral repeat instance (‘This Item’) cancels all subsequent instances as well
BUGFIX: No warning popup when booking inside a warning template
BUGFIX: Setting booking rule to “suggest retry as tentative/requested” doesn’t result in expected suggestion popup
BUGFIX: Bookings rejected by a workflow rule did not generate exception
BUGFIX: Repeat expansion rejected by a booking rule prevented any expansion
Bookings that repeat have a certain number of booking instances expanded and stored in the database. This is set to 90 days by default.
Suppose a booking rule prevents a booking being created on some day in the future.
This might be a holiday rule or anything else that rejects a future booking.
Then when you create a booking, if the day which would be rejected by the rule is WITHIN the 90 day period, the booking would be outright rejected as breaking the rule.
This is not ideal, but is how the system has always behaved, and we are accepting this for now.
Suppose then that the day which would be rejected by the rule is OUTSIDE the 90 day period.
Then it’s the job of the “Repeatable Handler” to check every day to see if there are repeat bookings that need to have another day’s booking expanded and stored in the database.
If that happened, and the booking it tried to create was rejected by a rule, then this would generate an exception and no changes would be written out.
This isn’t right because this booking would never be able to exist beyond this one day that the rule disallows.
The behaviour now is that on the day in question, the booking will be created, but it will have a status of DENIED.
A further issue with this behaviour exists on upgrading from 10.1 to 11.0. In this case, the upgrade procedure which runs at boot time does not expand the repeat instances. Instead, this expansion happens after the Calpendo boot has completed. However, any booking for which any of its repeat instances (within the 90 day period) are rejected by a rule will result in that booking not being expanded at all - not even before the day that is rejected.
The expected behaviour here is that those bookings that are rejected are assigned a status of DENIED, and all others would be expanded as normal.
Issue: 4043
BUGFIX: Repeat expansion could set a whole sequence to denied when it should not
BUGFIX: Errors sent from API set the HTTP return status code to 200, which suggests no error
BUGFIX: RepeatableHandler “update” system event is badly formatted, confusing and misleading
BUGFIX: Permission editor gives false-positive errors about unknown properties
BUGFIX: Database stored functions ‘formatpk’ and ‘parsepk’ get timezone wrong
BUGFIX: Change finish time on last instance of a repeat gives exception
Suppose you create a repeat booking and give it a finish date, so that it does not repeat forever.
Then if you edit the last instance of the repeat and change the finish time, then you get an exception that says:
"IndexOutOfBoundsException: Index -1 out of bounds for length 0"
Issue: 4060
BUGFIX: Edit ephemeral afternoon daily repeat booking this-item and non-ephemeral booking not created next day
If you create a daily repeating booking that starts after noon, and then edit the description of any one of the repeat instances after the period of expansion in the database (90 days from today by default), then it does not store a new instance of the repeating booking a day later, which it should.
Issue: 4061
BUGFIX: Ephemeral bookings sometimes do not display in the calendar
BUGFIX: Existence of before-transaction db event causes aborted cancellation to be persisted
BUGFIX: Edit description of last ephemeral THIS-ITEM and previous ephemeral is not created
Suppose:
Then it will correctly store a booking in the database to represent this instance.
However, it should also create bookings in the database for all previous ephemeral bookings, and it did not do this.
Issue: 4066
BUGFIX: Exception on change repeat so previously cancelled bookings now needed
Suppose you have a repeat booking, and you then modify the repeat in such a way that some repeat instances are no longer needed, and so are cancelled.
Then modify the repeat again so that some or all of those cancelled instances are required again. That is, they must be “uncancelled”.
This situation was not handled correctly, and it tried to save the uncancelled bookings with a null status, which is not allowed.
Issue: 4071
BUGFIX: Approve repeat booking also approves cancelled and denied instances
Suppose you:
Then all the repeat instances are approved.
This means that the instances that are not wanted (because it’s repeating every 2 days) are also approved, and so they look like that are wanted, even though the repeat still says every 2 days.
Issue: 4075
BUGFIX: You can approve a repeat booking instance that is cancelled because the repeat says it should not exist
BUGFIX: Uncancelling repeat booking ALL ITEMS only uncancels one instance
BUGFIX: Creating a new booking allowed you to select “custom” repeat type
Custom repeat types are partially implemented. This is a type where you have multiple bookings that are considered part of the same repeat sequence, but without a defined pattern to the dates that the repeats occur on.
During an upgrade from 10.1 to 11.0, any repeat bookings where the whole sequence is in the past will have lost the information about what sort of repeat it was.
Consequently, during the upgrade they are converted to a repeating sequence with “Custom” repeat type.
This is currently the only way to create such repeats as they are not fully implemented.
So when creating a new booking or template, the repeat types drop-down lists “Custom”, but it is greyed out and cannot be selected.
Issue: 4078
BUGFIX: Custom repeat type is selectable when editing existing booking
A custom repeat type should ONLY be selectable when:
However, pre-existing bookings which were either not repeating, or were repeating with a type that was not custom could be edited to make them custom repeats. This is not supported.
Issue: 4080
BUGFIX: Choose reason for cancellation and it did not notice (if on subtab)
BUGFIX: Change repeat booking description ALL ITEMS gives shallow exception with status on subtab
BUGFIX: Change repeat booking description ALL ITEMS gives shallow exception with formulaic property
BUGFIX: Edit a repeat booking instance and “Cancelled” does not appear in the status drop-down
BUGFIX: User can change the resource of any booking from a repeat sequence
BUGFIX: Error displayed after editing a non-ephemeral booking in the future and select ‘This and Later’ option
BUGFIX: Created booking appears to be ephemeral via ‘Copy to Clipboard’
BUGFIX: Cut/paste some workflow actions gives EntityNotFoundException on save
BUGFIX: Cannot save User BiskitDef with property that references a User
BUGFIX: Data loss if edit a biskit referencing a non-enumerable biskit value
Changes
Bug Fixes
The lastRepeat property has been removed from Booking and Template in 11.0.
Some conditions are automatically modified when the reference the lastRepeat property, but not all.
There was already an upgrade script to make sure there was a warning generated during the upgrade for any remaining condition that referenced lastRepeat, but it never ran because it was misconfigured.
Issue: 4120
In 10.1, there are properties Booking.lastRepeat and Template.lastRepeat that do not exist in 11.0.
If you have a report which has a column referencing one of those properties, and it is not the last column in the report, then upgrading from 10.1 to 11.0 produces a report that gives errors when you open it.
Specifically, locate the report in the report manager page, and then click on either “Open Report” or “Run Report”, and it gives an exception.
Issue: 4121
When a Calpendo’s licence has expired, and gone beyond its grace period, trying to use it will instead display a “Licence Reset” page.
When a Calpendo has just been upgraded from version 10.1 to 11.0, then the “Licence Reset” page will show as well. This is because it will need to be assigned a “system identity”. This is used with the new licence server so that each system can have their licences automatically updated each year, rather than requiring a manual change to input the new licence.
However, if an already-expired system is upgraded, then you could not use the licence reset page to assign a system identity. Without a licence and without a system identity, recovery from this would be messy.
So now, the system reset page will allow you to set the system identity when the licence has expired. This allows for upgrades from 10.1 (which have no system identity) to work properly.
Issue: 4124,4125
Suppose you have linked bookings set up so that the creation of a booking for a parent resource will create a booking for exactly one child booking, but from a selection of more than one resource.
Then if you make a parent booking and the first child it tries to create fails because it breaks a rule, it means that it doesn’t even try to make a booking for another child, so the parent gets refused.
Issue: 4129
If you configure a layout to display a boolean property with a checkbox (rather than radio buttons or a list box), then it does not display the correct value and does not let you change the value.
Issue: 4133
Create or edit a report in the report manager, and the time-of-day on the schedule’s “When” tab always reverts to midnight, regardless of what time you choose.
Issue: 4138
Bug Fixes
Search for “Calpendo Licence”, and either show a list report or a group report which includes the new property “usedLinkedBookingLinks”, and you get an error:
IllegalArgumentException during GroupSearchRequest: org.hibernate.QueryException: could not resolve property: usedLinkedBookingLinks of: Calpendo.CalpendoLicence
This was a bug introduced in 11.0.7 due to a change to allow linked bookings to be added to a Calpendo Starter licence.
This change had an error in it that meant that Calpendo Licence was not properly defined, and any attempt to access the new usedLinkedBookingLinks property would fail.
Issue: 4162