[ofbiz-framework] branch trunk updated: Improved: Convert ContactMechServices.xml mini-lang to groovyDSL (OFBIZ-11358)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[ofbiz-framework] branch trunk updated: Improved: Convert ContactMechServices.xml mini-lang to groovyDSL (OFBIZ-11358)

nmalin
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


The following commit(s) were added to refs/heads/trunk by this push:
     new c51f703  Improved: Convert ContactMechServices.xml mini-lang to groovyDSL (OFBIZ-11358)
c51f703 is described below

commit c51f703d36e43187b139d3895187170536621a62
Author: Nicolas Malin <[hidden email]>
AuthorDate: Sat Feb 22 11:19:40 2020 +0100

    Improved: Convert ContactMechServices.xml mini-lang to groovyDSL
    (OFBIZ-11358)
   
    Convert all services present on ContactMechService.xml to groovyDSL :
      * createContactMech
      * updateContactMech
      * createPostalAddress
      * updatePostalAddress
      * createTelecomNumber
      * updateTelecomNumber
      * createEmailAddress
      * updateEmailAddress
   
    I reorganized to move service definition from general services.xml file
    to dedicate services_contact.xml, and create a new directory groovyScript/contact/
    to centralize in future all groovy for contactMech as present on minilang directory
---
 .../contact/ContactMechServices.groovy             | 338 +++++++++++++++++++++
 .../groovyScripts/party/ContactMechServices.groovy |  99 ------
 .../party/minilang/contact/ContactMechMapProcs.xml |  33 --
 .../party/minilang/contact/ContactMechServices.xml | 273 -----------------
 applications/party/servicedef/services.xml         |  88 +-----
 applications/party/servicedef/services_contact.xml |  84 ++++-
 6 files changed, 425 insertions(+), 490 deletions(-)

