You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by nm...@apache.org on 2023/06/02 07:43:44 UTC

[ofbiz-framework] branch trunk updated (af1a19596d -> 6b00446509)

This is an automated email from the ASF dual-hosted git repository.

nmalin pushed a change to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git


    from af1a19596d Fixed: Form html validation not working correctly inside a modal (OFBIZ-12825)
     new e5dd1799bd Improved: Convert createMissingCategoryContentAltUrlInline service from mini-lang to groovy DSL (OFBIZ-11387)
     new 73ab86737a Improved: Convert createCommContentDataResource service from mini-lang to groovy DSL (OFBIZ-11378)
     new 6b00446509 Improved: Convert ContentServices.xml mini lang to groovy DSL (OFBIZ-12827)

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../groovyScripts/content/ContentServices.groovy   | 215 +++++++++++-
 .../content/minilang/content/ContentServices.xml   | 379 ---------------------
 applications/content/servicedef/services.xml       |  10 +-
 .../content/servicedef/services_commevent.xml      |   4 +-
 .../content/servicedef/services_content.xml        |  21 +-
 5 files changed, 231 insertions(+), 398 deletions(-)
 delete mode 100644 applications/content/minilang/content/ContentServices.xml


[ofbiz-framework] 02/03: Improved: Convert createCommContentDataResource service from mini-lang to groovy DSL (OFBIZ-11378)

Posted by nm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nmalin pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git

commit 73ab86737a4d527cfa24b07fb3d9517de7a79254
Author: Nicolas Malin <ni...@nereide.fr>
AuthorDate: Thu Jun 1 19:26:36 2023 +0200

    Improved: Convert createCommContentDataResource service from mini-lang to groovy DSL (OFBIZ-11378)
    
    Thanks to Devanshu Vyas for the patch
---
 .../groovyScripts/content/ContentServices.groovy   | 33 ++++++++++++++++++++--
 .../content/servicedef/services_commevent.xml      |  4 +--
 2 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/applications/content/groovyScripts/content/ContentServices.groovy b/applications/content/groovyScripts/content/ContentServices.groovy
