Changelog

Sophora 6: Update Notes

Instructions for updating from the previous Sophora version

General Update Notes

Version 6 is the first version supporting "decoupled releases", i.e. a relaxation in compatibility between major versions. Most importantly, the Sophora Client 5 remains compatible with Sophora Server 6, so you do not need to update all Sophora products at once during the major update for the Sophora Server.

We will provide a compatibility matrix once more Sophora products are released with different major versions.

Sophora Client API Update Notes

Major Changes

The Sophora Client 6 now uses the new gRPC-based Sophora API to communicate with the Sophora Servers. For Client API users, the internal transition to gRPC is transparent and requires no code changes. However, the connection URL must be updated to reflect the new port. By default, the gRPC service is available on port 2026.

Version 5 Clients remain fully compatible with Version 6 Servers, as the server exposes both the new gRPC API and the legacy HTTP API.

Notable Changes

Unauthenticated Calls

Previously, calling methods on a not-logged-in Sophora Client resulted in undefined behaviour, most of the time throwing exceptions related to network errors. Now these calls will result in the exception ClientStateException, which has two sub-types to further indicate the issue.

Before login: If the client attempts to send a request to the server before logging in, an exeption is thrown: SophoraClientAwaitingLoginException. There are some logical exceptions that do not require authentication, for example, the login method.

After logout: If the Sophora Client attempts to send a request to the server after logout, it will always throw the exception SophoraClientAlreadyDisposedException. After a logout a new Sophora Client needs to be instantiated in order to make requests again.

Discontinued Support of XPath Queries

With the replacement of JCR by PostgreSQL, XPath queries are no longer supported. Before updating, all XPath queries must be refactored to IQuery.

Affected components:

  • API methods accepting XPath query strings.
  • The XPathQuery implementation of the IQuery interface.
  • The forceRepositorySearch flag.

Unlike XPath queries, which always reflected the immediate, transactional state of the data, Solr-based IQueries are eventually consistent. Results may be outdated by a few seconds. This is generally unproblematic, but if your code reacts to a DocumentChangedEvent and immediately execuites a query, the change that triggered the event might not be represented by the search results.

Breaking Changes

VersionTimingChanges
6.0.0Before the update to Sophora Client 6.0.0.All searches using the IQuery interface will query SolrCloud. The flag SearchParameters forceRepositorySearch will be ignored by the Sophora Server. A warning is logged, if it is still in use.
6.0.0After the update to Sophora Client 6.0.0.This is relevant if you are using the NodeStateRestorer in com.subshell.sophora.commons instead of the method ISophoraClient#doAndRestoreState(). The NodeStateRestorer was moved from com.subshell.sophora.commons.content to com.subshell.sophora.client.documentstate.
6.0.0After the update to Sophora Client 6.0.0.The copy constructor of SearchParameters changed its visibility to protected. Use SearchParameters#copy instead.
6.0.0After the update to Sophora Client 6.0.0.SolrSearchParameters#getBqs and SolrSearchParameters#getFl now return unmodifiable lists.
6.0.0Before the update to Sophora Client 6.0.0.ServerNode#setNodes now only accepts a list of ServerNodes as the childNodes parameter. If the list contains any elements of other implementations of INode, it will not be set and an exeption IllegalArgumentException will be thrown.
6.0.0After the update to Sophora Client 6.0.0.The dependency org.apache.httpcomponents:httpclient has been replaced by org.apache.httpcomponents.client5:httpclient5.
6.0.0Before the update to Sophora Client 6.0.0.The Sophora Client now uses a new gRPC-based API to communicate with the Sophora Server. This comes with its own list of breaking changes: "Sophora 6: API changes". Read the page carefully and see if any of your own tools uses one of the deprecated methods.
6.0.0Before the update to Sophora Client 6.0.0.Methods for exporting content to files in Sophora XML or Excel format have been moved from the Sophora Client to a new library with the Maven coordinates com.subshell.sophora.export:sophora-export-library.

Sophora Content API Update Notes

Removed REST Methods