diff --git a/applications/party/groovyScripts/contact/ContactMechServices.groovy b/applications/party/groovyScripts/contact/ContactMechServices.groovy
new file mode 100644
index 0000000..26b259e
--- /dev/null
+++ b/applications/party/groovyScripts/contact/ContactMechServices.groovy
@@ -0,0 +1,338 @@
+/*
+ * 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.
+ */
+
+
+import org.apache.ofbiz.base.util.UtilProperties
+import org.apache.ofbiz.base.util.UtilValidate
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.service.ModelService
+import org.apache.ofbiz.service.ServiceUtil
+
+/**
+ * Update a Contact Mechanism
+ */
+def updateContactMech() {
+    Map successMessageMap = [
+            EMAIL_ADDRESS: 'EmailAddress',
+            WEB_ADDRESS: 'WebAddress',
+            IP_ADDRESS: 'IpAddress',
+            ELECTRONIC_ADDRESS: 'ElectronicAddress',
+            DOMAIN_NAME: 'DomainName',
+            default: 'ContactMechanism'
+    ]
+    String successMessage = "Party" +
+            successMessageMap."${parameters.contactMechTypeId}" ?: successMessageMap.default +
+            "SuccessfullyUpdated"
+    GenericValue lookedValue = from('ContactMech').where(parameters).queryOne()
+    if (! lookedValue) {
+        return error(UtilProperties.getMessage('ServiceErrorUiLabels', 'ServiceValueNotFound', locale))
+    }
+    if (lookedValue.infoString != parameters.infoString) {
+        lookedValue.setNonPKFields(parameters)
+        lookedValue.contactMechId = null
+        Map serviceResult = run service: 'createContactMech', with: lookedValue.getAllFields()
+        Map serviceReturn = success(UtilProperties.getMessage('PartyUiLabels', successMessage, locale))
+        serviceReturn.contactMechId = serviceResult.contactMechId
+        return serviceReturn
+    }
+    Map serviceReturn = success(UtilProperties.getMessage('PartyUiLabels', 'PartyNothingToDoHere', locale))
+    serviceReturn.contactMechId = parameters.contactMechId
+    return serviceReturn
+}
+
+/**
+ * locale function to control if the state province is mandatoring
+ * @param countryGeoId
+ * @param stateProvinceGeoId
+ * @return
+ */
+def hasValidStateProvince(String countryGeoId, String stateProvinceGeoId) {
+    String errorMessage
+    if (!stateProvinceGeoId) {
+        if ('USA' == countryGeoId) errorMessage = 'PartyStateInUsMissing'
+        if ('CAN' == countryGeoId) errorMessage = 'PartyProvinceInCanadaMissing'
+    }
+    return errorMessage
+}
+
+/**
+ * Create Contact Mechanism with PostalAddress
+ */
+def createPostalAddress() {
+    String errorMessage = hasValidStateProvince(parameters.countryGeoId, parameters.stateProvinceGeoId)
+    if (errorMessage) {
+        return error(UtilProperties.getMessage('PartyUiLabels', errorMessage, locale))
+    }
+    GenericValue newValue = makeValue('PostalAddress', parameters)
+    Map createContactMechMap = [contactMechTypeId: 'POSTAL_ADDRESS', contactMechId: parameters.contactMechId]
+    Map serviceResult = run service: 'createContactMech', with: createContactMechMap
+    newValue.contactMechId = serviceResult.contactMechId
+    newValue.create()
+    Map serviceReturn = success(UtilProperties.getMessage('PartyUiLabels',
+            'PartyPostalAddressSuccessfullyCreated', locale))
+    serviceReturn.contactMechId = newValue.contactMechId
+    return serviceReturn
+}
+
+/**
+ * Update Contact Mechanism with PostalAddress
+ */
+def updatePostalAddress() {
+    String errorMessage = hasValidStateProvince(parameters.countryGeoId, parameters.stateProvinceGeoId)
+    if (errorMessage) {
+        return error(UtilProperties.getMessage('PartyUiLabels', errorMessage, locale))
+    }
+    GenericValue lookedValue = from('PostalAddress').where(parameters).queryOne()
+    if (! lookedValue) {
+        return error(UtilProperties.getMessage('ServiceErrorUiLabels', 'ServiceValueNotFound', locale))
+    }
+    GenericValue newValue = makeValue('PostalAddress', parameters)
+    String contactMechId
+    String oldContactMechId = lookedValue.contactMechId
+    String successMessage = 'PartyPostalAddressSuccessfullyUpdated'
+    if (newValue.compareTo(lookedValue) != 0) {
+        logInfo('Postal address need updating')
+        Map createPostalAddressMap = [*:parameters]
+        createPostalAddressMap.contactMechId = null
+        Map serviceResult = run service: 'createPostalAddress', with: createPostalAddressMap
+        contactMechId = serviceResult.contactMechId
+    } else {
+        Map serviceResult = run service: 'updateContactMech', with: parameters
+        contactMechId = serviceResult.contactMechId
+        if (contactMechId != oldContactMechId) {
+            logInfo('Postal address need updating, contact mech changed')
+            newValue.contactMechId = contactMechId
+            newValue.create()
+        } else {
+            successMessage = 'PartyNothingToDoHere'
+        }
+    }
+
+    Map serviceReturn = success(UtilProperties.getMessage('PartyUiLabels', successMessage, locale))
+    serviceReturn.contactMechId = contactMechId
+    serviceReturn.oldContactMechId = oldContactMechId
+    return serviceReturn
+}
+
+/**
+ * Create Contact Mechanism with Telecom Number
+ */
+def createTelecomNumber() {
+    GenericValue newValue = makeValue('TelecomNumber', parameters)
+    Map createContactMechMap = [contactMechTypeId: 'TELECOM_NUMBER', contactMechId: parameters.contactMechId]
+    Map serviceResult = run service: 'createContactMech', with: createContactMechMap
+    newValue.contactMechId = serviceResult.contactMechId
+    newValue.create()
+    Map serviceReturn = success(UtilProperties.getMessage('PartyUiLabels',
+            'PartyTelecomNumberSuccessfullyCreated', locale))
+    serviceReturn.contactMechId = newValue.contactMechId
+    return serviceReturn
+}
+
+/**
+ * Update Contact Mechanism with Telecom Number
+ */
+def updateTelecomNumber() {
+    GenericValue lookedValue = from('TelecomNumber').where(parameters).queryOne()
+    if (!lookedValue) {
+        return error(UtilProperties.getMessage('ServiceErrorUiLabels', 'ServiceValueNotFound', locale))
+    }
+    GenericValue newValue = makeValue('TelecomNumber', parameters)
+    String contactMechId
+    String oldContactMechId = lookedValue.contactMechId
+    String successMessage = 'PartyTelecomNumberSuccessfullyUpdated'
+    if (newValue.compareTo(lookedValue) != 0) {
+        logInfo('Telecom number need updating')
+        Map createTelecomNumberMap = [*:parameters]
+        createTelecomNumberMap.contactMechId = null
+        Map serviceResult = run service: 'createTelecomNumber', with: createTelecomNumberMap
+        contactMechId = serviceResult.contactMechId
+    } else {
+        Map serviceResult = run service: 'updateContactMech', with: parameters
+        contactMechId = serviceResult.contactMechId
+        if (contactMechId != oldContactMechId) {
+            logInfo('Telecom number need updating, contact mech changed')
+            newValue.contactMechId = contactMechId
+            newValue.create()
+        } else {
+            successMessage = 'PartyNothingToDoHere'
+        }
+    }
+
+    Map serviceReturn = success(UtilProperties.getMessage('PartyUiLabels', successMessage, locale))
+    serviceReturn.contactMechId = contactMechId
+    serviceReturn.oldContactMechId = oldContactMechId
+    return serviceReturn
+}
+
+/**
+ * Create an email address contact mechanism
+ */
+def createEmailAddress() {
+    if (UtilValidate.isEmail(parameters.emailAddress)) {
+        Map createContactMechMap = [contactMechTypeId: 'EMAIL_ADDRESS',
+                                    contactMechId: parameters.contactMechId,
+                                    infoString: parameters.emailAddress]
+        Map serviceResult = run service: 'createContactMech', with: createContactMechMap
+        Map serviceReturn = success(UtilProperties.getMessage('PartyUiLabels',
+                'PartyEmailAddressSuccessfullyCreated', locale))
+        serviceReturn.contactMechId = serviceResult.contactMechId
+        return serviceReturn
+    }
+    return error(UtilProperties.getMessage('PartyUiLabels', 'PartyEmailAddressNotFormattedCorrectly', locale))
+}
+
+/**
+ * Update an email address contact mechanism
+ */
+def updateEmailAddress() {
+    if (UtilValidate.isEmail(parameters.emailAddress)) {
+        Map updateContactMechMap = [contactMechTypeId: 'EMAIL_ADDRESS',
+                                    contactMechId: parameters.contactMechId,
+                                    infoString: parameters.emailAddress]
+        Map serviceResult = run service: 'updateContactMech', with: updateContactMechMap
+        Map serviceReturn = success(UtilProperties.getMessage('PartyUiLabels',
+                'PartyEmailAddressSuccessfullyUpdated', locale))
+        serviceReturn.contactMechId = serviceResult.contactMechId
+        return serviceReturn
+    }
+    return error(UtilProperties.getMessage('PartyUiLabels', 'PartyEmailAddressNotFormattedCorrectly', locale))
+}
+
+/**
+ * Create FtpAddress contact Mech
+ */
+def createFtpAddress() {
+    Map contactMech = run service: 'createContactMech', with: [contactMechTypeId: 'FTP_ADDRESS']
+    String contactMechId = contactMech.contactMechId
+    if (contactMechId) {
+        GenericValue ftpAddress = makeValue('FtpAddress', parameters)
+        ftpAddress.contactMechId = contactMechId
+        ftpAddress.create()
+    } else return error('Error creating contactMech')
+
+    Map resultMap = success()
+    resultMap.contactMechId = contactMechId
+    return resultMap
+}
+
+/**
+ * Update FtpAddress contact Mech
+ */
+def updateFtpAddressWithHistory() {
+    Map resultMap = success()
+    resultMap.oldContactMechId = parameters.contactMechId
+    resultMap.contactMechId = parameters.contactMechId
+    Map newContactMechResult
+    if (resultMap.oldContactMechId) {
+        newValue = makeValue('FtpAddress', parameters)
+        if (newValue != from('FtpAddress').where(parameters).queryOne()) {  // if there is some modifications in FtpAddress data
+            newContactMechResult = run service: 'createFtpAddress', with: parameters
+        } else { //update only contactMech
+            Map updateContactMechMap = dispatcher.getDispatchContext().makeValidContext('updateContactMech', ModelService.IN_PARAM, parameters)
+            updateContactMechMap.contactMechTypeId = 'FTP_ADDRESS'
+            newContactMechResult = run service: 'updateContactMech', with: updateContactMechMap
+        }
+
+        if (!resultMap.oldContactMechId.equals(newContactMechResult.contactMechId)) {
+            resultMap.put('contactMechId', newContactMechResult.contactMechId)
+        }
+    }
+    return resultMap
+}
+
+/**
+ * Create FtpAddress contact Mech and link it with given partyId
+ * @return
+ */
+def createPartyFtpAddress() {
+    Map contactMech = run service: 'createFtpAddress', with: parameters
+    if (ServiceUtil.isError(contactMech)) return contactMech
+    String contactMechId = contactMech.contactMechId
+
+    Map createPartyContactMechMap = parameters
+    createPartyContactMechMap.put('contactMechId', contactMechId)
+    Map serviceResult = run service: 'createPartyContactMech', with: createPartyContactMechMap
+    if (ServiceUtil.isError(serviceResult)) return serviceResult
+
+    //TODO: manage purpose
+
+    Map resultMap = success()
+    resultMap.contactMechId = contactMechId
+    return resultMap
+}
+
+def updatePartyFtpAddress() {
+    Map updateFtpResult = run service: 'updateFtpAddressWithHistory', with: parameters
+    Map result = success()
+    result.contactMechId = parameters.contactMechId
+    if (parameters.contactMechId != updateFtpResult.contactMechId) {
+        Map updatePartyContactMechMap = dispatcher.getDispatchContext().makeValidContext('updatePartyContactMech', ModelService.IN_PARAM, parameters)
+        updatePartyContactMechMap.newContactMechId = updateFtpResult.contactMechId
+        updatePartyContactMechMap.contactMechTypeId = 'FTP_ADDRESS'
+        run service: 'updatePartyContactMech', with: updatePartyContactMechMap
+        result.contactMechId = updateFtpResult.contactMechId
+    }
+    return result
+}
+
+/**
+ * Send an email to the person for Verification of his Email Address
+ */
+def sendVerifyEmailAddressNotification() {
+    GenericValue storeEmail = from('ProductStoreEmailSetting')
+            .where(emailType: 'PRDS_EMAIL_VERIFY')
+            .cache()
+            .queryFirst()
+    GenericValue emailAddressVerification = from('EmailAddressVerification').where(parameters).queryOne()
+    if (emailAddressVerification && storeEmail) {
+        Map emailParams = [
+            sendTo: parameters.emailAddress,
+            subject: storeEmail.subject,
+            sendFrom: storeEmail.fromAddress,
+            sendCc: storeEmail.ccAddress,
+            sendBcc: storeEmail.bccAddress,
+            contentType: storeEmail.contentType,
+            bodyParameters: [verifyHash: emailAddressVerification.verifyHash],
+            bodyScreenUri: storeEmail.bodyScreenLocation]
+        GenericValue webSite = from("WebSite")
+                .where(productStoreId: storeEmail.productStoreId)
+                .cache()
+                .queryFirst()
+        emailParams.webSiteId = webSite ? webSite.webSiteId : null
+        run service: 'sendMailFromScreen', with: emailParams
+    }
+    return success()
+}
+
+/**
+ * Verify an Email Address through verifyHash and expireDate
+ */
+def verifyEmailAddress() {
+    GenericValue emailAddressVerification = from('EmailAddressVerification')
+            .where(verifyHash: parameters.verifyHash)
+            .queryFirst()
+    if (! emailAddressVerification) {
+        return error(UtilProperties.getMessage('PartyUiLabels', 'PartyEmailAddressNotExist', locale))
+    }
+    if (UtilValidate.isDateBeforeNow(emailAddressVerification.expireDate)) {
+        return error(UtilProperties.getMessage('PartyUiLabels', 'PartyEmailAddressVerificationExpired', locale))
+    }
+    return success()
+}
\ No newline at end of file
diff --git a/applications/party/groovyScripts/party/ContactMechServices.groovy b/applications/party/groovyScripts/party/ContactMechServices.groovy
deleted file mode 100644
index f7e22c9..0000000
--- a/applications/party/groovyScripts/party/ContactMechServices.groovy
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.
- */
-
-import org.apache.ofbiz.entity.GenericValue
-import org.apache.ofbiz.service.ModelService
-import org.apache.ofbiz.service.ServiceUtil
-
-/**
- * Create FtpAddress contact Mech
- */
-def createFtpAddress() {
-    Map contactMech = run service: 'createContactMech', with: [contactMechTypeId: 'FTP_ADDRESS']
-    String contactMechId = contactMech.contactMechId
-    if (contactMechId) {
-        GenericValue ftpAddress = makeValue('FtpAddress', parameters)
-        ftpAddress.contactMechId = contactMechId
-        ftpAddress.create()
-    } else return error('Error creating contactMech')
-
-    Map resultMap = success()
-    resultMap.contactMechId = contactMechId
-    return resultMap
-}
-
-/**
- * Update FtpAddress contact Mech
- */
-def updateFtpAddressWithHistory() {
-    Map resultMap = success()
-    resultMap.oldContactMechId = parameters.contactMechId
-    resultMap.contactMechId = parameters.contactMechId
-    Map newContactMechResult
-    if (resultMap.oldContactMechId) {
-        newValue = makeValue('FtpAddress', parameters)
-        if (newValue != from('FtpAddress').where(parameters).queryOne()) {  // if there is some modifications in FtpAddress data
-            newContactMechResult = run service: 'createFtpAddress', with: parameters
-        } else { //update only contactMech
-            Map updateContactMechMap = dispatcher.getDispatchContext().makeValidContext('updateContactMech', ModelService.IN_PARAM, parameters)
-            updateContactMechMap.contactMechTypeId = 'FTP_ADDRESS'
-            newContactMechResult = run service: 'updateContactMech', with: updateContactMechMap
-        }
-
-        if (!resultMap.oldContactMechId.equals(newContactMechResult.contactMechId)) {
-            resultMap.put('contactMechId', newContactMechResult.contactMechId)
-        }
-    }
-    return resultMap
-}
-
-/**
- * Create FtpAddress contact Mech and link it with given partyId
- * @return
- */
-def createPartyFtpAddress() {
-    Map contactMech = run service: 'createFtpAddress', with: parameters
-    if (ServiceUtil.isError(contactMech)) return contactMech
-    String contactMechId = contactMech.contactMechId
-
-    Map createPartyContactMechMap = parameters
-    createPartyContactMechMap.put('contactMechId', contactMechId)
-    Map serviceResult = run service: 'createPartyContactMech', with: createPartyContactMechMap
-    if (ServiceUtil.isError(serviceResult)) return serviceResult
-
-    //TODO: manage purpose
-
-    Map resultMap = success()
-    resultMap.contactMechId = contactMechId
-    return resultMap
-}
-
-def updatePartyFtpAddress() {
-    Map updateFtpResult = run service: 'updateFtpAddressWithHistory', with: parameters
-    Map result = success()
-    result.contactMechId = parameters.contactMechId
-    if (parameters.contactMechId != updateFtpResult.contactMechId) {
-        Map updatePartyContactMechMap = dispatcher.getDispatchContext().makeValidContext('updatePartyContactMech', ModelService.IN_PARAM, parameters)
-        updatePartyContactMechMap.newContactMechId = updateFtpResult.contactMechId
-        updatePartyContactMechMap.contactMechTypeId = 'FTP_ADDRESS'
-        run service: 'updatePartyContactMech', with: updatePartyContactMechMap
-        result.contactMechId = updateFtpResult.contactMechId
-    }
-    return result
-}
diff --git a/applications/party/minilang/contact/ContactMechMapProcs.xml b/applications/party/minilang/contact/ContactMechMapProcs.xml
deleted file mode 100644
index f3182ab..0000000
--- a/applications/party/minilang/contact/ContactMechMapProcs.xml
+++ /dev/null
@@ -1,33 +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-map-processors 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">
-    <!-- ContactMech map procs -->
-
-    <simple-map-processor name="emailAddress">
-        <process field="contactMechId"><copy set-if-null="false"/></process>
-        <process field="emailAddress">
-            <copy to-field="infoString"/>
-            <not-empty><fail-property resource="PartyUiLabels" property="PartyEmailAddressMissing"/></not-empty>
-            <validate-method method="isEmail"><fail-property resource="PartyUiLabels" property="PartyEmailAddressNotFormattedCorrectly"/></validate-method>
-         </process>
-    </simple-map-processor>
-</simple-map-processors>
diff --git a/applications/party/minilang/contact/ContactMechServices.xml b/applications/party/minilang/contact/ContactMechServices.xml
deleted file mode 100644
index 66cb7a1..0000000
--- a/applications/party/minilang/contact/ContactMechServices.xml
+++ /dev/null
@@ -1,273 +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="createContactMech" short-description="Create Contact Mechanism">
-        <make-value entity-name="ContactMech" value-field="newValue"/>
-        <if-empty field="parameters.contactMechId">
-            <sequenced-id sequence-name="ContactMech" field="newValue.contactMechId"/>
-            <else>
-                <set field="newValue.contactMechId" from-field="parameters.contactMechId"/>
-            </else>
-        </if-empty>
-        <set-nonpk-fields map="parameters" value-field="newValue"/>
-        <create-value value-field="newValue"/>
-        <field-to-result field="newValue.contactMechId" result-name="contactMechId"/>
-        <field-to-request field="newValue.contactMechId" request-name="contactMechId"/>
-        <log level="info" message="Contact mech created with id ${newValue.contactMechId}"/>
-    </simple-method>
-
-    <simple-method method-name="updateContactMech" short-description="Update Contact Mechanism">
-        <set field="successMessageProperty" value="PartyContactMechanismSuccessfullyUpdated"/>
-        <if-compare field="parameters.contactMechTypeId" operator="equals" value="EMAIL_ADDRESS">
-            <set field="successMessageProperty" value="PartyEmailAddressSuccessfullyUpdated"/>
-        </if-compare>
-        <if-compare field="parameters.contactMechTypeId" operator="equals" value="WEB_ADDRESS">
-            <set field="successMessageProperty" value="PartyWebAddressSuccessfullyUpdated"/>
-        </if-compare>
-        <if-compare field="parameters.contactMechTypeId" operator="equals" value="IP_ADDRESS">
-            <set field="successMessageProperty" value="PartyIpAddressSuccessfullyUpdated"/>
-        </if-compare>
-        <if-compare field="parameters.contactMechTypeId" operator="equals" value="ELECTRONIC_ADDRESS">
-            <set field="successMessageProperty" value="PartyElectronicAddressSuccessfullyUpdated"/>
-        </if-compare>
-        <if-compare field="parameters.contactMechTypeId" operator="equals" value="DOMAIN_NAME">
-            <set field="successMessageProperty" value="PartyDomainNameSuccessfullyUpdated"/>
-        </if-compare>
-
-        <make-value entity-name="ContactMech" value-field="ContactMechMap"/>
-        <set-pk-fields value-field="ContactMechMap" map="parameters"/>
-        <find-by-primary-key entity-name="ContactMech" map="ContactMechMap" value-field="oldValue"/>
-        <if-compare-field to-field="oldValue.infoString" field="parameters.infoString" operator="not-equals">
-             <log level="info" message="Contact mech need updating"/>
-            <clone-value value-field="oldValue" new-value-field="newValue"/>
-            <set-nonpk-fields map="parameters" value-field="newValue" set-if-null="false"/>
-            <set field="context.contactMechTypeId" from-field="parameters.contactMechTypeId"/>
-            <set field="context.infoString" from-field="parameters.infoString"/>
-            <call-service service-name="createContactMech" in-map-name="context">
-                <default-message resource="PartyUiLabels" property="${successMessageProperty}"/>
-                <result-to-field result-name="contactMechId" field="newValue.contactMechId"/>
-            </call-service>
-            <field-to-result field="newValue.contactMechId" result-name="contactMechId"/>
-            <field-to-request field="newValue.contactMechId" request-name="contactMechId"/>
-            <else>
-                <log level="info" message="Contact mech not changed"/>
-                <field-to-result field="oldValue.contactMechId" result-name="contactMechId"/>
-                <field-to-request field="oldValue.contactMechId" request-name="contactMechId"/>
-            </else>
-        </if-compare-field>
-    </simple-method>
-
-    <simple-method method-name="createPostalAddress" short-description="Create Contact Mechanism with PostalAddress">
-        <if-compare value="USA" operator="equals" field="parameters.countryGeoId">
-          <if-empty field="parameters.stateProvinceGeoId">
-            <add-error>
-              <fail-property resource="PartyUiLabels" property="PartyStateInUsMissing"/>
-            </add-error>
-          </if-empty>
-        </if-compare>
-        <if-compare value="CAN" operator="equals" field="parameters.countryGeoId">
-          <if-empty field="parameters.stateProvinceGeoId">
-            <add-error>
-              <fail-property resource="PartyUiLabels" property="PartyProvinceInCanadaMissing"/>
-            </add-error>
-          </if-empty>
-        </if-compare>
-        <check-errors/>
-        <make-value entity-name="PostalAddress" value-field="newValue"/>
-        <set field="context.contactMechTypeId" value="POSTAL_ADDRESS"/>
-        <set field="context.contactMechId" from-field="parameters.contactMechId"/>
-        <call-service service-name="createContactMech" in-map-name="context">
-            <default-message resource="PartyUiLabels" property="PartyPostalAddressSuccessfullyCreated"/>
-            <result-to-field result-name="contactMechId" field="newValue.contactMechId"/>
-        </call-service>
-        <set-nonpk-fields map="parameters" value-field="newValue"/>
-        <create-value value-field="newValue"/>
-        <field-to-result field="newValue.contactMechId" result-name="contactMechId"/>
-        <field-to-request field="newValue.contactMechId" request-name="contactMechId"/>
-    </simple-method>
-
-    <simple-method method-name="updatePostalAddress" short-description="Update Contact Mechanism with PostalAddress">
-        <if-compare value="USA" operator="equals" field="parameters.countryGeoId">
-          <if-empty field="parameters.stateProvinceGeoId">
-            <add-error>
-              <fail-property resource="PartyUiLabels" property="PartyStateInUsMissing"/>
-            </add-error>
-          </if-empty>
-        </if-compare>
-        <if-compare value="CAN" operator="equals" field="parameters.countryGeoId">
-          <if-empty field="parameters.stateProvinceGeoId">
-            <add-error>
-              <fail-property resource="PartyUiLabels" property="PartyProvinceInCanadaMissing"/>
-            </add-error>
-          </if-empty>
-        </if-compare>
-        <check-errors/>
-        <make-value entity-name="PostalAddress" value-field="newValue"/>
-        <set-pk-fields value-field="newValue" map="parameters"/>
-        <find-by-primary-key entity-name="PostalAddress" map="newValue" value-field="oldValue"/>
-        <set-nonpk-fields map="parameters" value-field="newValue"/>
-
-        <set field="context.contactMechTypeId" value="POSTAL_ADDRESS"/>
-
-        <if-compare-field field="oldValue" to-field="newValue" operator="not-equals" type="Object">
-            <log level="info" message="Postal address need updating"/>
-            <call-service service-name="createContactMech" in-map-name="context">
-                <default-message resource="PartyUiLabels" property="PartyPostalAddressSuccessfullyUpdated"/>
-                <result-to-field result-name="contactMechId" field="newValue.contactMechId"/>
-            </call-service>
-            <create-value value-field="newValue"/>
-            <else>
-                <set field="context.contactMechId" from-field="parameters.contactMechId"/>
-                <call-service service-name="updateContactMech" in-map-name="context">
-                    <default-message resource="PartyUiLabels" property="PartyPostalAddressSuccessfullyUpdated"/>
-                    <result-to-field result-name="contactMechId" field="newValue.contactMechId"/>
-                </call-service>
-                <if-compare-field to-field="newValue.contactMechId" field="oldValue.contactMechId" operator="not-equals">
-                    <log level="info" message="Postal address need updating, contact mech changed"/>
-                    <create-value value-field="newValue"/>
-                    <else>
-                        <log level="info" message="Postal address unchanged"/>
-                    </else>
-                </if-compare-field>
-            </else>
-        </if-compare-field>
-        <field-to-request field="newValue.contactMechId" request-name="contactMechId"/>
-        <field-to-result field="parameters.contactMechId" result-name="oldContactMechId"/>
-        <field-to-result field="newValue.contactMechId" result-name="contactMechId"/>
-    </simple-method>
-
-    <simple-method method-name="createTelecomNumber" short-description="Create Contact Mechanism with Telecom Number">
-        <make-value entity-name="TelecomNumber" value-field="newValue"/>
-        <set field="context.contactMechTypeId" value="TELECOM_NUMBER"/>
-        <set field="context.contactMechId" from-field="parameters.contactMechId"/>
-        <call-service service-name="createContactMech" in-map-name="context">
-            <default-message resource="PartyUiLabels" property="PartyTelecomNumberSuccessfullyCreated"/>
-            <result-to-field result-name="contactMechId" field="newValue.contactMechId"/>
-        </call-service>
-        <set-nonpk-fields map="parameters" value-field="newValue"/>
-        <create-value value-field="newValue"/>
-        <field-to-result field="newValue.contactMechId" result-name="contactMechId"/>
-        <field-to-request field="newValue.contactMechId" request-name="contactMechId"/>
-    </simple-method>
-
-    <simple-method method-name="updateTelecomNumber" short-description="Update Contact Mechanism with Telecom Number">
-        <make-value entity-name="TelecomNumber" value-field="newValue"/>
-        <set-pk-fields value-field="newValue" map="parameters"/>
-        <find-by-primary-key entity-name="TelecomNumber" map="newValue" value-field="oldValue"/>
-        <set-nonpk-fields map="parameters" value-field="newValue"/>
-        <set field="context.contactMechTypeId" value="TELECOM_NUMBER"/>
-
-        <if-compare-field field="oldValue" to-field="newValue" operator="not-equals" type="Object">
-            <log level="info" message="Telecom number needs updating"/>
-            <call-service service-name="createContactMech" in-map-name="context">
-                <default-message resource="PartyUiLabels" property="PartyTelecomNumberSuccessfullyUpdated"/>
-                <result-to-field result-name="contactMechId" field="newValue.contactMechId"/>
-            </call-service>
-            <create-value value-field="newValue"/>
-            <else>
-                <set field="context.contactMechId" from-field="parameters.contactMechId"/>
-                <call-service service-name="updateContactMech" in-map-name="context">
-                    <default-message resource="PartyUiLabels" property="PartyTelecomNumberSuccessfullyUpdated"/>
-                    <result-to-field result-name="contactMechId" field="newValue.contactMechId"/>
-                </call-service>
-                <if-compare-field to-field="newValue.contactMechId" field="oldValue.contactMechId" operator="not-equals">
-                    <log level="info" message="Telecom Number need updating, contact mech changed"/>
-                    <create-value value-field="newValue"/>
-                    <else>
-                        <log level="info" message="Telecom Number unchanged"/>
-                    </else>
-                </if-compare-field>
-            </else>
-        </if-compare-field>
-        <field-to-result field="newValue.contactMechId" result-name="contactMechId"/>
-        <field-to-result field="parameters.contactMechId" result-name="oldContactMechId"/>
-    </simple-method>
-
-    <simple-method method-name="createEmailAddress" short-description="Create an email address contact mechanism">
-        <call-map-processor xml-resource="component://party/minilang/contact/ContactMechMapProcs.xml"
-            processor-name="emailAddress" in-map-name="parameters" out-map-name="context"/>
-        <check-errors/>
-        <set field="context.contactMechTypeId" value="EMAIL_ADDRESS"/>
-        <call-service service-name="createContactMech" in-map-name="context">
-            <default-message resource="PartyUiLabels" property="PartyEmailAddressSuccessfullyCreated"/>
-            <result-to-result result-name="contactMechId"/>
-            <result-to-request result-name="contactMechId"/>
-        </call-service>
-    </simple-method>
-    <simple-method method-name="updateEmailAddress" short-description="Update an email address contact mechanism">
-        <call-map-processor xml-resource="component://party/minilang/contact/ContactMechMapProcs.xml"
-            processor-name="emailAddress" in-map-name="parameters" out-map-name="context"/>
-        <check-errors/>
-        <set field="context.contactMechTypeId" value="EMAIL_ADDRESS"/>
-        <call-service service-name="updateContactMech" in-map-name="context">
-            <default-message resource="PartyUiLabels" property="PartyEmailAddressSuccessfullyUpdated"/>
-            <result-to-result result-name="contactMechId"/>
-            <result-to-request result-name="contactMechId"/>
-        </call-service>
-    </simple-method>
-
-    <simple-method method-name="sendVerifyEmailAddressNotification" short-description="Send an email to the person for Verification of his Email Address" login-required="false">
-        <entity-condition entity-name="ProductStoreEmailSetting" list="productStoreEmailSettings">
-            <condition-list>
-                <condition-expr field-name="emailType" operator="equals" value="PRDS_EMAIL_VERIFY"/>
-            </condition-list>
-        </entity-condition>
-        <set field="lookupHash.emailAddress" from-field="parameters.emailAddress"/>
-        <find-by-primary-key value-field="emailAddressVerification" entity-name="EmailAddressVerification" map="lookupHash"/>
-        <set field="bodyParameters.verifyHash" from-field="emailAddressVerification.verifyHash"/>
-        <first-from-list entry="storeEmail" list="productStoreEmailSettings"/>
-        <entity-and entity-name="WebSite" list="webSites">
-            <field-map field-name="productStoreId" from-field="storeEmail.productStoreId"/>
-        </entity-and>
-        <first-from-list entry="webSite" list="webSites"/>
-        <if-not-empty field="storeEmail.bodyScreenLocation">
-            <set field="emailParams.sendTo" from-field="parameters.emailAddress"/>
-            <set field="emailParams.subject" from-field="storeEmail.subject"/>
-            <set field="emailParams.sendFrom" from-field="storeEmail.fromAddress"/>
-            <set field="emailParams.sendCc" from-field="storeEmail.ccAddress"/>
-            <set field="emailParams.sendBcc" from-field="storeEmail.bccAddress"/>
-            <set field="emailParams.contentType" from-field="storeEmail.contentType"/>
-            <set field="emailParams.bodyParameters" from-field="bodyParameters"/>
-            <set field="emailParams.bodyScreenUri" from-field="storeEmail.bodyScreenLocation"/>
-            <map-to-map to-map="emailParams.bodyParameters" map="bodyParameters"/>
-            <set field="emailParams.webSiteId" from-field="webSite.webSiteId"/>
-            <call-service service-name="sendMailFromScreen" in-map-name="emailParams"/>
-        </if-not-empty>
-    </simple-method>
-    <simple-method method-name="verifyEmailAddress" short-description="Verify an Email Address through verifyHash and expireDate" login-required="false">
-        <entity-and entity-name="EmailAddressVerification" list="emailAddressVerifications">
-            <field-map field-name="verifyHash" from-field="parameters.verifyHash"/>
-        </entity-and>
-
-        <first-from-list list="emailAddressVerifications" entry="emailAddressVerification"/>
-        <if-not-empty field="emailAddressVerification">
-            <now-timestamp field="nowTimestamp"/>
-            <if-compare-field field="emailAddressVerification.expireDate" to-field="nowTimestamp" operator="less">
-                 <add-error><fail-property resource="PartyUiLabels" property="PartyEmailAddressVerificationExpired"/></add-error>
-            </if-compare-field>
-        <else>
-            <add-error><fail-property resource="PartyUiLabels" property="PartyEmailAddressNotExist"/></add-error>
-        </else>
-        </if-not-empty>
-        <check-errors/>
-    </simple-method>
-</simple-methods>
diff --git a/applications/party/servicedef/services.xml b/applications/party/servicedef/services.xml
index cec56db..72fd7c6 100644
--- a/applications/party/servicedef/services.xml
+++ b/applications/party/servicedef/services.xml
@@ -372,13 +372,6 @@ under the License.
     </service>
 
     <!-- ContactMech services -->