index 9fa1c46283..65e5808c71 100644
--- a/applications/content/groovyScripts/content/ContentServices.groovy
+++ b/applications/content/groovyScripts/content/ContentServices.groovy
@@ -150,8 +150,7 @@ Map createContentAlternativeUrl() {
             .queryIterator()
 
     GenericValue content
-    while (contents.hasNext()) {
-        content = contents.next()
+    while (content = contents.next()) {
         String localeString = content.localeString ?: defaultLocaleString
         List contentAssocDataResources = select('contentIdStart', 'dataResourceId', 'localeString', 'drObjectInfo', 'caFromDate', 'caThruDate')
                 .from('ContentAssocDataResourceViewTo')
@@ -637,4 +636,34 @@ List createMissingContentAltUrlInline(String contentId) {
                 contentCreatedList.addAll(createMissingContentAltUrlInline(contentIdTo))
             }
     return contentCreatedList
+}
+
+/**
+ * This method first creates Content, DataResource and ElectronicText, ImageDataResource, etc. entities (if needed)
+ * by calling persistContentAndAssoc.
+ *
+ * It then takes the contentId coming out of that service, the passed in communicationEventId
+ * and calls the "createCommEventContentAssoc" service to tie the CommunicationEvent and Content entities together.
+ */
+Map createCommContentDataResource() {
+
+    // let's take a guess at what the dataResourceTypeId should be if it is empty
+    if (!parameters.dataResourceTypeId && parameters.drMimeTypeId) {
+        parameters.dataResourceTypeId = parameters.drMimeTypeId.startsWith('text') ?
+                'ELECTRONIC_TEXT' : 'IMAGE_OBJECT'
+    }
+    Map persistServiceResult = run service: 'persistContentAndAssoc', with: parameters
+    Map serviceResult = run service: 'createCommEventContentAssoc', with: [contentId: persistServiceResult.contentId,
+                                                       communicationEventId: parameters.communicationEventId,
+                                                       sequenceNum: parameters.sequenceNum]
+    return success([contentId: persistServiceResult.contentId,
+                    dataResourceId: persistServiceResult.dataResourceId,
+                    drDataResourceId: persistServiceResult.drDataResourceId,
+                    caContentIdTo: persistServiceResult.caContentIdTo,
+                    caContentId: persistServiceResult.caContentId,
+                    caContentAssocTypeId: persistServiceResult.caContentAssocTypeId,
+                    caFromDate: persistServiceResult.caFromDate,
+                    caSequenceNum: persistServiceResult.caSequenceNum,
+                    roleTypeList: persistServiceResult.roleTypeList,
+                    fromDate: serviceResult.fromDate])
 }
\ No newline at end of file
diff --git a/applications/content/servicedef/services_commevent.xml b/applications/content/servicedef/services_commevent.xml
index 3e0f36645f..d44a226b1f 100644
--- a/applications/content/servicedef/services_commevent.xml
+++ b/applications/content/servicedef/services_commevent.xml
@@ -35,8 +35,8 @@ under the License.
         Second, it must create a CommEventContentAssoc record.
             The fromData should be defaulted if not passed in.
     -->
-    <service name="createCommContentDataResource" engine="simple"
-                location="component://content/minilang/content/ContentServices.xml" invoke="createCommContentDataResource" auth="true">
+    <service name="createCommContentDataResource" engine="groovy"
+             location="component://content/groovyScripts/content/ContentServices.groovy" invoke="createCommContentDataResource">
         <description>Create CommunicationEvent and Content</description>
         <implements service="persistContentAndAssoc"/>
         <attribute name="communicationEventId" type="String" mode="IN" optional="false">


[ofbiz-framework] 01/03: Improved: Convert createMissingCategoryContentAltUrlInline service from mini-lang to groovy DSL (OFBIZ-11387)

Posted by nm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nmalin pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git

commit e5dd1799bde729e2e88c8e01d0304b40a4b88b29
Author: Nicolas Malin <ni...@nereide.fr>
AuthorDate: Thu Jun 1 19:24:13 2023 +0200

    Improved: Convert createMissingCategoryContentAltUrlInline service from mini-lang to groovy DSL (OFBIZ-11387)
    
    Thanks to Devanshu Vyas for the patch
---
 .../groovyScripts/content/ContentServices.groovy   | 105 +++++++++++++++++++++
 .../content/servicedef/services_content.xml        |   4 +-
 2 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/applications/content/groovyScripts/content/ContentServices.groovy b/applications/content/groovyScripts/content/ContentServices.groovy
index 9c3ab047e1..9fa1c46283 100644
--- a/applications/content/groovyScripts/content/ContentServices.groovy
+++ b/applications/content/groovyScripts/content/ContentServices.groovy
@@ -533,3 +533,108 @@ Map updateSimpleTextContent() {
     }
     return result
 }
+
+/**
+ * create missing content alternative urls.
+ */
+Map createMissingContentAltUrls() {
+    List contentCreatedList = []
+    if (parameters.prodCatalogId) {
+        List productCategorieIds = []
+        // Get all categories
+        from('ProdCatalogCategory')
+                .where(prodCatalogId: parameters.prodCatalogId)
+                .getFieldList('productCategoryId')
+                .each { String productCategoryId ->
+                    productCategorieIds.addAll(createMissingCategoryContentAltUrlInline(productCategoryId))
+                }
+        // Create Content Alternative URLs for Product Category Content
+        EntityCondition condition = new EntityConditionBuilder().AND {
+            NOT_EQUAL(prodCatContentTypeId: 'ALTERNATIVE_URL')
+            IN(productCategoryId: productCategorieIds)
+        }
+        from('ProductCategoryContentAndInfo')
+                .where(condition)
+                .filterByDate()
+                .orderBy('-fromDate')
+                .getFieldList('contentId')
+                .each { String contentId ->
+                    Map serviceResult = run service: 'createContentAlternativeUrl', with: [contentId: contentId]
+                    contentCreatedList << serviceResult.contentCreated
+                }
+
+        //Create Content Alternative URLs for Product Content
+        condition = new EntityConditionBuilder().AND {
+            IN(productCategoryId: productCategorieIds)
+        }
+        List productIds = from('ProductCategoryMember')
+                .where(condition)
+                .filterByDate()
+                .orderBy('-fromDate')
+                .getFieldList('productId')
+
+        condition = new EntityConditionBuilder().AND {
+            NOT_EQUAL(productContentTypeId: 'ALTERNATIVE_URL')
+            IN(productId: productIds)
+        }
+        from('ProductContentAndInfo')
+                .where(condition)
+                .filterByDate()
+                .orderBy('-fromDate')
+                .getFieldList('contentId')
+                .each { String contentId ->
+                    Map serviceResult = run service: 'createContentAlternativeUrl', with: [contentId: contentId]
+                    contentCreatedList << serviceResult.contentCreated
+                }
+    }
+
+    //Create Content Alternative URLs for WebSite Content and children
+    if (parameters.webSiteId) {
+        from('WebSiteContent')
+                .where(webSiteId: parameters.webSiteId)
+                .getFieldList('contentId')
+                .each { String contentId ->
+                    contentCreatedList.addAll(createMissingContentAltUrlInline(contentId))
+                }
+    }
+    long totalParse = contentCreatedList.size()
+    long contentsUpdated = contentCreatedList.stream().filter {it == 'Y'}.count()
+    return success([contentsUpdated: contentsUpdated, contentsNotUpdated: totalParse - contentsUpdated])
+}
+
+/**
+ * recursive call to get all productCategoryId from children
+ * @param parentProductCategoryId
+ * @return
+ */
+List createMissingCategoryContentAltUrlInline(String parentProductCategoryId) {
+    List productCategoryIds = []
+    from('ProductCategoryRollup')
+            .where(parentProductCategoryId: parentProductCategoryId)
+            .filterByDate()
+            .getFieldList('productCategoryId')
+            .each { String productCategoryId ->
+                productCategoryIds << productCategoryId
+                productCategoryIds.addAll(createMissingCategoryContentAltUrlInline(productCategoryId))
+            }
+    return productCategoryIds
+}
+
+/**
+ * call createContentAlternativeUrl on all subContent and return the result for analyse
+ * @param contentId
+ * @return
+ */
+List createMissingContentAltUrlInline(String contentId) {
+    List contentCreatedList = []
+    from('ContentAssoc')
+            .where(contentId: contentId)
+            .filterByDate()
+            .getFieldList('contentIdTo')
+            .each { String contentIdTo ->
+                Map serviceResult = run service: 'createContentAlternativeUrl', with: [contentId: contentIdTo]
+                contentCreatedList << serviceResult.contentCreated
+                contentCreatedList.addAll(createMissingContentAltUrlInline(contentIdTo))
+            }
+    return contentCreatedList
+}
\ No newline at end of file
diff --git a/applications/content/servicedef/services_content.xml b/applications/content/servicedef/services_content.xml
index 09350317e8..23dbfbf0ca 100644
--- a/applications/content/servicedef/services_content.xml
+++ b/applications/content/servicedef/services_content.xml
@@ -349,8 +349,8 @@
     </service>
 
     <!-- Alternative URLs services -->
-    <service name="createMissingContentAltUrls" engine="simple"
-                location="component://content/minilang/content/ContentServices.xml" invoke="createMissingContentAltUrls" auth="true" use-transaction="false">
+    <service name="createMissingContentAltUrls" engine="groovy" auth="true" use-transaction="false"
+                location="component://content/groovyScripts/content/ContentServices.groovy" invoke="createMissingContentAltUrls">
         <description>Create missing Content Alternative URLs</description>
         <attribute name="prodCatalogId" mode="IN" type="String" optional="true"/>
         <attribute name="webSiteId" mode="IN" type="String" optional="true"/>


[ofbiz-framework] 03/03: Improved: Convert ContentServices.xml mini lang to groovy DSL (OFBIZ-12827)

Posted by nm...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

nmalin pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git

commit 6b00446509dc0c1dd079cb098f6c3764a6d63f85
Author: Nicolas Malin <ni...@nereide.fr>
AuthorDate: Thu Jun 1 19:38:51 2023 +0200

    Improved: Convert ContentServices.xml mini lang to groovy DSL (OFBIZ-12827)
    
    Finish to convert ContentServices.xml with migrate service :
        - copyContentAndElectronicTextandAssoc
        - removeContentAndRelated
        - assocContent
        - getPublicForumMessage -> move only on service definition
    
    Move as deprecated :
        - assocContent
        - getPublicForumMessage
        - checkContentPermission
        - checkAssocPermission
---
 .../groovyScripts/content/ContentServices.groovy   |  77 +++++
 .../content/minilang/content/ContentServices.xml   | 379 ---------------------
 applications/content/servicedef/services.xml       |  10 +-
 .../content/servicedef/services_content.xml        |  17 +-
 4 files changed, 91 insertions(+), 392 deletions(-)

diff --git a/applications/content/groovyScripts/content/ContentServices.groovy b/applications/content/groovyScripts/content/ContentServices.groovy
index 65e5808c71..dfecd7d19c 100644
--- a/applications/content/groovyScripts/content/ContentServices.groovy
+++ b/applications/content/groovyScripts/content/ContentServices.groovy
@@ -666,4 +666,81 @@ Map createCommContentDataResource() {
                     caSequenceNum: persistServiceResult.caSequenceNum,
                     roleTypeList: persistServiceResult.roleTypeList,
                     fromDate: serviceResult.fromDate])
