Updated: SP5 (in CX 13.2) Commit Bug w/ active CPM

Updated 2013-12-17: Additional tests found that this issue only manifests when a CPM is active on an object. The post has been updated to reflect the new findings

This morning we discovered a bug in the newly released SP5 on our February 2013 site (13.2). This issue is around Connect PHP and the 'commit' method when a CPM is present. If a 'commit' is explicitly called in your Customer Portal code (controller, model, other) any object pointers that had a value that was changed will lose visibility to certain field values when a CPM is active for that object. We've observed this behavior so far on all object types that have a CPM in our systems (Contact, Incident, Opportunity). To be clear, the fields are still there, but you can't access their values after the commit. This behavior does not effect all fields, but the fields that do exhibit this problem are very important.

So far we've seen visibility lost on the following fields in our quick tests with a Contact:

  • Login
  • Name fields (Name->Last, Name->First)
  • Address->Street

Test Code

I created the following test as a controller. This test is specific to my user account on the site, but it can be modified to run tests on your own site. My inline code comments show which assertions succeed and fail.

<?php namespace Custom\Controllers; class SP5Regression extends \RightNow\Controllers\Base { function __construct() { parent::__construct(); } public function test(){ $contact = \RightNow\Connect\v1_2\Contact::fetch(64582); assert('$contact->Login == "pta_524ca9322905f3.10140019"'); assert('$contact->Name->Last == "Rowse"'); assert('$contact->Emails[0]->Address == "andy@45n.co.invalid"'); assert('$contact->CustomFields->c->outreach_opt_in->LookupName == "Yes - Active"'); assert('$contact->Address->Street == "100 Main Street"'); //Make sure an update occurs $contact->Name->First = ($contact->Name->First == "Andy" ) ? "Andrew" : "Andy"; \RightNow\Libraries\AbuseDetection::isAbuse(); $contact->save(); \RightNow\Connect\v1_2\ConnectAPI::commit(); assert('$contact->Login == "pta_524ca9322905f3.10140019"'); //fails assert('$contact->Name->Last == "Rowse"'); //fails assert('$contact->Emails[0]->Address == "andy@45n.co.invalid"'); //succeeds assert('$contact->CustomFields->c->outreach_opt_in->LookupName == "Yes - Active"'); //succeeds assert('$contact->Address->Street == "100 Main Street"'); //fails } }

I created the following "Blank" CPM that returns immediately and activated it for my Contact object.

<?php /** * CPMObjectEventHandler: contact_cpm_test * Package: RN * Objects: Contact * Actions: Create, Update * Version: 1.2 * Purpose: Description */ use \RightNow\CPM\v1 as RNCPM; use \RightNow\Connect\v1_2 as RNCPHP; class contact_cpm_test implements RNCPM\ObjectEventHandler { /** * * @param string $run_mode * @param string $action * @param Object $obj * @param type $n_cycles * @return type */ public static function apply($run_mode, $action, $contact, $n_cycles) { if ($n_cycles == 0) { } } } class contact_cpm_test_TestHarness implements RNCPM\ObjectEventHandler_TestHarness { const ACTION_CREATE = 1; const ACTION_UPDATE = 2; const ACTION_DESTROY = 3; public static function setup() { } public static function fetchObject($action, $object_type) { return array(); } public static function validate($action, $object) { return true; } protected static function testTrigger($object) { echo "Success."; return true; } public static function cleanup() { } }

Work Arounds

The only work around we've found is the remove the commit() call if you can spare it. In CP, a commit is implicitly called at the end of each process (that exits normally). If you legitimately need an explicit commit and need to access object fields afterwards, then you have a problem and need this defect fixed.

Comments

An option for working around this issue is to run a ROQL query to and retrieve the object data that is released, then manually rebuild the object data.

I'm an Oracle developer that works in the bowels of the server for this application. Commit() problems would be in my purview.
I deployed a parallel version of your Sp5regression controller, one that matched my contact data, and I do not get any asserts failures. Does the problem have more context than shown in your simple example?
I'd be happy to take a look at a log file produced during your commit() anomaly, if you can scare one up.

Hi Randy,
Thanks for the reply. I've sent some additional info to your email including a link to a live controller with expanded assertions that show field access failures in other objects (Contact, Incident, Opp).

Hopefully you can turn on PHP tracing for the site and figure out what is happening. This was definitely something that was working in SP4, and stopped as soon as SP5 was applied.

Did your test use CP? or a script out of the custom directory (or command line execution)? If it wasn't obvious from the namespacing used in my controller, we are using CP 3 (3.0.2)

We've reproduced the anomaly in our testing environment, given the new CPM information. We are currently debugging to find the root cause. More later.

I did some more testing this AM and found that the culprit of this issue is CPM's. The presence of a CPM for an object type will cause the field access problem described in this post. It doesn't matter what the CPM does, as long as it's present.

To test, removed all CPM mappings from my objects and all of my assertions passed. I then went back and added a blank CPM for my Contact object (blank == does nothing and returns immediately) and once again my assertions failed for my Contact object tests.

Our CPM's existed before SP5 and worked fine. There is still a bug in SP5 but the area of impact is a bit more narrow.

Zircon - This is a contributing Drupal Theme
Design by WeebPal.