-    <service name="createContactMech" engine="simple"
-            location="component://party/minilang/contact/ContactMechServices.xml" invoke="createContactMech" auth="true">
-        <description>Create a ContactMech</description>
-        <auto-attributes entity-name="ContactMech" include="nonpk" mode="IN" optional="false"/>
-        <auto-attributes entity-name="ContactMech" include="pk" mode="INOUT" optional="true"/>
-        <override name="infoString" optional="true"/>
-    </service>
     <service name="createPartyContactMech" engine="simple"
             location="component://party/minilang/contact/PartyContactMechServices.xml" invoke="createPartyContactMech" auth="true">
         <description>Create a PartyContactMech</description>
@@ -393,13 +386,6 @@ under the License.
             </type-validate>
         </attribute>
     </service>
-    <service name="updateContactMech" engine="simple"
-            location="component://party/minilang/contact/ContactMechServices.xml" invoke="updateContactMech" auth="true">
-        <description>Update a ContactMech</description>
-        <attribute name="contactMechId" type="String" mode="INOUT" optional="false"/>
-        <attribute name="contactMechTypeId" type="String" mode="IN" optional="false"/>
-        <attribute name="infoString" type="String" mode="IN" optional="true"/>
-    </service>
     <service name="updatePartyContactMech" engine="simple"
             location="component://party/minilang/contact/PartyContactMechServices.xml" invoke="updatePartyContactMech" auth="true">
         <description>Update a PartyContactMech</description>