+}
+
+/**
+ * Remove a Content Record, related resource(s) and assocs.
+ * @return
+ */
+Map removeContentAndRelated() {
+    GenericValue content = from('Content').where(parameters).queryOne()
+    if (content) {
+        content.removeRelated('ContentAttribute')
+        content.removeRelated('ContentRole')
+        content.removeRelated('ContentKeyword')
+        content.removeRelated('FromContentAssoc')
+        content.removeRelated('ToContentAssoc')
+        content.remove()
+        GenericValue dataResource = content.getRelatedOne('DataResource', false)
+        if (dataResource) {
+            dataResource.removeRelated("ElectronicText")
+            dataResource.removeRelated("ImageDataResource")
+            dataResource.removeRelated("OtherDataResource")
+            dataResource.removeRelated("VideoDataResource")
+            dataResource.removeRelated("DataResourceRole")
+            dataResource.remove()
+        }
+    }
+    return success()
+}
+
+/**
+ * copy a content, electronic text and assocs and set status in progress
+ * @return
+ */
+Map copyContentAndElectronicTextandAssoc() {
+    Map getContentResult = run service: 'getContent', with: parameters
+    GenericValue content = getContentResult.view
+    if (content.dataResourceId) {
+        Map getElectronicTextResult = run service: 'getElectronicText', with: content.getAllFields()
+        Map dataResourceResult = run service: 'createDataResource', with: [dataResourceTypeId: 'ELECTRONIC_TEXT']
+        run service: 'createElectronicText', with: [dataResourceId: dataResourceResult.dataResourceId,
+                                                    textData      : getElectronicTextResult.textData]
+        content.dataResourceId = dataResourceResult.dataResourceId
+    }
+    Map contentResult = run service: 'createContent', with: [*: content.getAllFields(),
+                                                             contentId: null,
+                                                             statusId: null]
+    from('ContentAssoc')
+            .where(contentId: content.contentId)
+            .queryList()
+            .each {
+                run service: 'createContentAssoc', with: [*: it.getAllFields(),
+                                                          contentId: contentResult.contentId]
+            }
+    from('ContentAssoc')
+            .where(contentIdTo: content.contentId)
+            .queryList()
+            .each {
+                run service: 'createContentAssoc', with: [*: it.getAllFields(),
+                                                          contentIdTo: contentResult.contentId]
+            }
+    return success([contentId: contentResult.contentId])
+}
+
+/**
+ * @deprecated use createContentAssoc instead
+ * Associate Content
+ * @return
+ */
+Map assocContent() {
+    GenericValue currentContent = from('Content').where(contentId: parameters.contentIdTo).cache().queryOne()
+    GenericValue fromContent = from('Content').where(contentId: parameters.contentIdFrom).cache().queryOne()
+
+    if (currentContent && fromContent) {
+        Map serviceResult = run service: 'createContentAssoc', with: [*: parameters,
+                                                                      contentId: fromContent.contentId]
+        return serviceResult
+    }
+    return error('Contents to assoc not exist')
 }
