Difficulty: Intermediate
TL;DR
Problem: An OIC integration triggered by a Fusion business event has a filter expression that validates cleanly but never produces an instance on a matching record. Stack: OIC Gen 3 ERP Cloud Adapter (trigger), Fusion SCM item business events, XPath filter expressions. Read this if: you are filtering a Fusion event subscription by OrganizationCode, ItemClass, or any field, and your xpathExpr is silently matching nothing.
Tested on / Prerequisites
Tested on Fusion 26B with OIC Gen 3. Requires an active integration using the ERP Cloud Adapter as a trigger, subscribed to a Fusion business event, and access to the OIC integration tracking/activity stream to download the debug payload.
Why an OIC business event filter validates but never fires
An OIC business event filter is the natural way to fire an integration only for specific records — but it’s also where teams lose hours.
We were subscribed to the Fusion item-creation business event (SCM_EGP_ITEM_CREATE) through the ERP Cloud Adapter trigger, and the customer only wanted the integration to run for one specific inventory organization. The obvious move is a filter expression in the trigger’s Filter Expr field, wrapped in <xpathExpr> tags — fire only when OrganizationCode equals a given value.
The expression validated in OIC. It also matched perfectly in a standalone XPath tester. And it produced zero instances at runtime. Remove the filter, and instances fire normally — so the subscription and activation were fine. The problem was entirely the expression itself: it was written against the wrong payload.
This is the trap Oracle’s tooling sets for you. The designer’s tracking stream exposes two different payload representations of the same event, with different XML structures. An XPath that matches one will not match the other. Build your filter against the one the designer shows you in the mapper, and it validates against nothing the runtime ever sees.
The two payloads — and why only one is the right one
When you open a tracked instance in the OIC designer, you can download two payloads. They are not two views of the same XML; they are structurally different documents.
This can be extracted from activity JSON file that can be downloaded from instance Debug.

