For the general upgrade process, see the page Upgrading the Nuxeo Platform.
This chapter highlights some major information about upgrade from Nuxeo Platform LTS 2019 (10.10) to Nuxeo Platform LTS 2021 (2021.x). We strongly encourage you to also have a quick read of the upgrade notes.
Prerequisites
This upgrade notes assume that Nuxeo Server is up to date in 10.10 before the upgrade, which means:
- Nuxeo Server is on 10.10 with the latest hotfixes
- All the migrations have been successfully completed (comments and trash).
Installation and Configuration
Recommended Changes
Configure Thumbnail Computation Maximum Duration Since 2021.5
The maximum duration to produce a thumbnail is now limited by default to 5min. This limit is applied to the listener in charge of creating a new thumbnail and also to the recomputeThumbnail bulk action.
The limit can be tuned with:
nuxeo.thumbnail.transaction.timeout.seconds=300
Note that the limit is set at the transaction level (and not at the command level) because thumbnail generation may involve multiple commands.
More on JIRA ticket NXP-30438
Enable Log4j Filter to Conceal Sensitive Data Since 2021.2
In order to enable the policy to mask sensitive data, you must configure a Log4j2 RewriteAppender applying the policy in your log4j2.xml configuration file.
See the example below:
<RollingFile name="FILE-ORIGINAL" fileName="${sys:nuxeo.log.dir}/server.log"
filePattern="${sys:nuxeo.log.dir}/server-%d{yyyy-MM-dd}.log.gz" append="true">
<PatternLayout pattern="%d{ISO8601} %-5p [%t] [%c] %m%n" />
<CronTriggeringPolicy schedule="0 0 0 * * ?" evaluateOnStartup="true" /> <!-- Rollover at midnight every day -->
<DefaultRolloverStrategy />
</RollingFile>
<Rewrite name="FILE">
<AppenderRef ref="FILE-ORIGINAL"/>
<MaskSensitiveData />
</Rewrite>
More on JIRA ticket NXP-30079
Disable Tomcat AJP Connector
For security reasons (CVE-2020-1938), AJP is now disabled by default. To re-enabled it, the following properties must be defined:
nuxeo.server.ajp.enabled=true
nuxeo.server.ajp.secretRequired=true
nuxeo.server.ajp.secret=changeme
The secret must also be mentioned in the mod_proxy_ajp
configuration, see Apache documentation for more.
If one is sure that the AJP port cannot be accessed by any untrusted hosts, then the following configuration is possible:
nuxeo.server.ajp.enabled=true
nuxeo.server.ajp.secretRequired=false
More on JIRA ticket NXP-28703
Allow Some Runtime Configuration in Nuxeo Docker Images
To control the JVM heap size with the new options (since Java 10): InitialRAMPercentage
and MaxRAMPercentage
, in nuxeo.conf
, we've changed:
JAVA_OPTS=-Xms512m -Xmx1024m
to:
JAVA_OPTS=-XX:InitialRAMPercentage=3 -XX:MaxRAMPercentage=25
See the best practices about the Java Virtual Machine Settings for more information.
More on JIRA ticket NXP-28145
Create ClusterService to Hold Cluster Node Info
When configuring Nuxeo in cluster mode, the configuration is now done with:
nuxeo.cluster.enabled=true
nuxeo.cluster.nodeid=...
You should specify a nuxeo.cluster.nodeid
even if you don't activate clustering, as it may help debugging (in particular Stream-based Pub/Sub).
The previous Framework properties (repository.clustering.enabled=true
, repository.clustering.id=...
) are still available for backward compatibility.
Note that repository.clustering.delay
still exists but is only meaningful for VCS when used with the legacy and deprecated JDBCClusterInvalidator (which is not the default anymore since Nuxeo 9.1 (NXP-21801)).
More on JIRA ticket NXP-25499
Behavior Changes
Better Tracking of the Nuxeo Health Check Failures Since 2021.2
The unhealthy status are now tracked into the logs at WARN level.
In order to not pollute the log if failures happen for all /runningstatus check, you should put this logger in your log4j2 configuration:
<Logger name="org.nuxeo.ecm.core.management.statuses.HealthCheckResult">
<!-- this filter allows to print 1 log (maxBurst) every minute (rate) -->
<BurstFilter level="warn" rate="0.0166" maxBurst="1"/>
</Logger>
More on JIRA ticket NXP-30100
RemoteIpValve
Added to the Tomcat Configuration Since 2021.2
The RemoteIp Valve has been added by default to the Tomcat configuration.
This valve replaces the apparent client remote IP address and hostname for the request with the IP address list presented by a proxy or a load balancer via a request header.
More on JIRA ticket NXP-25667
Configuration Generator Refactoring Since 2021.2
There're breaking changes on ConfigurationGenerator, a lot of methods has been removed, constants have been removed or moved to ConfigurationConstants.
The new class ConfigurationHolder is the new first citizen to get the Nuxeo Configuration in this layer. You can retrieve it with ConfigurationGenerator#getConfigurationHolder method.
You now can use nuxeo.append.templates.SOMETHING=A_TEMPLATE
parameter in nuxeo.conf
to append templates to load by the configuration generator.
More on JIRA ticket NXP-25667
Strict Mode by Default for nuxeoctl
Start
nuxeoctl
now starts a Nuxeo server in strict mode by default.
--force
and --strict
have no impact.
To start a Nuxeo server but aborting in error the start command when a component cannot be activated or if a server is already running, use the --lenient
option.
$ nuxeoctl start --lenient
More on JIRA ticket NXP-20418
Core Storage
Recommended Changes
Allow Efficient Search by Blob Key Since 2021.2
In order to improve the search by blob key in the existing databases, an index should be added on ecm:blobKeys
:
db.default.createIndex({"ecm:blobKeys": 1})
More on JIRA ticket NXP-29516
Use partialFilterExpression on parentId When Creating the Unique Index to Avoid Duplicates Since 2021.15
You MUST run the command below in a MongoDB Shell (assuming you're connected to the nuxeo database and your repository is default):
db.default.dropIndex("ecm:parentId_1_ecm:name_1");
As a workaround, you can configure the nuxeo.db.indexes.create property to false in nuxeo.conf.
More on JIRA ticket NXP-30638
Behavior Changes
Adjust the Mongodb Query Maxtime With Transaction Timeout Since 2021.2
The maximum query execution time on MongoDB side is now aligned with the Nuxeo transaction. The configurable maxTime introduced in NXP-29112 is only used when queries are performed outside of a transaction.
More on JIRA ticket NXP-30045
MongoDB Repository Configuration Descriptors
Contributions including a MongoDB nativeId
, sequenceBlockSize
or childNameUniqueConstraintEnabled
are now correctly merged.
More on JIRA ticket NXP-28770
Document Creator And Contributors Injection/Impersonation
The following dublincore
properties are now secured from edition:
dc:created
dc:modified
dc:creator
dc:lastContributor
dc:contributors
This means you have to be administrator to edit these properties. In tests, you can do the following:
Framework.doPrivileged(() -> doc.setPropertyValue("dc:creator", "john"));
or:
CoreInstance.doPrivileged("default", session -> {
DocumentModel doc = session.createDocumentModel("/", "file", "File");
doc.setPropertyValue("dc:creator", "john");
return session.createDocument(doc);
});
In order to declare a property secured you can contribute the following:
<component name="my.component.name">
<extension target="org.nuxeo.ecm.core.schema.TypeService" point="schema">
<property schema="YOUR_SCHEMA" name="PROP_NAME" secured="true" />
</extension>
</component>
You can also relax the constraint on a secured property, for example dc:creator with:
<component name="my.component.name">
<require>org.nuxeo.ecm.core.CoreExtensions</require>
<extension target="org.nuxeo.ecm.core.schema.TypeService" point="schema">
<property schema="dublincore" name="created" secured="false" />
</extension>
</component>
More on JIRA ticket NXP-27137
S3 Transfer Parameters Configurable Since 2021.11
All the S3 multipart upload and copy parameters are configurable through nuxeo.conf.
The nuxeo.s3.multipart.copy.part.size
ConfigurationService property, formerly contributed in configuration-properties.xml
, is deprecated since 2021.11/10.10-HF54.
The new nuxeo.s3storage.multipart.copy.part.size
nuxeo.conf
property should be used instead, default value hasn't changed: 5242880 (5 MB).
If you have contributed a custom nuxeo.s3.multipart.copy.part.size
ConfigurationService property with an XML component such as:
<extension target="org.nuxeo.runtime.ConfigurationService" point="configuration">
<property name="nuxeo.s3.multipart.copy.part.size">xxxx</property>
</extension>
you need to remove it and replace it by nuxeo.s3storage.multipart.copy.part.size=xxxx
in nuxeo.conf
. Though, backward compatibility is kept.
The following nuxeo.conf
properties have been added:
nuxeo.s3storage.multipart.copy.threshold
, default value: 5368709120 (5 GB)nuxeo.s3storage.multipart.upload.threshold
, default value: 16777216 (16 MB)nuxeo.s3storage.minimum.upload.part.size
, default value: 5242880 (5 MB)
setUserAgentPrefix in S3 Config Since 2021.15
The following nuxeo.conf properties have been added:
nuxeo.s3storage.user.agent.prefix
, empty string by default
nuxeo.s3storage.user.agent.suffix
, empty string by default
More on JIRA ticket NXP-30797
Improve KV TransientStore GC Resiliency Since 2021.17
Transient GC was not working in environments with segregated front and worker nodes.
As the result, transient stores in s3 might have accumulated lots of data and the current transient GC implementation might not be able to clean them efficiently.
In this case, it is recommended to purge manually all objects older than 3 days on transient stores before applying this hotfix.
This can be done using scripts or by creating an Object Lifecycle Management rule with a correct prefix /transient_*/
.
More on JIRA ticket NXP-30851
Nuxeo API Changes
New Endpoint to Get All Comments for 50+ Annotations Documents
REST API: The endpoint GET
/nuxeo/api/v1/id/DOC_ID/@annotation/comments
has been deprecated in favor of POST/nuxeo/api/v1/id/DOC_ID/@annotation/comments
.The annotationIds are now given in the payload request as a simple json array.
For instance:
curl -XPOST http://localhost:8080/nuxeo/api/v1/id/DOC_ID/@annotation/comments -d '[ "ANNOT_ID1", "ANNOT_ID2", ... ]'
Java API Added:
CommentManager#getComments(CoreSession session, Collection<String> documentIds) AnnotationAdapter#getCommentsFromBody(String payload)
Deprecated:
AnnotationAdapter#getComments(@QueryParam("annotationIds") List<String> annotationIds)
More on JIRA ticket NXP-29610
Remove "session id" Notion From CoreSession and DocumentModel
New methods:
DocumentModel.getPrincipal()
DocumentModel.attach(CoreSession)
DocumentModel.isAttached()
CoreInstance.getCoreSession()
various signatures, as replacements for deprecatedopenCoreSession()
CoreInstance.getCoreSessionSystem()
various signatures, as replacements for deprecatedopenCoreSessionSystem()
Deprecated methods/fields/classes:
DocumentModel.getSessionId()
DocumentModel()
constructors withsid
parameterCoreInstance.openCoreSession()
various signatures (usegetCoreSession()
instead)CoreInstance.openCoreSessionSystem()
various signatures (usegetCoreSessionSystem()
instead)CoreInstance.closeCoreSession()
(does nothing)DocumentModelFactory.createDocumentModel(type, id)
(was unused)CoreEventConstants.SESSION_ID
(was unused for a long time)CoreSessionService.releaseCoreSession(CoreSession)
(does nothing)CloseableCoreSession
(useCoreSession
instead)
New INTERNAL methods:
DocumentModel()
constructor withCoreSession
,repositoryName
,NuxeoPrincipal
parametersDocumentModelFactory.createDocumentModel()
signatures with CoreSession parameterBaseSession.createEntryModel(schema, id, values, readOnly)
and variations (directory class)
Removed methods/fields/classes (these were INTERNAL implementation details):
DocumentModel.attach(sid)
DocumentModelFactory.createDocumentModel()
signatures withsid
parameterCoreSession.isLive(boolean)
CoreSession.getSessionId()
CoreInstance.getSession(sid)
CoreSessionService.getCoreSession(sid)
CoreSessionService.getCoreSessionRegistrationInfos()
BaseSession.createEntryModel()
signatures withsid
parameter (directory class)LocalException
(DocumentNotFoundException
is thrown instead)CoreSessionRegistrationInfo
SessionInfo
SIDGenerator
More on JIRA ticket NXP-28799
ConfigurationService API
APIs below were deprecated:
String getProperty(String)
in favor ofOptional<String> getString(String)
String getProperty(String, String)
in favor ofString getString(String, String)
- boolean
isBooleanPropertyTrue(String)
in favor of booleanisBooleanTrue(String)
(same behavior) - boolean
isBooleanPropertyFalse(String)
in favor of booleanisBooleanFalse(String)
- new API returns true if and only if property value is false, it wasn't the case forisBooleanPropertyFalse
which returns true if property value is not blank and is nottrue
.
More on JIRA ticket NXP-26181
Cannot use multi repository (XA mode) with PostgreSQL
The following APIs are deprecated and will be removed in the future:
TransactionHelper.suspendTransaction
TransactionHelper.resumeTransaction
TransactionHelper.requireNewTransaction
Instead, the following APIs should be used:
TransactionHelper.runInNewTransaction
TransactionHelper.runWithoutTransaction
More on JIRA ticket NXP-274915
Operations and Automation
GET Call to an Operation's @async Returns a JSON
Result of a GET call to an operation's @async adapter is now always JSON. Previously when the result of the operation had a URL we returned a redirect to download the file but, in order to workaround the opaque redirect limitation, we are now returning the JSON object with the absolute URL. Clients should follow the URL manually to trigger the download.
More on JIRA ticket NXP-28608
Operation Document.AddPermission "users" Field Now Supports Stringlist
Document.AddPermission
operation use now StringList type for users field.
More on JIRA ticket NXP-26773
Error Management on Invalid Operation/Chain/Codec Registration
Operation chain contributions should now require contributions holding operations that they reference.
The following issue will now prevent server from starting in strict mode:
- invalid chain declaration, referencing an operation unknown to the service at registration time
- invalid operation class declaration (class not found or not an operation)
- invalid automation codec class declaration (class not found or not a codec)
More on JIRA ticket NXP-29499
Fn.htmlEscape is Now Available in JS Automation
The following methods become non-static to be available via JS automation:
org.nuxeo.ecm.automation.features.PlatformFunctions#htmlEscape
org.nuxeo.ecm.automation.features.PlatformFunctions#nxqlEscape
You can use them directly through the Fn
object:
var escapedHtml = Fn.htmlEscape(html)
var escapedNxql = Fn.nxqlEscape(nxql)
When used in Java code, you must update your code from:
String htmlEscaped = PlatformFunctions.htmlEscape(html);
String nxqlEscaped = PlatformFunctions.nxqlEscape(nxql);
to:
PlatformFunctions pf = new PlatformFunctions();
String nxqlEscaped = pf.nxqlEscape(nxql);
More on JIRA ticket NXP-27294
Make Tests Stop Depending on nuxeo-automation-client
Tests depending on EmbeddedAutomationServerFeature
can now make use of a limited-functionality org.nuxeo.ecm.automation.test.HttpAutomationClient
(in a new package) that does direct HTTP calls and doesn't attempt to map JSON responses to a domain-level object model like Document, etc.
@Inject
protected Session session;
becomes:
@Inject
protected HttpAutomationSession clientSession;
More on JIRA ticket NXP-28581
Rename the Parameter "overwite" of filemanager.import to "overwrite"
In the FileManager.Import operation, the misspelled param overwite
has been renamed to overwrite:
overwite
is now deprecated, no more used and replaced byoverwrite
.overwite
is kept as an alias for backward compatibility.
More on JIRA ticket NXP-29286
Allow Automation Contributions to be Disabled Since 2021.17
When replacing an Automation operation, chain or script, its old aliases are lost. If you contribute to an operation and want to call it by an alias, you need to copy that alias on the new operation contribution or to use the ID of the operation rather than an alias.
OperationType (Please note you can't cross contribute to an OperationType implementation, a chain operation can't disable a scripted operation for example)
ChainOperationType
:
<component name="org.nuxeo.ecm.automation.test-chain-operation" version="1.0">
<extension target="org.nuxeo.ecm.core.operation.OperationServiceComponent" point="chains">
<chain id="testScript" enabled="false" />
</extension>
</component>
ScriptingOperationType
:
<component name="org.nuxeo.ecm.automation.test-scripted-operation-disable" version="1.0">
<require>org.nuxeo.ecm.automation.test-scripted-operation</require>
<extension target="org.nuxeo.automation.scripting.internals.AutomationScriptingComponent" point="operation">
<scriptedOperation id="testScript" enabled="false"/>
</extension>
</component>
More on JIRA ticket NXP-30761
Workflow
Behavior Changes
Nuxeo Workflow Now Supports 2 Parallel Tasks Completed at the Same Time by 2 Different Users Since 2021.10
A warning is logged when assigning an unauthorized workflow global variable instead of throwing an exception.
Assigning an unauthorized workflow global variable won't throw an exception anymore but log a warning. The assignment is ignored.
More on JIRA ticket NXP-30589
Cluster-Wide Lock for the Workflow Model Import Since 2021.2
Workflow model import now uses a cluster-wide lock.
This improvement avoids the creation of several workflow definitions at the same time when starting several Nuxeo nodes simultaneously
In cluster mode, the worfklows are initialized non-concurrently in a cluster-wide critical section.
When a cluster node attempts to initialize its workflows and another node is already doing the same thing, it will wait for 1 min for the cluster-wide lock to be released and do its own initialization. If this timeout expires, then initialization fails with an exception.
The following nuxeo.conf
properties can be used to change this timeout:
org.nuxeo.workflow.cluster.start.duration=1m
In case where there's a startup crash while a lock is held, it may be necessary to manually cleanup the key/value store of its lock. The key corresponding to the lock is visible when using Redis with KEYS nuxeo:cluster:*
, in this case nuxeo:cluster:start-workflows-default
for the initialization of the workflows of the default repository. For a MongoDB key/value store, the keys are stored in the collection kv.cluster
More on JIRA ticket NXP-30135
Workflow Page Providers Now Used the ecm:isTrashed
Attribute
Workflow page providers now used the ecm:isTrashed
attribute.
More on JIRA ticket NXP-29183
Rendition
Behavior Changes
Process Picture Views in a Transaction With a Dedicated Timeout Since 2021.6
Picture views are now processed in a transaction with a dedicated timeout.
The maximum duration to produce the picture views is now limited by default to 5min. This limit is applied to the (deprecated) picture views generation work and also to the recomputeViews bulk action.
The limit can be tuned with:
nuxeo.picture.views.transaction.timeout.seconds=300
More on JIRA ticket NXP-30369
Add Explicit Timeout on Video Conversion Since 2021.6
The maximum duration to convert a video is now limited by default to 10min.
The limit can be tuned with:
nuxeo.video.transaction.timeout.seconds=600
Note that the limit is set at the transaction level (and not at the command level) because video conversion may involve multiple commands.
Elasticsearch
Elasticsearch client library version is now 7.9.2.
Once you have adapted your application to follow the behavior changes of Elasticsearch 7.x, you need to upgrade your existing Elasticsearch cluster to version 7.9 (7.7 or 7.8 are also supported).
Behavior Changes
Use Elastic word_delimiter_graph
instead of word_delimiter
to Avoid Indexing Error Since 2021.19
If you encounter indexing errors because of negative startOffset, your mapping needs to be updated.
If you have overridden the Elastic mapping then follow the recommended changes in the ticket. Then you need to reindex the repository, visit the related documentation for more information.
More on JIRA ticket NXP-30785
Default Elasticsearch Timeout Increased for the Write Operation Since 2021.5
A longer Elastic timeout is used for write operation.
By default, we have changed it from 60 sec to 120 sec.
More on JIRA ticket NXP-30470
Update Your Custom Elasticsearch Settings and Mapping
If you have a custom configuration for Elasticsearch, it needs to be adapted to follow the new 7.x rules.
Here are a few breaking changes to take into account when upgrading from Elasticsearch 6:
If you use the nGram tokenizer the type has been renamed from
nGram
tongram
.A phrase prefix search on a
keyword
field now raises an exception, this will happen on the following query:SELECT * FROM Document WHERE someKeywordField LIKE 'foo%'
The field needs to be of
text
type.
If you have to adapt your setting or mapping, you will need to re-index the repository to apply the change.
Don't Use the TransportClient
The connection to Elasticsearch should use the RestClient
(default since Nuxeo LTS 2017),
the TransportClient
is deprecated in version 7.x.
Technically, it can work if the index exists, but re-indexing is going to fail.
There is no advantage of using the TransportClient
over the default RestClient
.
Warnings in Unit Test with Embedded Elasticsearch Instance
Your unit tests may have the following WARN messages:
2020-11-16 11:10:43,561 [main] WARN [DanglingIndicesState] gateway.auto_import_dangling_indices is disabled, dangling indices will not be automatically detected or imported and must be managed manually
2020-11-16 11:10:43,828 [elasticsearch[nuxeoTestNode][clusterApplierService#updateTask][T#1]] WARN [ClusterApplierService] failed to notify ClusterStateListener
org.apache.lucene.util.SetOnce$AlreadySetException: The object cannot be set twice!
You can ignore them by editing your log4j2
test configuration to add:
<!-- Remove WARN on elastic embedded because dangling indices cannot be detected -->
<Logger name="org.elasticsearch.gateway.DanglingIndicesState" level="error" />
<!-- Remove WARN on elastic embedded because node and cluster identifiers change between test suites -->
<Logger name="org.elasticsearch.cluster.service.ClusterApplierService" level="error" />
Adapt Your Custom Elasticsearch Queries
If you use the Elasticsearch Passthrough, or if you use directly the elasticsearch query builder, make sure your query works in Elasticsearch 7.x.
One of the biggest changes is that the Elasticsearch document type has been removed,
for instance, this changes the URL pattern to access a Nuxeo document from http://elastic:9200/nuxeo/doc/<DOC_ID>
to: http://elastic:9200/nuxeo/<DOC_ID>
.
Make Elasticsearch Hints an Extension Point
Elasticsearch hints are now exposed as extension point. To contribute or override an existing Elasticsearch hint, you should provide a name for your Elasticsearch hint and an implementation of org.nuxeo.elasticsearch.api. ESHintQueryBuilder
.
The new way to expose the ES hints is by creating a contribution as below:
- We add new Extension Point to our existing ESComponent:
org.nuxeo.elasticsearch.ElasticSearchComponent
- The name of XP is
elasticSearchHints
. - At the end our "fuzzy" switch case, will be done like below:
<component name="org.nuxeo.elasticsearch.hint.contrib">
<require>org.nuxeo.elasticsearch.ElasticSearchComponent</require>
<extension point="elasticSearchHints" target="org.nuxeo.elasticsearch.ElasticSearchComponent">
<hint name="match" class="org.nuxeo.elasticsearch.hint.MatchESHintQueryBuilder" />
<hint name="match_phrase" class="org.nuxeo.elasticsearch.hint.MatchPhraseESHintQueryBuilder" />
<hint name="match_phrase_prefix" class="org.nuxeo.elasticsearch.hint.MatchPhrasePrefixESHintQueryBuilder" />
<hint name="multi_match" class="org.nuxeo.elasticsearch.hint.MultiMatchESHintQueryBuilder" />
<hint name="regex" class="org.nuxeo.elasticsearch.hint.RegexESHintQueryBuilder" />
<hint name="fuzzy" class="org.nuxeo.elasticsearch.hint.FuzzyESHintQueryBuilder" />
</extension>
</component>
More details in the Nuxeo How to documentation
More on JIRA ticket NXP-21874
Add property to set max_expansion on match_phrase_prefix operator Since 2021.17
Max expansions can be configured through the Configuration service with a contribution like
<extension target=org.nuxeo.runtime.ConfigurationService point=configuration>
<property name=elasticsearch.max_expansions>200</property>
</extension>
More on JIRA ticket NXP-30878
Upgrade Elasticsearch to 7.x
The procedure depends on when your instance has been created:
Elasticsearch Indexes Created in Elasticsearch 6.x (Nuxeo 10.10/LTS 2019)
Elasticsearch 7.x can read indexes created in version 6.0 or above.
This means that there is no migration to do if your Nuxeo instance has been created with Nuxeo LTS 2019.
Follow the Elasticsearch upgrade documentation to upgrade your Elasticsearch Cluster.
If you had to adapt your Elasticsearch settings or mappings for 7.x, you have to proceed to a repository re-index in order to apply the new configuration.
Migration of Elastic Indexes Created in Elasticsearch 5.x (Nuxeo 9.10/LTS 2017)
An Elasticsearch 7.x node will not start in the presence of indexes created in a version of Elasticsearch before 6.0. Indexes created in Elasticsearch 5.x or before will need to be reindexed with Elasticsearch 6.x in order to be readable by Elasticsearch 7.x.
Nuxeo uses 3 indexes:
The repository index, named
nuxeo
by default, doesn't need this migration because the repository will be re-indexed in the next step, so, once this index has been backed up, you can delete it.The sequence index named
nuxeo-uidgen
will be re-created at startup, so, once this index has been backed up, you can delete it.The audit index named
nuxeo-audit
needs to be migrated. Follow the re-index upgrade procedure.
Once the Elasticsearch cluster is upgraded, start Nuxeo LTS 2021 and proceed to a repository re-index.
Bulk Service (Aka "Bulk Action Framework")
Recommended Changes
Provide Options at nuxeo.conf
Level to Tune Bulk Re-indexing Since 2021.8
New options have been added to nuxeo.conf
to tune bulk Elasticsearch reindexing.
You now have the following options in nuxeo.conf
:
# Bulk Index action, fetching content (bulk/index computation)
elasticsearch.bulk.index.fetch.concurrency=4
elasticsearch.bulk.index.fetch.partitions=12
# Bulk Index action, submitting requests to elastic (bulk/bulkIndex computation)
elasticsearch.bulk.index.submit.concurrency=2
elasticsearch.bulk.index.submit.partitions=8
Where concurrency is the number of threads per node and partitions value fixes the maximum concurrency at the cluster level. Note that partitions value is taken into account only when creating Kafka topic.
More on JIRA ticket NXP-30536
Deletion BAF Action Now Runs With SYSTEM_USERNAME
org.nuxeo.ecm.core.storage.dbs.DBSSession#remove
launches the DeletionAction
BAF action to perform the db deletion of descendants of a folderish document being removed.
The problem is that we pass the current session's principal to run the action which will just skip the deletion of the document on which the current user does not have READ permission granted.
To fix that, we now run the DeletionAction
as SYSTEM_USER
.
More on JIRA ticket NXP-30661
Import
Behavior Changes
Initialize Filename With Blob Name in FileImporterContext
If the file name of the FileImporterContext
is missing, then it will now be filled with the Blob's file name.
This means that you no longer need to add control to avoid an empty filename outside of the FileImporterContext
class, for example see the snippet code below AudioImporter:
// code placeholder
@@ -57,8 +56,7 @@ public class AudioImporter extends AbstractFileImporter {
CoreSession session = context.getSession();
Blob blob = context.getBlob();
- String filename = FileManagerUtils.fetchFileName(
- StringUtils.defaultIfBlank(context.getFileName(), blob.getFilename()));
+ String filename = FileManagerUtils.fetchFileName(context.getFileName());
More on JIRA ticket NXP-26780
Don't Timeout During Long Imports
It is no more possible to call FileManager.Import
in a sychronous event, it has to be done in an asynchronous event. See NXP-28534.
More on JIRA ticket NXP-27346
Monitoring
Behavior Changes
Tagging for Datadog Metrics
Many metrics names have been renamed in order to support tagging which is necessary for Datadog and Prometheus support.
Visit the documentation for more information.
Metric names updated to use tag but that generates different metric names in Graphite:
# global metrics for all cluster
nuxeo.works.global.queue.scheduled{queue=$queue}
nuxeo.works.global.queue.running{queue=$queue}
nuxeo.works.global.queue.completed{queue=$queue}
# local metrics per node
nuxeo.works.local.queue.timer{queue=$queue}
Metric names updated to use tag but without changing metric name in Graphite:
# local metrics on computation
nuxeo.stream.computation.running{computation=$computation}
nuxeo.stream.computation.failure{computation=$computation}
nuxeo.stream.computation.skippedRecord{computation=$computation}
nuxeo.stream.computation.processRecord{computation=$computation}
nuxeo.stream.computation.processTimer{computation=$computation}
# elasticsearch service metrics timer, service in index, delete, bulkIndex, search, scroll and fetch:
nuxeo.elasticsearch.service.timer{service=service}
# cache
nuxeo.cache.*{cache=$cache}
More on JIRA ticket NXP-28639
Change Default Datadog Poll Intervar to 1min
The option to configure the metrics poll interval for Datadog is now metrics.datadog.pollInterval
and default is 60 (previously datadog.pollinterval=10
)
More on JIRA ticket NXP-28760
Authentication, User Management and Permissions
Recommended Changes
Use a Dedicated Work Queue for ACL Propagation Since 2021.4
A dedicated Work queue is used for ACL Propagation.
You now have options at nuxeo.conf
level to use a dedicated queue for DBS read ACL update:
# Queue for DBS Read ACL Update
nuxeo.work.queue.raclupdate.enabled=false
nuxeo.work.queue.raclupdate.threads=4
More on JIRA ticket NXP-30541
Nuxeo Streams
Behavior Changes
Keystore Is Now Optional With Kafka SSL Enabled
The SSL keystore is not mandatory for all Kafka setups. Kafka can work with several security configurations independently.
The best way to infer the need for an SSL keystore is to check if its path is set up in the configuration.
More on JIRA ticket NXP-27904
Namespaces for Stream and Consumer Group Names Stream and Consumer Group Names Have Changed
To upgrade:
- Wait for any asynchronous processing to be done, there must be no activity and no error,
- Stop the Nuxeo cluster,
- Drop the entire Kafka topics or Chronicle Queue directory,
- Upgrade the Nuxeo cluster, streams will be created with new names.
Note that custom code is backward compatible and will continue to work even with name without namespace, but names have been enforced and must match:
[A-Za-z0-9][A-Za-z0-9_]*
or you get:
IllegalArgumentException: Invalid name without namespace: 'foo.bar'
More on JIRA ticket NXP-28877
WorkManager
Behavior Changes
Support Filtering When Reprocessing DLQ Work Since 2021.4
DLQ works can be reprocessed thanks to new filters.
The RunWorkInFailure
operation has been extended to support 2 more options:
dryRun
: when true displays statistics on Works to reprocess, note that nothing is processed or modified when this option is activated.categoryFilter
: a list of Work categories (comma separated) to filter Works that will be reprocessed
Example of invocation:
curl -X POST "http://localhost:8080/nuxeo/site/automation/WorkManager.RunWorkInFailure" -u Administrator:Administrator -H 'content-type: application/json' -d '{"params":{"dryRun": true, "categoryFilter": "elasticSearchIndexing"},"context":{}}'
More on JIRA ticket NXP-30450
StreamWorkManager Workaround for Large Work
The wrongly named class LogConfigDescriptor.StreamDescriptor
has been renamed to LogConfigDescriptor.LogDescriptor
.
More on JIRA ticket NXP-26691
Addons
Web UI - nuxeo-document-preview
Should Not Load nuxeo-pdf-viewer
For Unsupported MIME Types Since 2021.10
Web UI does not display anymore a preview for unsupported MIME types.
PDF rendition is no longer listed in available renditions when no converter is found for a document's main blob given MIME type.
More on JIRA ticket NXP-30643
Web UI - Take Into Account the Commentable Facet
Comments will only be available for document with the Commentable facet.
Note that on 10.10, this check will only be done when setting the org.nuxeo.web.ui.enforceCommentable
conf property to true:
<require>org.nuxeo.web.ui.properties.contrib</require>
<extension target="org.nuxeo.runtime.ConfigurationService" point="configuration">
<property name="org.nuxeo.web.ui.enforceCommentable">true</property>
</extension>
to avoid a breaking change.
More on JIRA ticket NXP-27963
Web UI - Leverage Validation Report Client Side and Allow Async Layout Validation
- Layout validate method can now return a Promise in which case it must resolve to true to validate the layout.
- Server-side schema constraint violations are now reported at the top of the create and edit form layout.
- Server-side, you can now trigger a global validation error by throwing the following exception:
throw new DocumentValidationException("your.error.message");
in a synchronous listener on aboutToCreate or beforeDocumentModification. Note that your listener must bubble the exception to prevent the creation or modification. The error message of the exception will be translated Web UI (client) side and reported at the top of the create or edit form.
More on JIRA ticket NXP-27982
Web UI - Integrate Spreadsheet App Code in Nuxeo-Spreadsheet Web UI Addon
Nuxeo Spreadsheet is no longer a marketplace package, it is bundled with Web UI behind a feature flag.
To enable Nuxeo Spreadsheet the new configuration property org.nuxeo.web.ui.spreadsheet.enabled
should be set to true
:
<extension target="org.nuxeo.runtime.ConfigurationService" point="configuration"> <property name="org.nuxeo.web.ui.spreadsheet.enabled">true</property> </extension>
More on JIRA ticket NXP-27416
Web UI - Fix Selection Toolbar in Ordered Folders
Content distributed to "selectionActions" slot in <nuxeo-results>
is no longer wrapped with a <nuxeo-actions-menu>
. When overriding the default content be sure to wrap the actions or the <nuxeo-slot>
with a <nuxeo-actions-menu>
if you want to keep previous behavior.
More on JIRA ticket NXP-28977
Web UI - Allow using automation API in nuxeo-page-provider
This introduces a new Web UI configuration property org.nuxeo.web.ui.pageprovider.method
which by default is GET
but can be changed to POST
, in which case search requests will leverage the Automation API.
<extension target="org.nuxeo.runtime.ConfigurationService" point="configuration">
<property name="org.nuxeo.web.ui.pageprovider.method">POST</property>
</extension>
More on JIRA ticket NXP-29126
Retention - Directories Shouldn’t Be Internationalized
The vocabularies RetentionEvent
and RetentionEnd
are now normal vocabularies (not l10n one any more).
The corresponding tables must be dropped and they will be recreated on next startup.
More on JIRA ticket NXP-28809
Miscellaneous
Behavior Changes
Move RequestContext and RequestContextFilter to nuxeo-platform-web-common
RequestContext
and RequestContextFilter
have been moved from WebEngine to nuxeo-platform-web-common
.
They have to be imported from org.nuxeo.ecm.platform.web.common.RequestContext
and org.nuxeo.ecm.platform.web.common.RequestCleanupHandler
(they were previously under org.nuxeo.ecm.webengine.jaxrs.context
).
Maven dependency to add:
<dependency>
<groupId>org.nuxeo.ecm.platform</groupId>
<artifactId>nuxeo-platform-web-common</artifactId>
</dependency>
More on JIRA ticket NXP-26710
Fix Collections Drawer Refresh When Trashing/Restoring a Collection
The nuxeo-documents-untrashed
event payload is now consistent with the other similar event payloads and, instead of having only documents uids, contains the complete documents.
More on JIRA ticket NXP-28902
Quota Exception Not Raised When Version Is Incremented
Behavior of quota computation and check has changed for versioning.
Now we compute and check the quotas on the aboutToCheckIn
event instead of computing the quotas on the documentCheckedIn
one and checking the quotas on the documentCheckedOut
one.
More on JIRA ticket NXP-26841
Fix Retrieval of Personal Workspace for User With Special Characters
Retrieving a User Workspace through UserWorkspaceService requires that the user (NuxeoPrincipal) exists in the Nuxeo Platform.
More on JIRA ticket NXP-26003
Don't Do Orphan Versions Cleanup by Default
Orphan versions cleanup is now disabled by default, and can be re-enabled (if its performance is acceptable) by doing:
<require>org.nuxeo.ecm.core.orphanVersionsCleanup</require>
<extension point="listener" target="org.nuxeo.ecm.core.event.EventServiceComponent">
<listener name="orphanVersionsCleanup" enabled="true" />
</extension>
More on JIRA ticket NXP-24819
Fix Some Nuxeo Maven Groups
Old groupId:artifactId --> new groupId:artifactId for the following maven modules:
org.nuxeo:nuxeo-dmk-adaptor
-->org.nuxeo.ecm.platform:nuxeo-dmk-adaptor
org.nuxeo:nuxeo-platform-lang-ext
-->org.nuxeo.ecm.platform:nuxeo-platform-lang-ext
org.nuxeo:nuxeo-platform-lang-ext-incomplete
-->org.nuxeo.ecm.platform:nuxeo-platform-lang-ext-incomplete
org.nuxeo.binary.metadata:nuxeo-binary-metadata
-->org.nuxeo.ecm.platform:nuxeo-binary-metadata
More on JIRA ticket NXP-29046
Document.Lock Can Be Call Several Times for the Same User
The behavior of AbstractSession.setLock
has been modified to meet the requirement "Document.Lock called twice should not fail".
Now if you try to lock a document locked by you, you will only get your original lock.
More on JIRA ticket NXP-24359
Document Path Not Available in emptyDocumentmodelCreated Event Context
DocumentModel#getRef
behavior has changed when called on a non-saved document. Before it was always returning null, now it may return a non-null PathRef value.
If DocumentModel#getRef
was wrongly used to test if a document is saved or not, code must be updated to rely on DocumentModel#getId
instead.
More on JIRA ticket NXP-26903
Upgrade to Apache PDFBox 2.0.24 Since 2021.11
The upgrade of Apache PDFBox from 1.8.16 to 2.0.24 introduces breaking changes to the library, code relying on it must be updated.
See the Migration to PDFBox 2.0.0 guide.
More on JIRA tickets NXP-28825 and NXP-30662
Upgrade to mockserver-netty 5.10.0
import org.mockserver.client.server.MockServerClient;
becomes:
import org.mockserver.client.MockServerClient;
Use try-with-resource on MockServerClient
:
try {
MockServerClient client = new MockServerClient("localhost", PORT);
…
}
becomes:
try (MockServerClient client = new MockServerClient("localhost", PORT)) {
…
}
More on JIRA ticket NXP-28818
Remove the assignment to the ZIP extra field to produce correct ZIP
You can now disable the extra field setting when doing Nuxeo IO export by contributing the following:
<extension target=org.nuxeo.runtime.ConfigurationService point=configuration>
<property name=nuxeo.core.io.archive.extra.files.count>false</property>
</extension>
This could be interesting if you want to open the produced archive with external tools such as Archive Utility.app.
This property has true
as default as disabling this behavior may impact performance when re-importing to Nuxeo the archive.
More on JIRA ticket NXP-30713
Bulk SetPropertiesAction - VersioningOption parameter does not take effect when Versioning Service is extended via XML Extension
As documented in the automatic versioning system, the versioning policy order should be higher than 10
, order lower than 10 is reserved for internal purposes.
This restriction is now enforced on LTS 2021, a server having a versioning policy contribution that doesn't respect this rule will NOT start.
On LTS 2019, an ERROR message will be logged during Nuxeo startup.
In addition to disable the automatic versioning system for setProperties
action, we also have disabled the system for the following system related updates:
- add/remove a document to/from a collection
- recompute pictureViews
- add/remove notifications subscriptions
- add/remove tags
- update quotas
- recompute thumbnails
- recompute transcodedVideos
- recompute videoInfos
In a more general way, the system has been disabled in the code paths where auto checkout was disabled. This can impact positively performance by avoiding version creation on the above low-level updates.
More on JIRA ticket NXP-30700
Farewell
JAAS Since 2021.1
JAAS has been removed (the use of LoginContext, security domains, LoginModules, etc.) and replaced per a direct call to NuxeoAuthenticationPlugins
.
New methods:
Framework.loginSystem()
Framework.loginSystem(originatingUser)
Framework.loginUser(username)
NuxeoPrincipal.getCurrent()
NuxeoPrincipal.isCurrentAdministrator()
The above loginSystem
and loginUser
methods now return a NuxeoLoginContext
that is AutoCloseable
and can therefore be used in a try-with-resources.
Deprecated methods:
Framework.login()
->Framework.loginSystem()
Framework.loginAs(originatingUser)
->Framework.loginSystem(originatingUser)
Framework.loginAsUser(username)
->Framework.loginUser(username)
Framework.login(username, password)
->Framework.loginUser(username)
ClientLoginModule.clearThreadLocalLogin()
->LoginComponent.clearPrincipalStack()
(INTERNAL)ClientLoginModule.getThreadLocalLogin()
->LoginComponent
(INTERNAL)ClientLoginModule.getCurrentLogin()
->LoginComponent.getCurrentPrincipal()
ClientLoginModule.getCurrentPrincipal()
->NuxeoPrincipal.getCurrent()
ClientLoginModule.isCurrentAdministrator()
->NuxeoPrincipal.isCurrentAdministrator()
LoginStack
These extension points or part of their contributions are removed:
<loginModulePlugin>
in the element<authenticationPlugin>
of extension pointauthenticators
oforg.nuxeo.ecm.platform.ui.web.auth.service.PluggableAuthenticationService
- the extension point domains of
org.nuxeo.runtime.LoginComponent
(which included registration ofLoginModule
classes) - the extension point plugin of
org.nuxeo.ecm.platform.login.LoginPluginRegistry
(which included registration ofLoginPlugin
classes)
Behavior change:
NuxeoAuthenticationPlugin.handleRetrieveIdentity
should now contain all the authentication code, and return aUserIdentificationInfo with credentialsChecked = true
(using the 1-arg constructor) if the credentials have already been checked by the auth plugin itself. Otherwise the method may return aUserIdentificationInfo
that includes a username and password, to let the generic filter check the password against the UserManager.
More on JIRA ticket NXP-27942
Remove Deprecated org.nuxeo.ecm.core.model.LockManager
The internal interface org.nuxeo.ecm.core.model.LockManager
has been removed, org.nuxeo.ecm.core.api.lock.LockManager
should be used instead.
More on JIRA ticket NXP-29654
Remove Old JDBCClusterInvalidator for VCS
The configuration property repository.clustering.delay
is now fully unused (all clustering invalidation propagation is immediate).
The unused class JDBCClusterInvalidator has been removed.
The configuration property repository.clustering.delay
is not used anymore, and in the <repository> extension point, the <clustering> part doesn't exist anymore.
(Note that the <clustering> id= and enabled= attributes were removed from the <repository> extension point by NXP-25499.)
More on JIRA ticket NXP-28891
Dependencies Upgrade Versions
Component | Nuxeo Platform LTS 2019 | Nuxeo Platform LTS 2021 |
---|---|---|
ant | 1.9.16 | 1.10.11 since 2021.11 |
ant-maven-assembly-plugin | 2.1.2 | 2.1.3 since 2021.1, 2.1.5 since 2021.8 |
Apache HttpComponents | 4.5.6 | 4.5.11 |
Apache HttpCore | 4.4.10 | 4.4.13 |
ASM | 6.2.1 | 7.3.1 |
assertj-core | 3.8.0 | 3.17.2 |
avro | 1.8.2 | 1.9.2 |
AWS SDK | 1.11.516 | 1.11.885 |
Axiom | 1.2.20 | 1.2.22 |
Batik | 1.10 | 1.12 |
BouncyCastle | 1.60 | 1.69 |
bsh | 2.0b1 | 2.0b4 |
cglib-nodep | 2.2.2 | 3.3.0 |
chronicle | 2.17.92 | 2.17.465 |
Commons Codec | 1.11 | 1.14 |
Commons Collections | 4.1 | 4.4 |
Commons Compress | 1.20 | 1.21 |
Commons CSV | 1.5 | 1.7 |
Commons Fileupload | 1.3.3 | 1.4 |
Commons Lang3 | 3.8 | 3.9 |
Commons Pool2 | 2.6.0 | 2.8.0 |
Commons Text | 1.4 | 1.8 |
Commons VFS2 | 2.2 | 2.6.0 |
com.sun.xml.bind:jaxb-impl | 2.3.0.1 | 2.3.3 |
CORS Filter | 2.6 | 2.9 |
dependency-check-maven | 3.3.2 | 5.2.4 |
dnsjava | 2.1.8 | 2.1.9 |
dom4j | 1.6.1 | 2.1.1 |
Dumbster | 1.6 | 1.7 |
ESAPI | 2.1.0.1 | 2.2.1.1 |
fast-classpath-scanner | 2.0.4 | ClassGraph 4.8.60 |
freemarker | 2.3.28 | 2.3.29 |
Gatling | 2.3.1 | 3.3.1 |
Gatling plugin | 2.2.4 | 3.0.4 |
Guava | 26.0 | 28.2 |
ICU4J | 62.1 | 67.1 |
ISOParser | 1.9.27 | 1.9.41 |
Jackrabbit | 2.17.5 | 2.20.0 |
Jackson | 2.9.10 | 2.12.0 |
jacoco-maven-plugin | 0.8.1 | 0.8.2 |
JAI | 1.1.2_01 | 1.1.3 |
jansi | 1.17.1 | 1.18 |
javassist | 3.21.0-GA | 3.26.0-GA |
Java JWT | 3.4.0 | 3.11.0 |
javax.json | 1.1.2 | 1.1.4 |
javax.mail:mail | 1.4.5 | 1.4.7 |
Javax transaction | 1.1 | 1.3 |
javax.xml.bind:jaxb-api | 2.2.11 | jakarta.xml.bind:jakarta.xml.bind-api:2.3.3 |
jaxen | 1.1.6 | 1.2.0 |
JClouds | 2.1.1 | 2.2.0 |
Jettison | 1.3.7 | 1.4.0 |
JGiven | 0.16.0 | 0.18.2 |
JMock | 2.8.4 | 2.12.0 |
joda-time | 2.9.2 | 2.10.6 |
Jolokia | 1.3.3 | 1.6.2 | json-simple | 1.1 | 1.1.1 | json-smart | 1.3.2 | 1.3.3 |
JSONAssert | 1.2.3 | 1.5.0 |
junit | 4.12 | 4.13 |
Jxls | jxls 1.0.6-NX01 | jxls 1.0.6-NX02, jxls2 2.8.1 |
Log4j | 2.11.1 | 2.13.3 |
maven-compiler-plugin | 3.1 | 3.8.0 |
maven-dependency-analyzer | 1.11.0 | 1.11.1 |
maven-dependency-plugin | 2.10 | 5.2.4 |
maven-shade-plugin | 3.1.1 | 3.2.1 |
mockserver-netty | 3.10.4 | 5.10.0 |
Metrics | 4.0.3 | Metrics5 5.0.0-rc3 |
metrics-datadog | 1.0.2 | 2.0.0-RC1 |
MongoDB Java Driver | 3.8.1 | 3.12.1 |
Mongo quartz | 2.0.0-NX3 | 2.1.0-NX1 |
MVEL | 2.4.2.Final | 2.4.5.Final |
mysql-connector-java | 8.0.13 | 8.0.19 |
onedrive | 1.0 | 2.0 |
OpenPDF | 1.2.1 | 1.3.22 |
PDFBox | 1.8.16 | 2.0.24 |
pdf-html | 1.2.1 | 1.2.16 |
POI | 3.17 | 4.1.2 |
PostgreSQL Java Driver | 42.2.5 | 42.2.9 |
quartz | 2.3.0 | 2.3.2 |
Restlet | 2.4.1 | 2.4.2 |
scala-maven-plugin | 3.3.2 | 4.3.1 |
SLF4J | 1.7.21 | 1.7.30 |
snakeyaml | 1.21 | 1.25 |
stax-ex | 1.7.8 | 1.8.2 |
Surefire | 2.22.0 | 2.22.2 |
Wink Client | 1.3.0 | 1.4 |
xerces | 2.12.0 | 2.12.0-nx1 |
XBean Naming | 3.18 | 4.15 |
Xmlbeans | 3.0.1 | 3.1.0 |
xmlsec | 2.1.7 | 2.2.3 |
XOM | 1.2.5 | 1.3.2 |
XStream | 1.4.11 | 1.4.18 since 2021.11 |
webdav-jaxrs | 1.2.1 | 1.2.1-nx1 |
Dependencies Removal
Removed component |
---|
com.sun.xml.bind:jaxb-core |