Usage
We can use pack-unpack methods in RunBaseBatch classes and all its descendants to save and/or store the state of an object, and then later re-instantiate the same object.
We need it, for example, to use the user's input for any batch job: some parameters can be used when a batch job is executed on the server.
Documentation
Microsoft doc article is here.
Quote: "A reinstantiated object is not the same object as the one that was saved. It is just an object of the same class whose members contain the same information."
You need to teleport your objects without a fly or other bugs.
Case examples
Basics
Basic example of such a class is Tutorial_RunbaseBatch.
TransDate transDate;
CustAccount custAccount;
#define.CurrentVersion(1)
#localmacro.CurrentList
transDate,
custAccount
#endmacro
public container pack()
{
return [#CurrentVersion,#CurrentList];
}
public boolean unpack(container packedClass)
{
Version version = RunBase::getVersion(packedClass);
;
switch (version)
{
case #CurrentVersion:
[version,#CurrentList] = packedClass;
break;
default:
return false;
}
return true;
}
Containers
Basically you can add a container directly to pack() or convert a container to a string and save the latter. Opposite conversion required for restoring.
container siteIds;
str siteIdsStr;
#define.CurrentVersion(1)
#define.Version1(1)
#localmacro.CurrentList
siteIdsStr
#endmacro
public boolean getFromDialog()
{
...
// convert it to string for pack/unpack
siteIdsStr = con2Str(siteIds);
return super();
}
public void dialogPostRun(DialogRunbase _dialog)
{
FormRun formRun;
super(dialog);
formRun = _dialog.dialogForm().formRun();
if (formRun)
{
// if we restored from last values
if(siteIdsStr)
{
//then we convert the string to container
siteIds = str2con(siteIdsStr);
}
}
}
See the following article for the complete usage https://alexvoy.blogspot.com/2014/11/dialog-field-with-multiple-choice.html
Tables
Save an unique key value, say, RecId to find a target buffer after unpack()
Collection types
Maps, lists, and sets are equipped with method pack, which you can use directly for packing.
// collections
List list;
Map map;
Set set;
// saved states
container packedCont;
packedCont = list.pack();
list = List::create(packedCont);
packedCont = map.pack();
map = Map::create(packedCont);
packedCont = set.pack();
set = Set::create(packedCont);
Queries
How to pack/unpack a query among other parameters, you can find in IntrastatTransfer class.
QueryRun queryRunIntrastatTransfer;
container pack()
{
return [#CurrentVersion,#CurrentList,queryRunIntrastatTransfer.pack()];
}
boolean unpack(container packedClass)
{
Integer version = conPeek(packedClass,1);
container packedQuery;
switch (version)
{
case #CurrentVersion:
[version,#CurrentList,packedQuery] = packedClass;
if (packedQuery)
{
queryRunIntrastatTransfer = new QueryRun(packedQuery);
}
break;
default:
return false;
}
return true;
}
Subclasses
How to pack/unpack additional parameters in a subclass.
class myVendCreateGlobalPaymJournal extends CustVendCreatePaymJournal_Vend
NoYes myParm;
#define.CurrentVersion(1)
#localmacro.CurrentList
myParm
#endmacro
/// <summary>
/// Pack the new parameters
/// </summary>
/// <returns>standard list of parameters with the new ones</returns>
public container pack()
{
return [#CurrentVersion,#CurrentList] + [super()];
}
/// <summary>
/// Unpacks saved parameters
/// </summary>
/// <param name = "_packedClass">Parameters container</param>
/// <returns>True if OK</returns>
public boolean unpack(container _packedClass)
{
Integer version = conPeek(_packedClass,1);
container packedBase;
switch (version)
{
case #CurrentVersion:
[version, #CurrentList, packedBase] = _packedClass;
return super(packedBase);
}
return super(_packedClass);
}
Extensions
How to pack/unpack additional parameters in an augmented class (extension).
/// <summary>
/// We are going to use a new additional parameter
/// </summary>
[ExtensionOf(classStr(<ClassName>))]
public final class My<ClassName>_Extension
{
private boolean myNewParm;
#define.CurrentVersion(1)
#localmacro.CurrentList
myNewParm
#endmacro
/// <summary>
/// myNewParm access
/// </summary>
/// <param name = "_parm">boolean</param>
/// <returns>boolean</returns>
public boolean parmMyNewParm(boolean _parm = myNewParm)
{
myNewParm= _parm;
return myNewParm;
}
/// <summary>
/// Extends Pack
/// </summary>
/// <returns>container</returns>
public container pack()
{
container packedClass = next pack();
return SysPackExtensions::appendExtension(packedClass, classStr(My<ClassName>_Extension), this.myPack());
}
/// <summary>
/// Extends Unpack
/// </summary>
/// <param name = "packedClass">container</param>
/// <returns>boolean</returns>
private boolean myUnpack(container packedClass)
{
Integer version = RunBase::getVersion(packedClass);
switch (version)
{
case #CurrentVersion:
[version, #currentList] = packedClass;
break;
default:
return false;
}
return true;
}
/// <summary>
/// Packs my locals
/// </summary>
/// <returns>container</returns>
private container myPack()
{
return [#CurrentVersion, #CurrentList];
}
/// <summary>
/// Extends unpack
/// </summary>
/// <param name = "_packedClass">container</param>
/// <returns>boolean</returns>
public boolean unpack(container _packedClass)
{
boolean result = next unpack(_packedClass);
if (result)
{
container myState = SysPackExtensions::findExtension(_packedClass, classStr(My<ClassName>_Extension));
//Also unpack the extension
if (!this.myUnpack(myState))
{
result = false;
}
}
return result;
}
}
Originally from https://alexvoy.blogspot.com/2022/02/additional-parameters-in-runbasebatch.html
Please, ping me if I missed anything.