@@ -417,15 +403,6 @@ under the License.
         <attribute name="partyId" type="String" mode="IN" optional="true"/>
         <attribute name="contactMechId" type="String" mode="IN" optional="false"/>
     </service>
-    <service name="createPostalAddress" engine="simple"
-            location="component://party/minilang/contact/ContactMechServices.xml" invoke="createPostalAddress" auth="true">
-        <description>Create a Postal Address</description>
-        <auto-attributes entity-name="PostalAddress" include="all" mode="IN" optional="true"/>
-        <attribute name="contactMechId" type="String" mode="OUT" optional="false"/>
-        <override name="address1" optional="false"/>
-        <override name="city" optional="false"/>
-        <override name="postalCode" optional="false"/>
-    </service>
     <!-- Party ContachMech reverse find -->
     <service name="findPartyFromEmailAddress" engine="simple"
         location="component://party/minilang/contact/PartyContactMechServices.xml" invoke="findPartyFromEmailAddress" auth="true">
@@ -469,20 +446,6 @@ under the License.
         <override name="city" optional="false"/>
         <override name="postalCode" optional="false"/>
     </service>
-    <service name="updatePostalAddress" engine="simple"
-            location="component://party/minilang/contact/ContactMechServices.xml" invoke="updatePostalAddress" auth="true">
-        <description>Update a Postal Address</description>
-        <auto-attributes entity-name="PostalAddress" include="nonpk" mode="IN" optional="true"/>
-        <attribute name="contactMechId" type="String" mode="INOUT" optional="false"/> <!-- the out paramater is the id of the new address -->
-        <attribute name="directions" type="String" mode="IN" optional="true"/> <!-- ?? -->
-        <attribute name="oldContactMechId" type="String" mode="OUT" optional="false"/> <!-- this is the id of the old address -->
-        <attribute name="partyId" type="String" mode="IN" optional="true"/>
-        <attribute name="latitude" type="String" mode="IN" optional="true"/>
-        <attribute name="longitude" type="String" mode="IN" optional="true"/>
-        <override name="address1" optional="false"/>
-        <override name="city" optional="false"/>
-        <override name="postalCode" optional="false"/>
-    </service>
     <service name="updatePartyPostalAddress" engine="simple"
             location="component://party/minilang/contact/PartyContactMechServices.xml" invoke="updatePartyPostalAddress" auth="true">
         <description>Update a Postal Address</description>
