AASH: Upgrade to 2025.06

Our Project

Our project AASH (Access Ablösung Schleswig-Holstein, Replace MS-Access in the state of Schleswig-Holstein) is still a small project with the goal to replace databases of MS-Access and their UI with (modelled) solutions in A12. There will be many different instances of this solution, each containing the databases of a specific ministry or a lower government body.

The goal of the project is to enable the customer to replace their existing MS-Access solution with a A12 solution that is created by just modelling (“no code”). The container application (the “web tool”) brings a set of different features, like

  • Import DM, FM, AM, OM, PM via zip file and make them available within the running application
  • Provide a mapping from the original database tables and fields into the A12 data model via annotations
  • Import an existing database into the web tool according to the mapping information
  • Migration of documents when the the model is updated
  • An admin panel
  • Export to Excel from an overview
  • Integration of Metabase
  • Handling of external unique identifiers (for import and update)
  • Print documents to PDF
  • Back up / restore all models, documents, attachments and relations to / from a zip file.

Motivation for migrating to 2025.06

Our application has not gone live yet as the project used to be a PoC only. It was our goal to get the migration done without having to care for existing installations (and we’ll have plenty of those, not only one instance).

What we did

We followed the standard migration instructions and ran the code migration tools. After that we ended up with some 60 files modified, and the code filled with squiggly red lines, but not too bad.

Backend

We started by cleaning up the backend. the biggest obvious change was the transition from IDocument to DocumentV2 and IFieldInstance to FieldInstanceV2 respectively. As our application manipulates documents via various levels of indirections on the meta level, we had to take care of the now immutable nature of DocumentV2 and FieldInstanceV2. Using new service classes, we had to rewrite some of our application logic.

Going from H2 to embedded Postgres

Our biggest obstacle turned out to be the ousting of H2 in favour of embedded Postgres for integration tests.

Configuration: the embedded database is not held in a local file even though the property spring.datasources.dataservices.embedded-postgres.pathdeceivingly suggests just that. The embedded database is rather found on postgres@localhost:5434 ![(warning)] .

Persistence of embedded DB: Other than the H2 database, the embedded database appears to be rather persistent. That means, there is some content in the database when the spring boot application is restarted (or, a new integration test is run, to be precise). As out our application does things at startup (like migration documents), we had a hard time to ensure that a new spring context also brings a clean database. In the end we came up with having a configuration class that manually deletes the content in the A12 tables at application start up, so that the integration test can be run without inferring with each other.

Integration test user: What also was more than a bit of an annoyance was figuring out how to configure the integration test user so that it was allowed to execute calls into the backend services without getting access denied. Here, too, we spent a hell lot of time in the debugger. In the end it turned out that a file we had configured in YAML was read internally as JSON.

Overall, the task of figuring out the database settings, what’s going when starting the integration tests, and debugging through the depth of A12 turned out to be the longest, most tedious individual task of the migration.

With the integration tests up and running again, straightening out the functional errors brought in by the migration was a matter of only a couple of days.

Frontend

Even though the frontend looked pretty bad in terms of squiggly red lines in the code, it turned out that most of the issues could be resolved relatively easily with the help of the TPS team and using the correct versions of all frontend components. Some smaller things, like getting rid of JSX were done relatively quick.

UI-state for filter conditions: In overviews, the ui state is kept in a different data format than needed by the query API. This makes it necessary to either (a) convert the filter data on client side before sending it to the server or (b) convert it in the backend. Neither of both seems a good was to go. We’d highly appreciate the use of a uniform data format.

Conclusion

Overall, the migration took something close to four weeks and probably had taken way longer without the support of TPS. Even though the code changes appear not be too big, figuring out the bits and pieces was in parts a nerve wrecking experience. Luckily it’s over now.

Hello Juergen,

Thanks for great feedback. As discussed, can you please add few notes regarding Query API?

Query API

In general, the Java side of the new query API felt pretty straightforward; however, so far, we only used “document” projection, no aggregation, no tree results, …
In most cases, we need to iterate over all documents of a model, so for that use case, we only had to adapt our “document iterator”. Unfortunately, the max. page size restriction stuck with us, but so be it.
Our Excel export function uses the filter and sort criteria from the standard A12 overview. Here, we had to do some magic in the frontend to transform the filter setting of the overview into “ILogicOperator” so that it can be used in the back end with the query API. Same applies for the sort criteria.

Nice to have: Simplified query language. While one can easily read and understand amount=12 AND status=’new’ OR amount=10 AND status=’inUse', this is absolutely not the case when formulating the same using DadaOperation.builder().operands(List.of(DuduOperation.builder.operands(List.of ……).build()).build()).build(). This is clearly a step down from Solr queries which one can write intuitively. So, here it’d be nice to have a simplified language as it is used in the documentation for explanation purposes.

Also nice to have for QueryRoot

  • default paging
  • default projection

JSONB (mis)understanding
My understanding was that we switched to Postgres because that allows JSON-queries on JSONB columns. However, the type of the column document-->content is still text. I had expected that to change to JSONB with the migration to 2025.06… Can someone clarify?