\ No newline at end of file
diff --git a/applications/content/minilang/content/ContentServices.xml b/applications/content/minilang/content/ContentServices.xml
deleted file mode 100644
index 17f1abf29e..0000000000
--- a/applications/content/minilang/content/ContentServices.xml
+++ /dev/null
@@ -1,379 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-  http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing,
-  software distributed under the License is distributed on an
-  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  KIND, either express or implied.  See the License for the
-  specific language governing permissions and limitations
-  under the License.
-  -->
-
-<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">
-
-    <simple-method method-name="removeContentAndRelated" short-description="Remove a Content Record, related resource(s) and assocs.">
-        <entity-one entity-name="Content" value-field="content"/> 
-        <if-not-empty field="content">
-            <remove-related value-field="content" relation-name="ContentAttribute"/>
-            <remove-related value-field="content" relation-name="ContentRole"/>
-            <remove-related value-field="content" relation-name="ContentKeyword"/>
-            <remove-related value-field="content" relation-name="FromContentAssoc"/>
-            <remove-related value-field="content" relation-name="ToContentAssoc"/>
-            <remove-value value-field="content"/>
-            <get-related-one value-field="content" relation-name="DataResource" to-value-field="dataResource"/>
-            <if-not-empty field="dataResource">
-                <get-related-one value-field="dataResource" relation-name="ImageDataResource" to-value-field="imageDataResource"/>
-                <if-not-empty field="imageDataResource">
-                    <remove-value value-field="imageDataResource"/>
-                </if-not-empty>
-                <get-related-one value-field="dataResource" relation-name="ElectronicText" to-value-field="electronicText"/>
-                <if-not-empty field="electronicText">
-                    <remove-value value-field="electronicText"/>
-                </if-not-empty>
-                <remove-related value-field="dataResource" relation-name="DataResourceRole"/>
-                <remove-value value-field="dataResource"/>
-            </if-not-empty>
-        </if-not-empty>
-    </simple-method>
-
-    <simple-method method-name="copyContentAndElectronicTextandAssoc" short-description="copy a content, electronic text and assocs and set status in progress">
-        <set-service-fields service-name="getContent" map="parameters" to-map="getC"/>
-        <call-service service-name="getContent" in-map-name="getC">
-            <result-to-field result-name="view" field="content"/>
-        </call-service>
-        <clone-value value-field="content" new-value-field="content"/>
-        <if-not-empty field="content.dataResourceId">
-            <set-service-fields service-name="getElectronicText" map="content" to-map="getEt"/>
-            <call-service service-name="getElectronicText" in-map-name="getEt">
-                <result-to-field result-name="textData" field="et.textData"/>
-            </call-service>
-            <set field="dataResource.dataResourceTypeId" value="ELECTRONIC_TEXT"/>
-            <call-service service-name="createDataResource" in-map-name="dataResource">
-                <result-to-field result-name="dataResourceId" field="et.dataResourceId"/>
-            </call-service>
-            <call-service service-name="createElectronicText" in-map-name="et"/>
-
-            <set field="content.dataResourceId" from-field="et.dataResourceId"/>
-
-        </if-not-empty>
-
-        <clear-field field="content.contentId"/><!-- force new value -->
-        <clear-field field="content.statusId"/><!-- force new value -->
-        <set-service-fields service-name="createContent" map="content" to-map="createContent"/>
-        <call-service service-name="createContent" in-map-name="createContent">
-            <result-to-field result-name="contentId" field="newContentId"/>
-        </call-service>
-
-        <entity-and entity-name="ContentAssoc" list="assocs">
-            <field-map field-name="contentId" from-field="parameters.contentId"/>
-        </entity-and>
-        <iterate list="assocs" entry="assoc">
-            <set field="assoc.contentId" from-field="newContentId"/>
-            <set-service-fields service-name="createContentAssoc" map="assoc" to-map="assocS"/>
-            <call-service service-name="createContentAssoc" in-map-name="assocS"/>
-        </iterate>
-
-        <entity-and entity-name="ContentAssoc" list="assocsTo">
-            <field-map field-name="contentIdTo" from-field="parameters.contentId"/>
-        </entity-and>
-        <iterate list="assocsTo" entry="assocTo">
-            <set field="assocTo.contentIdTo" from-field="newContentId"/>
-            <set-service-fields service-name="createContentAssoc" map="assocTo" to-map="assocTos"/>
-            <call-service service-name="createContentAssoc" in-map-name="assocTos"/>
-        </iterate>
-
-        <field-to-result field="newContentId" result-name="contentId"/>
-
-    </simple-method>
-
-    <!-- Methods for ContentAssoc -->
-    <simple-method login-required="true" method-name="assocContent" short-description="Associate Content" >
-        <log level="info" message="assocContent, parameters:${parameters}"/>
-        <log level="info" message="assocContent, context:${context}"/>
-        <call-service in-map-name="parameters" service-name="checkAssocPermission">
-            <result-to-field result-name="permissionStatus" field="permissionStatus"/>
-            <result-to-field result-name="rolesOut" field="rolesOut"/>
-        </call-service>
-        <log level="info" message="permissionStatus:${permissionStatus}"/>
-
-
-        <set from-field="parameters.contentIdTo" field="pk.contentId"/>
-        <set from-field="currentContent" field="context.currentContent"/>
-        <set from-field="parameters.contentIdFrom" field="pk.contentId"/>
-        <set from-field="parameters.userLogin" field="context.userLogin"/>
-        <find-by-primary-key value-field="currentContent" entity-name="Content" map="pk"/>
-        <find-by-primary-key value-field="fromContent" entity-name="Content" map="pk"/>
-
-        <if-compare field="permissionStatus" operator="equals" type="String" value="granted">
-            <make-value entity-name="ContentAssoc" value-field="newContentAssoc"/>
-            <set from-field="parameters.contentIdTo" field="newContentAssoc.contentIdTo"/>
-            <set from-field="parameters.contentIdFrom" field="newContentAssoc.contentId"/>
-            <set from-field="parameters.contentAssocTypeId" field="newContentAssoc.contentAssocTypeId"/>
-            <set from-field="newUserLogin.userLoginId" field="newContentAssoc.createdByUserLogin"/>
-            <set from-field="newUserLogin.userLoginId" field="newContentAssoc.lastModifiedByUserLogin"/>
-            <now-timestamp field="newContentAssoc.createdDate"/>
-            <now-timestamp field="newContentAssoc.lastModifiedDate"/>
-
-            <if-empty field="parameters.fromDate">
-                <now-timestamp field="parameters.fromDate"/>
-            </if-empty>
-            <set from-field="parameters.fromDate" field="newContentAssoc.fromDate"/>
-            <if-not-empty field="parameters.thruDate">
-                <set from-field="parameters.thruDate" field="newContentAssoc.thruDate"/>
-            </if-not-empty>
-            <create-value value-field="newContentAssoc"/>
-        </if-compare>
-        <check-errors/>
-    </simple-method>
-
-    <!-- This method first creates Content, DataResource and ElectronicText, ImageDataResource, etc. entities (if needed)
-         by calling persistContentAndAssoc.
-
-        It then takes the contentId coming out of that service, the passed in communicationEventId
-         and calls the "createCommEventContentAssoc" service to tie the CommunicationEvent and Content entities together.
-        -->
-    <simple-method method-name="createCommContentDataResource" short-description="Create CommunicationEvent and Content">
-
-        <!--
-        <check-permission permission="CONTENTMGR" action="_DELETE">
-            <fail-property resource="ContentUiLabels" property="ContentSecurityDeletePermission"/>
-        </check-permission>
-        <check-errors/>
-            -->
-
-        <now-timestamp field="nowTimestamp"/>
-        <set-service-fields service-name="persistContentAndAssoc" map="parameters" to-map="persistIn"/>
-        <!-- let's take a guess at what the dataResourceTypeId should be if it is empty -->
-        <if-empty field="persistIn.dataResourceTypeId">
-        <log level="info" message="persistIn.drMimeTypeId: ${persistIn.drMimeTypeId}"/>
-            <if-regexp expr="text.*" field="persistIn.drMimeTypeId">
-                <set field="persistIn.dataResourceTypeId" value="ELECTRONIC_TEXT"/>
-                <else>
-                    <set field="persistIn.dataResourceTypeId" value="IMAGE_OBJECT"/>
-                </else>
-            </if-regexp>
-        </if-empty>
-        <log level="info" message="persistIn.dataResourceTypeId: ${persistIn.dataResourceTypeId}"/>
-
-        <call-service service-name="persistContentAndAssoc" in-map-name="persistIn">
-            <results-to-map map-name="persistOut"/>
-        </call-service>
-
-        <field-to-result field="persistOut.contentId" result-name="contentId"/>
-        <field-to-result field="persistOut.dataResourceId" result-name="dataResourceId"/>
-        <field-to-result field="persistOut.drDataResourceId" result-name="drDataResourceId"/>
-        <field-to-result field="persistOut.caContentIdTo" result-name="caContentIdTo"/>
-        <field-to-result field="persistOut.caContentId" result-name="caContentId"/>
-        <field-to-result field="persistOut.caContentAssocTypeId" result-name="caContentAssocTypeId"/>
-        <field-to-result field="persistOut.caFromDate" result-name="caFromDate"/>
-        <field-to-result field="persistOut.caSequenceNum" result-name="caSequenceNum"/>
-        <field-to-result field="persistOut.roleTypeList" result-name="roleTypeList"/>
-        <field-to-result field="persistOut.fromDate" result-name="fromDate"/>
-
-        <set field="mapIn.contentId"  from-field="persistOut.contentId"/>
-        <set field="mapIn.communicationEventId"  from-field="parameters.communicationEventId"/>
-        <set field="mapIn.sequenceNum"  from-field="parameters.sequenceNum"/>
-        <call-service service-name="createCommEventContentAssoc" in-map-name="mapIn">
-            <result-to-result result-name="fromDate"/>
-        </call-service>
-
-    </simple-method>
-
-    <!-- simply use createContent and the accoc will be created too" the service below +aca will create 2 contentAssocs-->
-    <!--simple-method method-name="createContentAndAssoc" short-description="Create content and associate with other content">
-        <set-service-fields service-name="createContent" map="parameters" to-map="contentData"/>
-        <call-service service-name="createContent" in-map-name="contentData">
-            <result-to-field result-name="contentId" field="newContentId"/>
-        </call-service>
-        <if-not-empty field="newContentId">
-            <set-service-fields service-name="createContentAssoc" map="parameters" to-map="assocData"/>
-            <set field="assocData.contentId" from-field="newContentId"/>
-            <call-service service-name="createContentAssoc" in-map-name="assocData">
-                <result-to-result result-name="contentId" service-result-name="contentIdFrom"/>
-                <result-to-result result-name="contentIdTo" service-result-name="contentIdTo"/>
-            </call-service>
-            <field-to-result field="newContentId" result-name="contentId"/>
-        </if-not-empty>
-    </simple-method-->
-
-    <simple-method method-name="getPublicForumMessage" short-description="get the content and related resource information without security" login-required="false">
-        <set field="publicForumMessage" value="true"/>
-        <set-service-fields service-name="getContentAndDataResource" map="parameters" to-map="getC"/>
-        <call-service service-name="getContentAndDataResource" in-map-name="getC"/>
-    </simple-method>
-
-    <simple-method method-name="createMissingContentAltUrls" short-description="create missing content alternative urls.">
-        <now-timestamp field="now"/>
-        <set field="contentsNotUpdated" value="0" type="Integer"/>
-        <set field="contentsUpdated" value="0" type="Integer"/>
-        <if-not-empty field="parameters.prodCatalogId">
-            <entity-and entity-name="ProdCatalogCategory" list="prodCatalogCategoryList" filter-by-date="false">
-                <field-map field-name="prodCatalogId" from-field="parameters.prodCatalogId"/>
-            </entity-and>
-            
-            <!-- Get all categories -->
-            <set field="parameters.productCategories" value="${groovy: [];}" type="List"/>
-            <iterate list="prodCatalogCategoryList" entry="prodCatalogCategory">
-                <set field="rootProductCategoryId" from-field="prodCatalogCategory.productCategoryId"/>
-                <entity-and entity-name="ProductCategoryRollup" list="productCategoryRollupList" filter-by-date="true">
-                    <field-map field-name="parentProductCategoryId" from-field="rootProductCategoryId"/>
-                </entity-and>
-                <set field="parameters.parentProductCategoryId" from-field="rootProductCategoryId"/>
-                <call-simple-method method-name="createMissingCategoryContentAltUrlInline"/>
-            </iterate>
-            
-            <iterate list="parameters.productCategories" entry="productCategoryList">
-                <!-- Create Content Alternative URLs for Product Category Content -->
-                <entity-condition entity-name="ProductCategoryContentAndInfo" list="productCategoryContentAndInfoList" filter-by-date="true" use-cache="true">
-                    <condition-list combine="and">
-                        <condition-expr field-name="productCategoryId" from-field="productCategoryList.productCategoryId"/>
-                        <condition-expr field-name="prodCatContentTypeId" operator="not-equals" value="ALTERNATIVE_URL"/>
-                    </condition-list>
-                    <order-by field-name="-fromDate"/>
-                </entity-condition>
-                <iterate list="productCategoryContentAndInfoList" entry="productCategoryContentAndInfo">
-                    <set field="createMissingCategoryContentAltUrlsMap.contentId" from-field="productCategoryContentAndInfo.contentId"/>
-                    <call-service service-name="createContentAlternativeUrl" in-map-name="createMissingCategoryContentAltUrlsMap">
-                        <result-to-field result-name="contentCreated" field="contentCreated"/>
-                    </call-service>
-                    <if-compare operator="equals" value="Y" field="contentCreated">
-                        <calculate field="contentsUpdated" type="Integer">
-                            <calcop operator="add" field="contentsUpdated">
-                                <number value="1"/>
-                            </calcop>
-                        </calculate>
-                    </if-compare>
-                    <if-compare operator="equals" value="N" field="contentCreated">
-                        <calculate field="contentsNotUpdated" type="Integer">
-                            <calcop operator="add" field="contentsNotUpdated">
-                                <number value="1"/>
-                            </calcop>
-                        </calculate>
-                    </if-compare>
-                </iterate>
-                
-                <!-- Create Content Alternative URLs for Product Content -->
-                <entity-condition entity-name="ProductCategoryMember" list="productCategoryMemberList" filter-by-date="true" use-cache="true">
-                    <condition-list combine="and">
-                        <condition-expr field-name="productCategoryId" from-field="productCategoryList.productCategoryId"/>
-                    </condition-list>
-                    <order-by field-name="-fromDate"/>
-                </entity-condition>
-                <iterate list="productCategoryMemberList" entry="productCategoryMember">
-                    <set field="product.productId" from-field="productCategoryMember.productId"/>
-                    <entity-condition entity-name="ProductContentAndInfo" list="productContentAndInfoList" filter-by-date="true" use-cache="true">
-                        <condition-list combine="and">
-                            <condition-expr field-name="productId" from-field="product.productId"/>
-                            <condition-expr field-name="productContentTypeId" operator="not-equals" value="ALTERNATIVE_URL"/>
-                        </condition-list>
-                        <order-by field-name="-fromDate"/>
-                    </entity-condition>
-                    <iterate list="productContentAndInfoList" entry="productContentAndInfo">
-                        <set field="createMissingProductContentAltUrlsMap.contentId" from-field="productContentAndInfo.contentId"/>
-                        <call-service service-name="createContentAlternativeUrl" in-map-name="createMissingProductContentAltUrlsMap">
-                            <result-to-field result-name="contentCreated" field="contentCreated"/>
-                        </call-service>
-                        <if-compare operator="equals" value="Y" field="contentCreated">
-                            <calculate field="contentsUpdated" type="Integer">
-                                <calcop operator="add" field="contentsUpdated">
-                                    <number value="1"/>
-                                </calcop>
-                            </calculate>
-                        </if-compare>
-                        <if-compare operator="equals" value="N" field="contentCreated">
-                            <calculate field="contentsNotUpdated" type="Integer">
-                                <calcop operator="add" field="contentsNotUpdated">
-                                    <number value="1"/>
-                                </calcop>
-                            </calculate>
-                        </if-compare>
-                    </iterate>
-                </iterate>
-            </iterate>
-        </if-not-empty>
-        
-        <!-- Create Content Alternative URLs for Website Content -->
-        <entity-and list="webSiteContents" entity-name="WebSiteContent" filter-by-date="true">
-            <field-map field-name="webSiteId" from-field="parameters.webSiteId"/>
-        </entity-and>
-        <iterate list="webSiteContents" entry="webSiteContent">
-            <entity-and list="subContents" entity-name="ContentAssoc" filter-by-date="true">
-                <field-map field-name="contentId" from-field="webSiteContent.contentId"/>
-            </entity-and>
-            <iterate list="subContents" entry="subContent">
-                <set field="createMissingContentAltUrlsMap.contentId" from-field="subContent.contentIdTo"/>
-                <call-service service-name="createContentAlternativeUrl" in-map-name="createMissingContentAltUrlsMap">
-                    <result-to-field result-name="contentCreated" field="contentCreated"/>
-                </call-service>
-                <if-compare operator="equals" value="Y" field="contentCreated">
-                    <calculate field="contentsUpdated" type="Integer">
-                        <calcop operator="add" field="contentsUpdated">
-                            <number value="1"/>
-                        </calcop>
-                    </calculate>
-                </if-compare>
-                <if-compare operator="equals" value="N" field="contentCreated">
-                    <calculate field="contentsNotUpdated" type="Integer">
-                        <calcop operator="add" field="contentsNotUpdated">
-                            <number value="1"/>
-                        </calcop>
-                    </calculate>
-                </if-compare>
-                <entity-and entity-name="ContentAssoc" list="contentAssocs" filter-by-date="true">
-                    <field-map field-name="contentId" from-field="subContent.contentIdTo"/>
-                </entity-and>
-                <iterate list="contentAssocs" entry="contentAssoc">
-                    <set field="createMissingContentAltUrlsMap.contentId" from-field="contentAssoc.contentIdTo"/>
-                    <call-service service-name="createContentAlternativeUrl" in-map-name="createMissingContentAltUrlsMap">
-                        <result-to-field result-name="contentCreated" field="contentCreated"/>
-                    </call-service>
-                    <if-compare operator="equals" value="Y" field="contentCreated">
-                        <calculate field="contentsUpdated" type="Integer">
-                            <calcop operator="add" field="contentsUpdated">
-                                <number value="1"/>
-                            </calcop>
-                        </calculate>
-                    </if-compare>
-                    <if-compare operator="equals" value="N" field="contentCreated">
-                        <calculate field="contentsNotUpdated" type="Integer">
-                            <calcop operator="add" field="contentsNotUpdated">
-                                <number value="1"/>
-                            </calcop>
-                        </calculate>
-                    </if-compare>
-                </iterate>
-            </iterate>
-        </iterate>
-        <field-to-result field="contentsNotUpdated" result-name="contentsNotUpdated"/>
-        <field-to-result field="contentsUpdated" result-name="contentsUpdated"/>
-    </simple-method>
-
-    <simple-method method-name="createMissingCategoryContentAltUrlInline" short-description="create missing category alternative inline">
-        <entity-and entity-name="ProductCategoryRollup" list="productCategoryRollups" filter-by-date="true">
-            <field-map field-name="parentProductCategoryId" from-field="parameters.parentProductCategoryId"/>
-        </entity-and>
-        <iterate list="productCategoryRollups" entry="productCategoryRollup">
-            <!-- append product category to list -->
-            <entity-one entity-name="ProductCategory" value-field="productCategory">
-                <field-map field-name="productCategoryId" from-field="productCategoryRollup.productCategoryId"/>
-            </entity-one>
-            <field-to-list list="parameters.productCategories" field="productCategory"/>
-            
-            <!-- find rollup product categories -->
-            <set field="parameters.parentProductCategoryId" from-field="productCategoryRollup.productCategoryId"/>
-            <call-simple-method method-name="createMissingCategoryContentAltUrlInline"/>
-            <check-errors/>
-        </iterate>
-    </simple-method>
-</simple-methods>
-
diff --git a/applications/content/servicedef/services.xml b/applications/content/servicedef/services.xml
index f252a75903..48fe8c5cc8 100644
--- a/applications/content/servicedef/services.xml
+++ b/applications/content/servicedef/services.xml
@@ -32,12 +32,12 @@
     </service>
 
     <!-- Content services? -->