@@ -495,12 +458,6 @@ under the License.
         <override name="city" optional="false"/>
         <override name="postalCode" optional="false"/>
     </service>
-    <service name="createTelecomNumber" engine="simple"
-            location="component://party/minilang/contact/ContactMechServices.xml" invoke="createTelecomNumber" auth="true">
-        <description>Create a Telecommunications Number</description>
-        <auto-attributes entity-name="TelecomNumber" include="all" mode="IN" optional="true"/>
-        <attribute name="contactMechId" type="String" mode="OUT" optional="false"/>
-    </service>
     <service name="createPartyTelecomNumber" engine="simple"
             location="component://party/minilang/contact/PartyContactMechServices.xml" invoke="createPartyTelecomNumber" auth="true">
         <description>Create a Telecommunications Number</description>
@@ -510,13 +467,6 @@ under the License.
         <attribute name="contactMechPurposeTypeId" type="String" mode="IN" optional="true"/>
         <attribute name="contactMechId" type="String" mode="OUT" optional="false"/>
     </service>
-    <service name="updateTelecomNumber" engine="simple"
-            location="component://party/minilang/contact/ContactMechServices.xml" invoke="updateTelecomNumber" auth="true">
-        <description>Update a Telecommunications Number</description>
-        <auto-attributes entity-name="TelecomNumber" include="nonpk" mode="IN" optional="true"/>
-        <attribute name="contactMechId" type="String" mode="INOUT" optional="false"/>
-        <attribute name="oldContactMechId" type="String" mode="OUT" optional="false"/>
-    </service>
     <service name="updatePartyTelecomNumber" engine="simple"
             location="component://party/minilang/contact/PartyContactMechServices.xml" invoke="updatePartyTelecomNumber" auth="true">
         <description>Update a Telecommunications Number</description>