The following REST endpoints/methods have been removed without a replacement:

  • /api/v1/configuration/roles
  • /api/v1/configuration/users
The following REST endpoints/methods have been removed, but an alternative is available:
  • /api/v1/solrquery/: Use /api/v1/solrIQuery instead.

The following REST endpoints/methods have been added:

Sophora Delivery: Update Notes

Sophora Importer Update Notes

VersionTimingChanges
6.0.0The Sophora Importer now uses Spring 6.1.6 and Spring Boot 3.2.5. Adjust your custom preprocessors, if they make use of Spring or Spring Boot or their dependency management. See the Spring 6 migration guide and the Spring Boot 3 migration guide for details.
6.0.0The Sophora Importer now uses Groovy 4.0. Adjust your custom preprocessors, if they are written in Groovy. See the Groovy 4.0 release notes for details.
6.0.0The Sophora Importer now requires version 1.2.0 of the Helm chart sophora-import-job.

Configuration Changes

VersionTimingChanges
6.0.0This must be done before the Importer is started for the first time in version 6.The syntax of the logback-spring.xml file changed. To filter log messages marked as 'SPECIAL_EMAIL_NOTIFICATION', adjust your Logback configuration according to the example provided on the Installation & Configuration page.

Sophora Server Update Notes

Major changes in Version 6

Postgres as the persistence layer

With the release of version 6, Sophora has transitioned its persistence layer from Apache Jackrabbit to PostgreSQL. This shift delivers enhanced performance, greater scalability, and more robust concurrency. See the Document Store documentation for details.

Upon the initial startup of Server version 6, data is automatically migrated from JCR to PostgreSQL. Depending on the size of the repository, this process may take several hours. If the migration is interrupted, it will resume seamlessly upon the next start.
Migration progress can be tracked in the server logs. During the migration process, the server does not open an HTTP port. Thus, it remains inaccessible to clients, metrics are unavailable, and health endpoints do not respond. Make sure your setup does not try to automatically restart the server too quickly due to unresponsiveness.

As with every major release update, replicas must be updated before the primary. While a version 5 primary is compatible with version 6 replicas and staging servers, a version 6 primary is not compatible with version 5 replicas or staging servers.


Once the migration is successfully completed, the JCR repository can be deleted. Both the repository folder in the server's home directory and the associated JCR databases are obsolete. The server must be stopped before deleting the JCR repository.

As a result of this transition, XPath queries are no longer supported. All XPath queries must be migrated to IQuery, which relies on Apache Solr for execution. This affects not only API calls but also text-based configurations in:

  • Select Values
  • Scripts
  • Configurations

These configurations must be refactored to SoQL before starting the update.

The Sophora Server now requires PostgreSQL 17 or later.

Removing obsolete JCR data

Starting with Sophora Server 6.1.0, you can safely remove all data related to JCR after the initial migration. This includes the following directories in your filesystem:

  • sophora/repository/repository
  • sophora/repository/version
  • sophora/repository/workspaces
  • sophora/data/tags

You may also delete the database that stores JCR data.

In case you are using our Helm Chart, make sure to update the Helm Chart to at least version 3.0.1. Now apply the following steps in order to delete the old data:

  • Set sophora.server.persistence.repositoryType to none
  • Configure an extra volume mount to access the old data: 
extraVolumeMounts:   
  - name: sophora-server-storage
    mountPath: /sophora/old_data 
  • Remove all obsolete directories via shell access
rm -rf /sophora/old_data/config
rm -rf /sophora/old_data/solr
rm -rf /sophora/old_data/repository.binarystore
rm -rf /sophora/old_data/repository.version
rm -rf /sophora/old_data/repository.binaries
rm -rf /sophora/old_data/repository.workspaces.live.index
rm -rf /sophora/old_data/repository.workspaces.live.db
rm -rf /sophora/old_data/repository.workspaces.default.index
rm -rf /sophora/old_data/repository.workspaces.default.db
rm -rf /sophora/old_data/repository.repository
rm -rf /sophora/data/tags

You can remove the old_data volume mount afterwards.