-    <service name="getPublicForumMessage" engine="simple" default-entity-name="Content" auth="true"
-            location="component://content/minilang/content/ContentServices.xml" invoke="getPublicForumMessage">
+    <service name="getPublicForumMessage" engine="group" default-entity-name="Content" auth="true">
         <description>Get Content and resource information</description>
-        <permission-service service-name="genericContentPermission" main-action="VIEW"/>
-        <auto-attributes include="pk" mode="IN" optional="false"/>
-        <attribute mode="OUT" name="resultData" optional="true" type="java.util.Map"/>
+        <deprecated use-instead="getContentAndDataResource" since="Release 22.01"/>
+        <group>
+            <invoke name="getContentAndDataResource"/>
+        </group>
     </service>
 
     <service name="getContentAndDataResource" engine="groovy" default-entity-name="Content" auth="true"
diff --git a/applications/content/servicedef/services_content.xml b/applications/content/servicedef/services_content.xml
index 23dbfbf0ca..1b75c54c0f 100644
--- a/applications/content/servicedef/services_content.xml
+++ b/applications/content/servicedef/services_content.xml
@@ -116,8 +116,8 @@
         </group>
     </service>
 
-    <service name="copyContentAndElectronicTextandAssoc" default-entity-name="Content" engine="simple"
-        location="component://content/minilang/content/ContentServices.xml" invoke="copyContentAndElectronicTextandAssoc" auth="true" >
+    <service name="copyContentAndElectronicTextandAssoc" default-entity-name="Content" engine="groovy" auth="true"
+                location="component://content/groovyScripts/content/ContentServices.groovy" invoke="copyContentAndElectronicTextandAssoc">
         <description>Copy a Content, e;ectronic text and assocs</description>
         <!-- uses createContent internally; additonal permission(s) not necessary -->
         <auto-attributes include="pk" mode="INOUT" optional="false"/>