@@ -525,14 +475,6 @@ under the License.
         <auto-attributes entity-name="TelecomNumber" include="nonpk" mode="IN" optional="true"/>
         <attribute name="contactMechId" type="String" mode="INOUT" optional="false"/>
     </service>
-    <service name="createEmailAddress" engine="simple"
-            location="component://party/minilang/contact/ContactMechServices.xml" invoke="createEmailAddress" auth="true">
-        <description>Create an Email Address</description>
-        <auto-attributes entity-name="ContactMech" include="nonpk" mode="IN" optional="true"/>
-        <auto-attributes entity-name="ContactMech" include="pk" mode="OUT" optional="false"/>
-        <attribute name="emailAddress" type="String" mode="IN" optional="false"/>
-        <override name="infoString" optional="true"/>
-    </service>
     <service name="createPartyEmailAddress" engine="simple"
             location="component://party/minilang/contact/PartyContactMechServices.xml" invoke="createPartyEmailAddress" auth="true">
         <description>Create an Email Address</description>
@@ -543,12 +485,6 @@ under the License.
         <attribute name="contactMechId" type="String" mode="INOUT" optional="true"/>
         <attribute name="emailAddress" type="String" mode="IN" optional="false"/>
     </service>
-    <service name="updateEmailAddress" engine="simple"
-            location="component://party/minilang/contact/ContactMechServices.xml" invoke="updateEmailAddress" auth="true">
-        <description>Update an Email Address</description>
-        <attribute name="contactMechId" type="String" mode="INOUT" optional="false"/>
-        <attribute name="emailAddress" type="String" mode="IN" optional="false"/>
-    </service>
     <service name="updatePartyEmailAddress" engine="simple"
             location="component://party/minilang/contact/PartyContactMechServices.xml" invoke="updatePartyEmailAddress" auth="true">
         <description>Update an Email Address</description>
@@ -582,22 +518,6 @@ under the License.
         <auto-attributes entity-name="FtpAddress" mode="IN" optional="true"/>
         <attribute name="contactMechId" type="String" mode="INOUT"/>
     </service>
-    <service name="createFtpAddress" default-entity-name="FtpAddress" engine="groovy" invoke="createFtpAddress"
-             location="component://party/groovyScripts/party/ContactMechServices.groovy">
-        <description>create FtpAddress</description>
-        <permission-service service-name="partyBasePermissionCheck" main-action="CREATE"/>
-        <auto-attributes mode="OUT" include="pk"/>
-        <auto-attributes mode="IN" include="nonpk" optional="true"/>
-    </service>
-    <service name="updateFtpAddressWithHistory" default-entity-name="FtpAddress" engine="groovy" invoke="updateFtpAddressWithHistory"
-        location="component://party/groovyScripts/party/ContactMechServices.groovy">
-        <description>update FtpAddress</description>
-        <permission-service service-name="partyBasePermissionCheck" main-action="UPDATE"/>
-        <auto-attributes mode="IN" include="pk"/>
-        <auto-attributes mode="IN" include="nonpk" optional="true"/>
-        <attribute name="contactMechId" type="String" mode="INOUT"/> <!-- the out paramater is the id of the new address -->
-        <attribute name="oldContactMechId" type="String" mode="OUT"/> <!-- this is the id of the old address -->
-    </service>
     <!-- contact mech attribute services -->
     <service name="createContactMechAttribute" engine="entity-auto" default-entity-name="ContactMechAttribute" invoke="create" auth="true">
         <description>create a contact mech attribute record</description>
@@ -1110,12 +1030,12 @@ under the License.
         <attribute name="verifyHash" type="String" mode="OUT" optional="false"/>
         <attribute name="expireDate" type="String" mode="IN" optional="true"/>
     </service>