The Sophora Server now hosts a new gRPC-based Sophora API on an additional port (default 2026).

Due to the discontinuation of Spring Remoting, the Sophora Client (version 6 and later) now utilizes gRPC for server communication. This gRPC services listens on port 2026 by default. Sophora Server 6 exposes both the gRPC and the legacy HTTP API. Consequently, the Sophora Client in 5 remains compatible with Sophora Server 6.

Deprecation Warning: Starting with Sophora Server version 7, the HTTP API will be removed, and only gRPC will be supported.

The module Linkchecker has been sourced out in version 5 and has been removed from Sophora Server 6.

Consequently, the Linkchecker must be deployed as a standalone application.

Content-API Externalization

Up to Version 5, the Content-API was an integral part of the Sophora Server. Starting with Version 6, the Content-API is available exclusively as an external service. Consequently, it must be deployed separately if required.

Minimum Sophora Version prior to Upgrade

For compatibility reasons all of your Sophora Servers must be running with at least version 5.11.0 prior to the upgrade to 6.

Configuration changes

Document Store configuration

Several new configuration options have been added for the Document Store in Sophora 6.

StatusDocument Store configurationDescriptionDefault
NEWsophora.documentstore.sophoraids.declutter.cronSchedules cleanup of the Sophora ID table. Removes IDs of fully deleted documents if their ID base is continued by other documents.0 0 0 * * * (00:00)
NEWsophora.documentstore.cache.documents.maxSizeDocument cache located directly behind the database. Prevents database lookups when fetching documents. Stores live and working versions.5000
NEWsophora.documentstore.cache.summaries.maxSizeDocument summary cache located directly behind the database. Prevents database lookups when fetching summaries. Stores live and working versions.5000
NEWsophora.documentstore.cache.ids.maxSizeDocument ID cache located directly behind the database. Used for resolving references and executing simple queries. Stores live and working versions.100000
NEWsophora.documentstore.cache.primaryTypes.maxSizeResolves the primary type of a document based on its document ID.100000
NEWsophora.proposals.cache.maxSectionsMaximum number of proposal sections stored in the cache.2000
NEWsophora.proposals.cache.maxProposalsMaximum number of proposals stored in the cache.20000
NEWsophora.repository.jcrNodeTypesPath to a .cnd file containing old JCR definitions that aren't stored in PostgreSQL. The default includes all required JCR nodetypes. It is unlikely that you need to change this property.classpath:/cnd/jcr.cnd
REMOVEDsophora.backupSystemDocuments.cronExpressionAutomatic backup of user settings is no longer supported.
REMOVEDsophora.autoPublish.legacyModeThe released status is no longer considered during publishing.
REMOVEDsophora.repository.transaction.uuidlocks.enabledThis lock is no longer needed due to the updated transaction model in the Document Store.

PostgreSQL configuration

The PostgreSQL configuration has been available since Sophora 5 but is included here for completeness.

PropertyDescriptionDefault
sophora.persistence.postgres.hostnameHostname of the PostgreSQL server
sophora.persistence.postgres.portPort of the PostgreSQL server
sophora.persistence.postgres.usernamePostgreSQL username
sophora.persistence.postgres.passwordPostgreSQL password
sophora.persistence.postgres.databaseDatabase used for both Version Store and Document Store
sophora.persistence.postgres.maxPoolSizeMaximum number of connections in the connection pool. Determines how many SQL requests can be processed in parallel. Connections are reused.10
sophora.persistence.postgres.minIdleConnectionsMinimum number of connections that should always be available
sophora.persistence.postgres.connectionTimeoutMsMaximum time the Sophora Server waits for a connection30000 (30s)
sophora.persistence.postgres.idleTimeoutMsMaximum time a connection should remain idle before being closed10000 (10s)
sophora.persistence.postgres.validationTimeoutMsAfter this timeout, the Sophora Server checks the connection’s health status5000 (5s)
sophora.persistence.postgres.sslModeSets the SSL mode. To enforce a connection over TLS use require. For more information about SSL modes refer to the official postgres documentation.prefer (Postgres default)