@@ -161,8 +161,8 @@
         <attribute mode="INOUT" name="roleTypeList" optional="true" type="List"/>
     </service>
 
-    <service name="removeContentAndRelated" default-entity-name="Content" engine="simple"
-            location="component://content/minilang/content/ContentServices.xml" invoke="removeContentAndRelated" auth="true">
+    <service name="removeContentAndRelated" default-entity-name="Content" engine="groovy" auth="true"
+                location="component://content/groovyScripts/content/ContentServices.groovy" invoke="removeContentAndRelated">
         <description>Remove Content</description>
         <permission-service service-name="genericContentPermission" main-action="DELETE"/>
         <auto-attributes include="pk" mode="IN" optional="false"/>
@@ -172,12 +172,12 @@
         <attribute mode="INOUT" name="roleTypeList" optional="true" type="List"/>
     </service>
 
-    <!-- TODO: old permission service; being replaced with genericContentPermission -->
     <service name="checkContentPermission"
         transaction-timeout="7200"
         auth="false" engine="java" invoke="checkContentPermission"
         location="org.apache.ofbiz.content.content.ContentPermissionServices">
         <description>Check for permission to perform operation on Content</description>
+        <deprecated use-instead="genericContentPermission" since="Release 22.01"/>
         <attribute mode="IN" name="targetOperationList" optional="true" type="List"/>
         <attribute mode="IN" name="contentPurposeList" optional="true" type="List"/>
         <!-- it was a mistake to pass in List objects because it makes it difficult to use