-    <service name="sendVerifyEmailAddressNotification" engine="simple"
-        location="component://party/minilang/contact/ContactMechServices.xml" invoke="sendVerifyEmailAddressNotification">
+    <service name="sendVerifyEmailAddressNotification" engine="groovy"
+             location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="sendVerifyEmailAddressNotification">
         <attribute name="emailAddress" type="String" mode="IN" optional="false"/>
     </service>
-    <service name="verifyEmailAddress" engine="simple"
-             location="component://party/minilang/contact/ContactMechServices.xml" invoke="verifyEmailAddress">
+    <service name="verifyEmailAddress" engine="groovy"
+             location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="verifyEmailAddress">
         <attribute name="verifyHash" type="String" mode="IN" optional="false"/>
     </service>
 
diff --git a/applications/party/servicedef/services_contact.xml b/applications/party/servicedef/services_contact.xml
index 55a619c..1fa4461 100644
--- a/applications/party/servicedef/services_contact.xml
+++ b/applications/party/servicedef/services_contact.xml
@@ -24,7 +24,89 @@ under the License.
     <vendor>OFBiz</vendor>
     <version>1.0</version>
 
-    <!-- Party contact services -->
+    <!-- contact mech services -->
+    <service name="createContactMech" default-entity-name="ContactMech" engine="entity-auto" invoke="create" auth="true">
+        <description>Create a new ContactMech Record</description>
+        <auto-attributes mode="INOUT" include="pk" optional="true"/>
+        <auto-attributes mode="IN" include="nonpk" optional="false"/>
+        <override name="infoString" optional="true"/>
+    </service>
+    <service name="updateContactMech" default-entity-name="ContactMech" engine="groovy"
+             location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="updateContactMech" auth="true">
+        <description>Update a ContactMech</description>
+        <auto-attributes mode="INOUT" include="pk" optional="false"/>
+        <auto-attributes mode="IN" include="nonpk" optional="true"/>
+    </service>
+
+    <service name="createPostalAddress" engine="groovy"
+             location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="createPostalAddress" auth="true">
+        <description>Create a Postal Address</description>
+        <auto-attributes entity-name="PostalAddress" include="all" mode="IN" optional="true"/>
+        <attribute name="contactMechId" type="String" mode="OUT" optional="false"/>
+        <override name="address1" optional="false"/>
+        <override name="city" optional="false"/>
+        <override name="postalCode" optional="false"/>
+    </service>
+    <service name="updatePostalAddress" engine="groovy"
+            location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="updatePostalAddress" auth="true">
+        <description>Update a Postal Address</description>
+        <auto-attributes entity-name="PostalAddress" include="nonpk" mode="IN" optional="true"/>
+        <attribute name="contactMechId" type="String" mode="INOUT" optional="false"/> <!-- the out parameter is the id of the new address -->
+        <attribute name="directions" type="String" mode="IN" optional="true"/> <!-- ?? -->
+        <attribute name="oldContactMechId" type="String" mode="OUT" optional="false"/> <!-- this is the id of the old address -->
+        <attribute name="partyId" type="String" mode="IN" optional="true"/><!-- ?? -->
+        <attribute name="latitude" type="String" mode="IN" optional="true"/><!-- ?? -->
+        <attribute name="longitude" type="String" mode="IN" optional="true"/><!-- ?? -->
+        <override name="address1" optional="false"/>
+        <override name="city" optional="false"/>
+        <override name="postalCode" optional="false"/>
+    </service>
+
+    <service name="createTelecomNumber" engine="groovy"
+             location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="createTelecomNumber" auth="true">
+        <description>Create a Telecommunications Number</description>
+        <auto-attributes entity-name="TelecomNumber" include="all" mode="IN" optional="true"/>
+        <attribute name="contactMechId" type="String" mode="OUT" optional="false"/>
+    </service>
+    <service name="updateTelecomNumber" engine="groovy"
+             location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="updateTelecomNumber" auth="true">
+        <description>Update a Telecommunications Number</description>
+        <auto-attributes entity-name="TelecomNumber" include="nonpk" mode="IN" optional="true"/>
+        <attribute name="contactMechId" type="String" mode="INOUT" optional="false"/>
+        <attribute name="oldContactMechId" type="String" mode="OUT" optional="false"/>
+    </service>
+
+    <service name="createEmailAddress" engine="groovy"
+             location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="createEmailAddress" auth="true">
+        <description>Create an Email Address</description>
+        <auto-attributes entity-name="ContactMech" include="nonpk" mode="IN" optional="true"/>
+        <auto-attributes entity-name="ContactMech" include="pk" mode="OUT" optional="false"/>
+        <attribute name="emailAddress" type="String" mode="IN" optional="false"/>
+        <override name="infoString" optional="true"/>
+    </service>
+    <service name="updateEmailAddress" engine="groovy"
+             location="component://party/groovyScripts/contact/ContactMechServices.groovy" invoke="updateEmailAddress" auth="true">
+        <description>Update an Email Address</description>
+        <attribute name="contactMechId" type="String" mode="INOUT" optional="false"/>
+        <attribute name="emailAddress" type="String" mode="IN" optional="false"/>
+    </service>
+    <service name="createFtpAddress" default-entity-name="FtpAddress" engine="groovy" invoke="createFtpAddress"
+             location="component://party/groovyScripts/party/ContactMechServices.groovy">
+        <description>create FtpAddress</description>
+        <permission-service service-name="partyBasePermissionCheck" main-action="CREATE"/>
+        <auto-attributes mode="OUT" include="pk"/>
+        <auto-attributes mode="IN" include="nonpk" optional="true"/>
+    </service>
+    <service name="updateFtpAddressWithHistory" default-entity-name="FtpAddress" engine="groovy" invoke="updateFtpAddressWithHistory"
+             location="component://party/groovyScripts/party/ContactMechServices.groovy">
+        <description>update FtpAddress</description>
+        <permission-service service-name="partyBasePermissionCheck" main-action="UPDATE"/>
+        <auto-attributes mode="IN" include="pk"/>
+        <auto-attributes mode="IN" include="nonpk" optional="true"/>
+        <attribute name="contactMechId" type="String" mode="INOUT"/> <!-- the out paramater is the id of the new address -->
+        <attribute name="oldContactMechId" type="String" mode="OUT"/> <!-- this is the id of the old address -->
+    </service>
+
     <service name="createContactMechType" default-entity-name="ContactMechType" engine="entity-auto" invoke="create" auth="true">
         <description>Create a new ContactMech Type Record</description>
         <auto-attributes mode="INOUT" include="pk" optional="true"/>