Yone Moreno · Mar 28, 2022

Production message filtering: How could we find a substring inside a %XML.GlobalCharacterStream?


First of all thanks for your help

How would you recommend us to filter in the message viewer to find inside a property called "mensaje" of type "%XML.GlobalCharacterStream" which is inside a class called "Mensajes.Request.Laboratorio.peticionER7Request", the text "24642"?

We have tried:

It shows:

ERROR #5540: SQLCODE: Message -37: Unary function %EXTERNAL does not support sequence fields.

ORIGIN ELEMENT: %ZEN.Component.tablePane (resultsTable)


In addition we have tried to output the %XML.GlobalCharacterStream as a %String, using Read() function, and then trying to filter with "Contains" method as follows:


We observe:

ERROR #5540: SQLCODE: Message -29: The field 'MESSAGES_REQUEST_REQUEST_LABORATORIO.PETICIONER7REQUEST.MESSAGE->' was not found in the corresponding tables.  ^ SELECT TOP ? head . ID AS ID , { fn RIGHT ( %EXTERNAL ( head . TimeCreated ) , ? ) } AS TimeCreated , head . SessionId AS Session , head . Status AS Status , CASE head . IsError WHEN ? THEN ? ELSE ? END AS Error , head . SourceConfigName AS Source , head . TargetConfigName AS Target , head . MessageBodyClassName AS BodyClassname , head . MessageBodyId AS BodyId , Mensajes_Request_Laboratorio . peticionER7Request . %ID AS Body_ID , Mensajes_Request_Laboratorio . peticionER7Request . mensaje -> READ

SOURCE ELEMENT: %ZEN.Component.tablePane (resultsTable)


Plus we have also read some documentation:

Filtering with Extended Criteria

Filter Conditions ( Contains )


Thanks for your time


How would you recommend us to filter in the message viewer to find inside a property called "mensaje" of type "%XML.GlobalCharacterStream" which is inside a class called "Mensajes.Request.Laboratorio.peticionER7Request", the text "24642"?



Thanks for your help, time and replies


Product version: Caché 2017.1
$ZV: Cache for UNIX (Red Hat Enterprise Linux for x86-64) 2017.2.1 (Build 801_3_18358U) Tue Jul 24 2018 16:36:10 EDT
0 153
Discussion (2)2
Log in or sign up to continue

method FindAt(position As %Integer, target As %CacheString, ByRef tmpstr As %CacheString = "", caseinsensitive As %Boolean = 0) as %Integer

Find the first occurrence of target in the stream starting the search at position. It returns the position at this match starting at the beginning of the stream. If it does not find the target string then return -1. If position=-1 then start searching from the current location and just return the offset from the last search, useful for searching through the entire file. If you are doing this you should pass in tmpstr by reference in every call which is used as a temporary location to store information being read so the next call will start where the last one left off. If you pass caseinsensitive=1 then the search will be case insensitive rather than the default case sensitive search.

Copy to String may help but is limited by MAXSTRING size.
There you may use [  (=contains OPERATOR) or $FIND() function

Don't mix up SQL predicate %CONTAINS  with [  (string contains operator)


That is a very good question related to an extremely broad topic I usually term as "Advanced Production Management". Should write a book on that. Maybe some day.

Anyway, production management tools are good, but they are generic - they work for any production. The problems start to arise when you need to perform some application specific management. In that case I recommend writing an SQL query.

While interoperability contains a lot of utility tables, you can start with Ens.MessageHeader and its' properties. It's a table containing message headers for all messages - specifically where they come from and where they go to. Join this table to your actual message using MessageBodyClassName and MessageBodyId values.

After that you'll need to filter by all the common criteria - business host, timestamp (id!), some structured message body or header properties. The goal here is to minimize the dataset we'll perform a full text search on.

Finally, after you got your dataset, expose FindAt as an SQL procedure and add it to the query conditions.