@@ -222,10 +222,10 @@
     </service>
 
     <!--Content Assoc services.-->
-    <!-- TODO: old permission service; being replaced with genericContentPermission -->
     <service name="checkAssocPermission" engine="java" transaction-timeout="7200" auth="true"
             location="org.apache.ofbiz.content.content.ContentPermissionServices" invoke="checkAssocPermission">
         <description>Check for permission to perform operation on Content</description>
+        <deprecated use-instead="genericContentPermission" since="Release 22.01"/>
         <attribute mode="IN" name="targetOperationList" optional="true" type="List"/>
         <attribute mode="IN" name="contentPurposeList" optional="true" type="List"/>
         <attribute mode="INOUT" name="roleTypeList" optional="true" type="List"/>
@@ -245,9 +245,10 @@
         <attribute mode="OUT" name="permissionRecorder" optional="true" type="org.apache.ofbiz.content.content.PermissionRecorder"/>
     </service>
 
-    <service name="assocContent" engine="simple" default-entity-name="ContentAssoc"  auth="true"
-            location="component://content/minilang/content/ContentServices.xml" invoke="assocContent">
+    <service name="assocContent" engine="groovy" default-entity-name="ContentAssoc"  auth="true"
+            location="component://content/groovyScripts/content/ContentServices.groovy" invoke="assocContent">
         <description>Check for permission to perform operation on Content</description>
+        <deprecated use-instead="genericContentPermission" since="Release 22.01"/>
         <attribute mode="IN" name="targetOperationList" optional="true" type="List"/>
         <attribute mode="IN" name="contentPurposeList" optional="true" type="List"/>
         <attribute mode="INOUT" name="roleTypeList" optional="true" type="List"/>