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
diff --git a/applications/content/groovyScripts/content/ContentServices.groovy b/applications/content/groovyScripts/content/ContentServices.groovy
index 65e5808..dfecd7d 100644
--- a/applications/content/groovyScripts/content/ContentServices.groovy
+++ b/applications/content/groovyScripts/content/ContentServices.groovy
@@ -666,4 +666,81 @@
                     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 17f1abf..0000000
--- 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 f252a75..48fe8c5 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 23dbfbf..1b75c54 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"/>