TriggerInternalPayload_tTextPayload is the enriched, normalized payload the adapter hands to your integration mapper. Its root walks onEvent → findItemResponse → result → [fields]. This is the one you map from in Assign operations — and it is not what the event filter evaluates.
TriggerWirePayload_tTextPayload is the raw SOAP envelope Fusion actually sends over the wire. Its root walks env:Envelope → env:Body → findItemResponse → result → Value → [fields]. This is the message the event filter is evaluated against.
The critical structural difference is one element: the wire payload has an extra Value wrapper (in the generic ADF types namespace) sitting between result and the item fields. The internal payload collapses that wrapper out. Every filter built from the internal capture omits Value — and therefore never matches the wire message the filter actually sees.
The screenshot below is the designer’s Sources tree — the internal representation. Note that it goes straight from Result to Item Id / Organization Id / Organization Code, with no Value node in between. This is exactly the view that misleads you: it is correct for mapping, wrong for filtering.
Worked example — filter item creation by organization
Goal: fire the integration only for a single inventory organization. We will use the mock organization code XX throughout; substitute your real value.
What the internal payload looks like (misleading)
Captured from TriggerInternalPayload_tTextPayload — note there is no Value node:
<ns01:onEvent xmlns:ns01="...erp/process_REQUEST/types"> <ns1:findItemResponse xmlns:ns0=".../itemServiceV2/types/"> <ns0:result xmlns:ns1=".../itemServiceV2/"> <ns1:ItemId>300000000000001</ns1:ItemId> <ns1:OrganizationId>300000000000000</ns1:OrganizationId> <ns1:OrganizationCode>XX</ns1:OrganizationCode> <!-- ... --> </ns0:result> </ns1:findItemResponse> </ns01:onEvent>
A filter built from this structure — $eventPayload/ns0:result/ns1:OrganizationCode='XX' — validates, and matches in a tester. It never fires in OIC.
What the wire payload looks like (correct)
Captured from TriggerWirePayload_tTextPayload — the real SOAP message, with the Value wrapper present:
<env:Envelope ...> <env:Header> ... fmw-context ... </env:Header> <env:Body> <ns0:findItemResponse xmlns:ns0=".../itemServiceV2/types/"> <ns2:result xmlns:ns0="http://xmlns.oracle.com/adf/svc/types/" xmlns:ns1=".../itemServiceV2/" xmlns:ns2=".../itemServiceV2/types/" xsi:type="ns0:DataObjectResult"> <ns0:Value xsi:type="ns1:Item"> <ns1:ItemId>300000000000001</ns1:ItemId> <ns1:OrganizationId>300000000000000</ns1:OrganizationId> <ns1:OrganizationCode>XX</ns1:OrganizationCode> <!-- ... --> </ns0:Value> </ns2:result> </ns0:findItemResponse> </env:Body> </env:Envelope>
Our solution — build the filter against the wire payload
Anchor at $eventPayload, walk through result, then Value, then the field — using three distinct namespace prefixes.
Filter by OrganizationCode (string — value in quotes):
<xpathExpr xmlns:ns_0="http://xmlns.oracle.com/adf/svc/types/" xmlns:ns_1="http://xmlns.oracle.com/apps/scm/productModel/items/itemServiceV2/" xmlns:ns_2="http://xmlns.oracle.com/apps/scm/productModel/items/itemServiceV2/types/">$eventPayload/ns_2:result/ns_0:Value/ns_1:OrganizationCode='XX'</xpathExpr>
Filter by OrganizationId instead (numeric — no quotes):
<xpathExpr xmlns:ns_0="http://xmlns.oracle.com/adf/svc/types/" xmlns:ns_1="http://xmlns.oracle.com/apps/scm/productModel/items/itemServiceV2/" xmlns:ns_2="http://xmlns.oracle.com/apps/scm/productModel/items/itemServiceV2/types/">$eventPayload/ns_2:result/ns_0:Value/ns_1:OrganizationId=300000000000000</xpathExpr>
The namespace mapping that trips everyone up
The single most common reason a corrected filter still fails: result, Value, and the item fields live in three different namespaces, and reusing one prefix for all of them silently evaluates to false.
ns_2bindsresult— namespace.../items/itemServiceV2/types/(with the trailingtypes/).ns_0bindsValue— the generic ADF namespacehttp://xmlns.oracle.com/adf/svc/types/.ns_1bindsOrganizationCode,OrganizationId, and the other item fields — namespace.../items/itemServiceV2/(notypes/).
result and the fields differ only by a trailing types/ segment — easy to miss, fatal if collapsed. Value is a third namespace entirely. Declare one prefix per distinct URI.
The general method — any ERP/SCM/CRM event
This is not specific to item creation. The same procedure works for any Fusion ADF business event reaching OIC:
- Activate the integration without a filter, and create one matching record so an instance fires.
- In the tracked instance, open
TriggerWirePayload_tTextPayload— not the internal one. - Read the real path from the SOAP
env:Bodydown. For Fusion ADF services it is almost alwaysresult / Value / <field>. - Read each element’s exact namespace URI from the wire payload, and declare a separate prefix per distinct URI.
- Build
$eventPayload/<ns:result>/<ns:Value>/<ns:field>=value— string values in quotes, numeric values without. - Save, reactivate (this re-registers the subscription in Fusion), and test with both a matching and a non-matching record.
How to verify
The filter is registered on the Fusion side, not just inside OIC. Confirm it directly at the FA instance event subscriptions endpoint:
https://<FA-host>/soa-infra/PublicEvent/subscriptions
The subscription JSON for your integration endpoint should contain a filter attribute holding your exact <xpathExpr> string. If the filter value there does not match what you saved in OIC, the reactivation did not re-register — reactivate again. If the filter is present and correct but instances still do not fire on a matching record, the expression itself is wrong: go back to the wire payload and recheck the namespaces.
Gotchas / Production notes
Filtering
- It validates against nothing. OIC’s filter validator checks XPath syntax, not whether the path exists in the runtime message. A filter against the internal payload passes validation and fails silently. Validation green is not a signal that the filter works.
- External testers lie if you feed them the wrong capture. Pasting the internal payload into an online XPath tester will show your expression matching — because it matches the internal structure. Always test against the wire capture.
- One prefix per distinct URI.
result(.../types/),Value(ADFadf/svc/types/), and the fields (.../itemServiceV2/) are three namespaces. Reusing a prefix doesn’t error — it evaluates to false.
Activation
- Reactivate to re-register. The filter is pushed to the Fusion subscription only on activation. Editing the expression without reactivating leaves the old filter (or none) registered server-side.
- Confirm at the subscriptions endpoint, not just in OIC. The OIC console showing your filter is not proof Fusion received it. The
/soa-infra/PublicEvent/subscriptionsendpoint is the source of truth.
Conclusion
A filter that validates but never fires costs hours of dead-end debugging because every tool you reach for says the expression is fine. The fix is knowing which of the two payloads the runtime actually evaluates — the wire payload — and reading your namespaces straight off it. Once you do, event-level filtering becomes a reliable way to keep integration volume (and OIC consumption) down to only the records that matter.
Facing a similar challenge?
Wrestling with a Fusion business event subscription that won’t fire, or trying to scope an OIC integration to exactly the right records? We’ve shipped this pattern at multiple enterprise clients and we can do the same for you. Reach out at info@cidsolutions.co.il or WhatsApp — let’s get it solved.
Tags: Oracle Fusion, OIC, Oracle Integration Cloud, ERP Cloud Adapter, Business Events, XPath, SCM, Item Creation
Related posts:
