However, it is often difficult to test just the REST API without inadvertently involving the authentication scheme, the web application configuration, or even network connectivity. Those are a lot of hoops to jump through just to test the code within your dispatch class.

Another way you can do this is by splitting web (rest) api from the business logic. I think ideally your REST handler method does only the following two things:

  • Parses incoming request
  • Verifies incoming request (debatable, might also be offloaded to the underlying API)
  • Calls underlying API

This way you can focus on unit testing your underlying api layer and keep the REST parts of your implementation as simple as possible.

You can use BPs to do that automatically.

BS (pool size 1) sends file to BP (1 request, pool size 1).

BP parses the file and sends X async requests to BO (pool size >1) for processing, total request count is stored in BP.

BP OnError/OnResponse methods are called once rows are being processed, maintain count here.

Once OnError/OnResponse count matches original count send a final batch request.  

Eduard Lebedyuk · Dec 18, 2025 go to post

a-z, A-Z only. Everything else is considered non-alphabetic, although I guess non-latin characters would be a more correct term. 

Eduard Lebedyuk · Dec 17, 2025 go to post

PS: why is the correct result in the testNumbers method 321 and not 213?

Thanks for noticing! Fixed.

Eduard Lebedyuk · Dec 16, 2025 go to post

Check out %GetSetting implementation in Ens.Config.DefaultSettings:

// Look in table starting with most specific match
If $D(^Ens.Config.DefaultSettingsD(pProductionName,pItemName,pHostClassName,pSettingName),data)
|| $D(^Ens.Config.DefaultSettingsD("*",            pItemName,pHostClassName,pSettingName),data)
|| $D(^Ens.Config.DefaultSettingsD(pProductionName,"*",      pHostClassName,pSettingName),data)
|| $D(^Ens.Config.DefaultSettingsD("*",            "*",      pHostClassName,pSettingName),data)
|| $D(^Ens.Config.DefaultSettingsD(pProductionName,pItemName,"*",           pSettingName),data)
|| $D(^Ens.Config.DefaultSettingsD("*",            pItemName,"*",           pSettingName),data)
|| $D(^Ens.Config.DefaultSettingsD(pProductionName,"*",      "*",           pSettingName),data)
|| $D(^Ens.Config.DefaultSettingsD("*",            "*",      "*",           pSettingName),data)

In your case your first setting would be resolved on line three:

$D(^Ens.Config.DefaultSettingsD(pProductionName,"*",      pHostClassName,pSettingName),data)

And your second setting would be resolved on line five:

|| $D(^Ens.Config.DefaultSettingsD(pProductionName,pItemName,"*",           pSettingName),data)

But since line three resolves to a valid setting, line five would never be hit.

To work around that provide both item name and class name explicitly - it would be resolved on the first line for your outlier (since both item and class match) and the rest of the items would get their setting resolved on line three.

Eduard Lebedyuk · Dec 15, 2025 go to post

1️⃣ When you joined the Developer Community and how you first discovered it.

November 2015 not long after DC started. @Evgeny Shvarov told me about it.


2️⃣ A meaningful moment or story from your personal journey here.

I've been writing my Continuous Delivery series for seven years now! That's one of my longest writing projects.
3️⃣ An article, question, or discussion you consider especially valuable — one you believe others should take the time to revisit.

Lots of great stuff to find here on DC! 

This post by @Guillaume Rongier is probably the one I revisited the most over the years.

This post by @Dmitry Maslennikov too.

This comment by @Timothy Leavitt (wrote an article based on that). Also this one - should be in product imo.

Eduard Lebedyuk · Nov 3, 2025 go to post

Great article!

Highly recommend adding a common package root. I.e. not Operation.Alert but Company.Operation.Alert. 

This way querying %Dictionary/InformationSchema becomes much easier since you always know what to filter on.

Eduard Lebedyuk · Oct 29, 2025 go to post

It will work with any HTTP request verb.

Most REST dev clients have support for HTML preview, just remember to set Content Type. I don't think swagger-ui can do that as it's not an app, rather a page running in a browser.

Eduard Lebedyuk · Oct 28, 2025 go to post

Set response type to HTML:

ClassMethod Test()
{
	set %response.ContentType = "application/html"
	do ##class(%CSP.Utils).DisplayAllObjects()
	quit $$$OK
}

In Postman click Preview button:

Eduard Lebedyuk · Oct 9, 2025 go to post

URL must have a scheme (either TCP or SSL). I don't think your (redacted) URL has a scheme.

If that does not help, try to init the object directly to see what's going on:

Set client=##class(%Net.MQTT.Client).%New(Url, ClientID, QOS, KeepAlive, LWTTopic, LWTMessage)

When creating a new client instance at minimum the url to connect and a client id is required to be specified.
The client id must be a utf-8 string which is used to uniquely identify the client.
This takes the form "tcp://localhost:1883" where the scheme is tcp and the host and port are seperated by a colon. If
you are using ssl you should specify the url in the form "ssl://localhost:8883" where scheme is ssl.
The second parameter is a string which the broker can use to identify the client. The client will generate an id if not specified.
The third parameter defines the required quality of service, 'Fire and Forget' (0) or 'Wait for Delivery' (1).

The fourth parameter is the keepalive interval, defaults to 60. 
The client will send keepalive messages to the broker according to the specified interval. The final pair of parameters specifies the last will and testament topic and associated message.
The LWT (last will and testament) feature tells the broker to deliver the Last Will message to the Last Will topic, should the client unexpectedly disconnect.

Note, %New() can error so it's important to check that the return value with $IsObject() and examine the %objlasterror status value should the %New() not return a valid object.

Eduard Lebedyuk · Oct 9, 2025 go to post

Doubt it - $system.OBJ.MakeClassDeployed deletes the source code so there's nothing to recompile. Contact the WRC maybe they can suggest something, but without the source code there's not much anyone can do.

Maybe you still have this class in your source control?

Eduard Lebedyuk · Oct 8, 2025 go to post

Health Connect Cloud clients use System Default Settings. SDS serve two purposes:

  1. Providing environment-specific settings (i.e. Port).
  2. Providing settings common to several BHs using wildcards (i.e. Connect Timeout).

They can be easily integrated into CICD processes. Starting from 2024.1 SDS can also control enabled/disabled state of individual BHs.

Eduard Lebedyuk · Oct 6, 2025 go to post

If you need to look at request/session/response - add this to any part of your REST handler:

set %response.ContentType = "html"
do ##class(%CSP.Utils).DisplayAllObjects()
return $$$OK

Here are some other tools available: part 1, part 2.

Eduard Lebedyuk · Sep 26, 2025 go to post

%Close is called automatically. Consider the following example:

Class Utils.GC Extends %RegisteredObject
{

Property Type As %String;

/// do ##class(Utils.GC).Test()
ClassMethod Test()
{
	set obj = ..%New("explicit")
	kill obj
	
	do ..Implicit()
}

ClassMethod Implicit()
{
	set obj = ..%New("implicit")
	// obj will be removed from memory after we exit current method/frame.
}

Method %OnClose() As %Status [ Private, ServerOnly = 1 ]
{
	Write "%Close is running: ", ..Type,!
	Quit $$$OK
}

Method %OnNew(type) As %Status [ Private, ServerOnly = 1 ]
{
	Set ..Type = type
	Quit $$$OK
}

}

Here's the output from the Test method:

HCC>do ##class(Utils.GC).Test()
%Close is running: explicit
%Close is running: implicit
Eduard Lebedyuk · Sep 23, 2025 go to post

In router Force Sync Send should be 1.

The default RCA behavior is ':?R=RF,:?E=S,:~=S,:?A=C,:*=S,:I?=W,:T?=C'
This means for NACKs received with error code AR or CR retry, while codes AE or CE suspend the current outbound message and move on to the next. I suppose you want ':?R=RF,:?E=F,:~=S,:?A=C,:*=S,:I?=W,:T?=C'

Eduard Lebedyuk · Sep 17, 2025 go to post

To avoid getting unrelated http errors on xDBC testing, test in terminal:

set sc = ##class(%SYSTEM.SQLGateway).TestConnection(name, 0, 0, .err)
set sc = ##class(%SQL.Manager.API).TestDecodeDSN(name, usr, password, 0, .err)
Eduard Lebedyuk · Sep 17, 2025 go to post

Are you on Linux? Use JDBC. ODBC Snowflake driver is incompatible with IRIS because it uses a backtrace() syscal which causes signal 11 in IRIS process if the process is running in a background.

Snowflake ODBC driver uses backtrace to determine Driver Manager on Linux, so currently it does not work on Linux at all with IRIS.

Eduard Lebedyuk · Jul 8, 2025 go to post

Great!

IRIS 2019.4.0, Business Host class compilation triggers all Config Items of that class to be automatically restarted.  

Which compile flag is that?