List of breaking changes

VersionTimingChanges
6.0.0Before the update, preferably months beforeThe Sophora Server does no longer come with an internal Linkchecker. If you use this feature and have not yet switched to the external Linkchecker application, you should install it before updating.
6.0.0Before the update, preferably months beforeSupport for the legacy structure node document type "sophora-nt:structureNodeDocument" is discontinued in version 6. Please ensure that you do not use this document type anywhere. Since version 3 it is replaced by "sophora-nt:structureNode2".
6.0.0Before the update, preferably months beforeThe Sophora Server no longer supports to search its PostgreSQL based document repository with IQuerys. Instead all queries will search in SolrCloud. The SearchParameters forceRepositorySearch flag will be ignored by the Sophora Server.
6.0.0Before the update, preferably months beforeThe Sophora Server has a default implementation for composing and parsing URLs, which uses the URL components of the Sophora Webapp-Framework instead of requesting the deliveries.This implementation can handle both Sophora document URLs and URLs for the Sophora Image Service. It also avoids HTTP calls to the deliveries and thus it's much faster.

Using the URL handling from the deliveries by setting the property sophora.url.use-url-library=false in the configuration file is no longer possible. The configuration sophora.documentUuidProvider.servletPath has also been removed.

For more information about the properties, see the description in the documentation of the Sophora Server configuration.
6.0.0Before the update, preferably months beforeSince the method getAdditionalXPath (deprecated in 5) was removed from the ITimingActionScript interface, all implementations must also omit this method. Use getAdditionalIQuery as replacement.
6.0.0Before the update, preferably months beforeThe Sophora Server no longer natively supports HTTPS and all associated configuration options have been removed. We highly recommend using an SSL-terminating reverse-proxy like nginx to connect to the Sophora Server. Read the configuration guide for more information how to configure Sophora correctly.
6.0.0Before the update, preferably months beforeThe Sophora Server now hosts the new gRPC-based Sophora API on an additional port (default 2026). The previous API remains but will be removed with the future Sophora Server 7 release. The new API comes with its own list of breaking changes, which can be found on the "Sophora 6: API changes" page. Read the page carefully and see, if any of your own tools uses one of the deprecated methods.
6.0.0Before the update, preferably months beforeThe shell script sophoraServerControl.sh, previously used to start the Sophora Server for on-premises setups, was removed in version 6 (was deprecated in 5). Customers can still run the Sophora Server on-premise, but no official script will be provided or supported. The recommended deployment method is now container-based/cloud-based using Helm charts.
6.0.0Before the update, preferably months beforeWe removed the support for the deprecated sophora-nt:tags node type. The method com.subshell.sophora.api.server.IContentManagerContent#getTags will not be removed in Sophora 6 but it will always return an empty set.
Related to this change the following sophora.properties configurations were removed:
  • sophora.tagManager.cacheFileEnabled
  • sophora.tagManager.storeAllTags
Also these MBeans (JMX) methods are no longer available:
  • void setTagManagerCacheJobEnabled(boolean enabled)
  • boolean isTagManagerCacheJobEnabled()
  • void setTagManagerCacheJobCronExpression(String cronExpression)
  • String getTagManagerCacheJobCronExpression()
6.0.0Before the updateA BooleanQuery without any subqueries will now lead to an exception in the server, instead of interpreting it as a "find everything" query. Tools may create such queries when generating a BooleanQuery by using an empty list.

Sophora Web Update Notes

Major Changes

Project renamed

The Sophora Mobile Client has been renamed to Sophora Web.

Existing documentation still might refer to the Mobile Client or Webclient, but Sophora Web is the new official name.

UI-Overhaul

The overall appearance of Sophora Web has been changed. This covers essentially every view.

Notably, Sophora Web now has a configurable theming. Refer to the documentation for more details.

New Copytext Editor

The editor for the copytext and all other rich-text fields has been completely rewritten in a new framework.

This comes with a number of new features for the copy text like tables, support for markup etc.

New Search Options

Sophora Web now comes with extended support for the Sophora Query Language.

Additionally, search results now also can be displayed in a table.

New Module Co-Curator

Sophora Web 6 introduces the new module Co-Curator.

Introducing support for Bulk-Edits

Sophora Web v6 Introduces bulk edits as a new feature.

VersionTimingChanges
6.0.0Sophora Web uses the Client API in version 6. New configuration options for the client, specifically for using the new gRPC-Port therefore also apply to Sophora Web.
6.1.0Sophora Web now uses Java 25
6.3.0Sophora Web now uses a configuration document. The externalId of the used document must be written into your application.yml. Furthermore, the branding icon is now configured via this document. Thus, the old banner image configuration via the application.yml can be deleted.
Besides this breaking change, the theming and maximum number of Excel exports can now be configured via this document.
6.4.0Support for configuration-sets has been discontinued.
6.4.0The maxFileSize parameter for images no longer works, as Sophora Web now supports file- and image-uploads of arbitrary size. The maximum size for both can now be controlled via spring.servlet.multipart.max-file-size and .max-request-size.
6.4.0Sophora Web 6.4.0 required the Sophora Server in Version 6.1.5 or newer

Spring Data Sophora: Update Notes

API Changes

VersionTimingChanges
6.0.0The SolrSyncChecker has been moved from com.subshell.sophora.spring.data.repository.solr to com.subshell.sophora.spring.data.commons.solr.
To be able to continue using this class, you will need the following dependency: com.subshell.sophora:spring-data-sophora-commons

Sophora UGC Update Notes

UGC Service

VersionTimingChanges
6.0.0Starting with this version, the JVM proxy settings will be used automatically for connections. Therefore, the configuration parameters sophora-server.proxyHost, sophora-server.proxyPort, sophora-server.proxyUser, and sophora-server.proxyPassword are no longer necessary as of this version and have been removed.
6.0.0Starting with this version, UGC only supports PostgreSQL. Support for Oracle and MySQL has been discontinued to streamline database operations.

If you are currently using Oracle or MySQL, you must migrate your data before upgrading:
  • Data Migration: Use third party tools like pgloader or DBeaver to move your data to a Postgres database. Please refer to their official documentation for the migration process.
  • Sequence Adjustment: After migration, you must manually update your database sequences (or the sequence table) to match the current MAX(id) of your data. Migration tools often don't sync sequence counters. If not updated, the application will attempt to use IDs that already exist, leading to Primary Key conflicts.
  • To ensure high performance you may need to create new indexes. For more information read the Database — Performance Optimization (Indexes) here.

Update your configuration parameter database.url in the application.yml of the UGC Webapp.
6.0.0The configuration parameter database.oracleDB is no loger recognized and needs to be removed from the application.yml.

UGC Multimedia Service 

VersionTimingChanges
6.0.0Starting with this version, UGC only supports PostgreSQL. Support for Oracle and MySQL has been discontinued to streamline database operations (see UGC Service table above).

If you are currently using Oracle or MySQL, you must migrate your data before upgrading:
  • Data Migration: Use third party tools like pgloader or DBeaver to move your data to a Postgres database. Please refer to their official documentation for the migration process.
  • Sequence Adjustment: After migration, you must manually update your database sequences (or the sequence table) to match the current MAX(id) of your data. Migration tools often don't sync sequence counters. If not updated, the application will attempt to use IDs that already exist, leading to Primary Key conflicts.
  • To ensure high performance you may need to create new indexes. For more information read the Database — Performance Optimization (Indexes) here.

Update your configuration parameters in spring.jpa.hibernate and spring.datasource in the application.yml of the UGC Multimedia Service to use PostgreSQL.
Troubleshooting the PostgreSQL migration

If you encounter issues after migrating your data from MySQL or Oracle to PostgreSQL, check the following common pitfalls:

1. "Resource Not Found" or Empty Results
  • Symptom: The application starts, but certain data (like Form Data or Comments) is not displayed, or you see ResourceNotFoundException.
  • Reason: This is often caused by Case Sensitivity. If your table or column names were imported with capital letters or double quotes (e.g., "VALUE"), JPA might not find them.
  • Solution: Ensure all identifiers are lowercase. Use the Normalization Script provided above to rename tables and columns to lowercase.
2. "Duplicate Key" or "Primary Key Violation" on Save
  • Symptom: You can read data, but creating new entries fails with a Unique Constraint Violation.
  • Reason: PostgreSQL sequences (which handle the id generation) are not automatically updated during a data import. They often remain at 1, while your data already has IDs up to 5000.
  • Solution: Run the Sequence Initialization Script to sync all database sequences with your existing record IDs.
3. "Column is of type integer but expression is of type boolean"
  • Symptom: Saving data fails with a PSQLException regarding type mismatch for columns like pinned, spam, or legitimate.
  • Reason: MySQL uses TINYINT(1) for booleans, which PostgreSQL imports as integer. JPA, however, expects a real boolean type.
  • Solution: Cast these columns to boolean using the Data Type Correction Script: ALTER TABLE usercomment ALTER COLUMN spam TYPE boolean USING (spam::boolean);
SQL scripts after database migration

This section contains scripts that may be required after migrating your MySQL database to PostgreSQL. Please review and customize the scripts before execution.

All column and table names need to be lower case:

DO $$
DECLARE
    rec record;
BEGIN
    FOR rec IN
        SELECT table_name, column_name
        FROM information_schema.columns
        WHERE table_schema = 'public'
          AND column_name <> lower(column_name)
    LOOP
        EXECUTE 'ALTER TABLE public."' || rec.table_name || '" RENAME COLUMN "' || rec.column_name || '" TO ' || lower(rec.column_name);
    END LOOP;

    FOR rec IN
        SELECT table_name
        FROM information_schema.tables
        WHERE table_schema = 'public'
          AND table_type = 'BASE TABLE'
          AND table_name <> lower(table_name)
    LOOP
        EXECUTE 'ALTER TABLE public."' || rec.table_name || '" RENAME TO ' || lower(rec.table_name);
    END LOOP;
END;
$$;

Creating sequence for all tables and set the value to the highest ID to prevent collisions:

DO $$
DECLARE
    row record;
BEGIN
    FOR row IN 
        SELECT table_name 
        FROM information_schema.columns 
        WHERE table_schema = 'public' 
        AND column_name = 'id' 
        AND table_name != 'databasechangelog' 
    LOOP
        EXECUTE 'CREATE SEQUENCE IF NOT EXISTS ' || row.table_name || '_id_seq';
        
        EXECUTE 'ALTER TABLE ' || row.table_name || ' ALTER COLUMN id SET DEFAULT nextval(''' || row.table_name || '_id_seq'')';
        
        EXECUTE 'SELECT setval(''' || row.table_name || '_id_seq'', (SELECT COALESCE(MAX(id), 0) + 1 FROM ' || row.table_name || '), true)';
        
        EXECUTE 'ALTER TABLE ' || row.table_name || ' ALTER COLUMN id TYPE bigint';
        
    END LOOP;
END $$;

Alter columns so that boolean types are used now:

-- User comments & Uploads
ALTER TABLE usercomment ALTER COLUMN spam TYPE boolean USING (spam::boolean);
ALTER TABLE usercomment ALTER COLUMN pinned TYPE boolean USING (pinned::boolean);
ALTER TABLE imageupload ALTER COLUMN spam TYPE boolean USING (spam::boolean);
ALTER TABLE imageupload ALTER COLUMN pinned TYPE boolean USING (pinned::boolean);

-- Results (Quiz, Voting, Forms)
ALTER TABLE formresult ALTER COLUMN legitimate TYPE boolean USING (legitimate::boolean);
ALTER TABLE quizresult ALTER COLUMN legitimate TYPE boolean USING (legitimate::boolean);
ALTER TABLE votingresult ALTER COLUMN legitimate TYPE boolean USING (legitimate::boolean);

Last modified on 2/10/26

The content of this page is licensed under the CC BY 4.0 License. Code samples are licensed under the MIT License.

Icon