There are times when you will want to pass your batch job some parameters to control what data is processed. In this article, learn how to add D365 SysOperation Framework parameters. Adding parameters to the user interface gives users more control and makes the batch job more useful. Instead of always needing to process all of the data, parameters allow users to process only what is needed. While still taking advantage of running the process in the background.
Why Use Parameters?
Developers can create a SysOperation Framework batch job without sending in any parameters. The code in the Service class can still read values from a parameter table to control what data is processed. However, the values in the parameter table will affect all instances of the batch job.
By adding D365 SysOperation Framework parameters, users can change what data is processed each time they set up and run the job. Multiple instances of the batch job can be set up at the same time to process different pieces of data. Additionally, each instance of the batch job could then have a different recurrence if desired. This gives the user a lot more flexibility and control.
Review
In a previous article, I explained how to develop a batch job using SysOperation Framework in D365. Before adding a user interface to your batch job you need to first follow the steps in that article. As a reminder, you need to create three classes in Visual Studio and add them to a project.
- First, create a Contract class. This was empty in the last article. In this article, we will add code to this class. This will contain the parameters that will be shown in the D365 SysOperation Framework parameters.
- Secondly, you need to create a Service class. One that extends the class SysOperationServiceBase. This class contains the code that performs some kind of process. In this article, we will allow a developer to use the parameters from the Contract class to affect how the processing code works.
- Thirdly, you need to create a Controller class. This class really just configures how the batch job works. It tells the system what method on the Service class to run.
Add Parameters To The Contract Class
Now, to add D365 SysOperation Framework parameters, developers simply need to add parm methods to the Contract class. By adding parm methods, and adding the right ‘attribute‘ to each method, the system will automatically display a parameter on the Dialog form matching this type.
The easiest way to explain is with an example. As an example, a common type of batch job is one that is written to delete data out of a table that is X days old. In this case, we want X to be an integer number that is specified by the user when the batch job is created.
Adding The Attribute
In this example, my class is name is rsmTutSysOperationsContract. Your contract class may have a different name. Add the code [DataContractAttribute] just above the class declaration. This tells the system that this class is a ‘Contract‘ class.
[DataContractAttribute]
class rsmTutSysOperationsContract
{
}
To explain, the information between two square brackets like this it is an ‘attribute‘. It allows developers to specify metadata about a class or method that can be used by the compiler. See Microsoft’s documentation here. Your code should now look like this:
Add Variable And Parm Method
Now, the Contract class needs a variable to store the parameter value. Additionally, there needs to be a method to set and get the value. The class should now look like this
[DataContractAttribute]
class rsmTutSysOperationsContract
{
private int retentionDays;
public int parmRetentionDays(int _retentionDays = retentionDays)
{
retentionDays = _retentionDays;
return retentionDays;
}
}
Add DataMember Attribute
Lastly, add another attribute above the ‘parm‘ method. This attribute tells the system the label, help text, and order to display this field on the D365 SysOperation Framework parameters form. Without this attribute the parameters will not be shown on the batch job dialog form. The code will now look like this:
[DataContractAttribute]
class rsmTutSysOperationsContract
{
private int retentionDays;
[DataMember,
SysOperationLabel(literalStr("Retention days")),
SysOperationHelpText(literalStr("Data older than the retention days will be cleaned up.")),
SysOperationDisplayOrder('1')]
public int parmRetentionDays(int _retentionDays = retentionDays)
{
retentionDays = _retentionDays;
return retentionDays;
}
}
To review, you added the class attribute, variable and parm method. Now, you can see the field is on the Dialog form. Compile and run the solution. Notice, you can see the “retention days” field.
Read The Parameter Value
Now that a user can specify a parameter value, add code to allow the Service class to read that value and use it.
In Visual Studio, open the Service class and the Controller class. In my example, name the service class rsmTutSysOperationsService. And the controller class rsmTutSysOperatoinsController. Your class name may be different.
In the ‘new’ method of the Controller class, locate which method from the Service class is specified to run. In my case, name the method ‘process‘.
protected void new()
{
super(classStr(rsmTutSysOperationsService), methodStr(rsmTutSysOperationsService, process), SysOperationExecutionMode::Synchronous);
}
Next, open that method in the Service class.
Add code inside the process method to call the parm method on the contract class variable and assign it to a variable.
class rsmTutSysOperationsService extends SysOperationServiceBase
{
public void process(rsmTutSysOperationsContract _contract)
{
//Do something
int retentionDays = _contract.parmRetentionDays();
Info(strFmt("Retention days: %1", retentionDays));
}
}
Finally, use the parameter value to control what data is processed. In this example, subtract from today’s date, the number of days specified by the “retentionDays“. Then, delete from a table all records with a created date time that is older than that date. The final code will look like this:
class rsmTutSysOperationsService extends SysOperationServiceBase
{
public void process(rsmTutSysOperationsContract _contract)
{
int retentionDays = _contract.parmRetentionDays();
utcdatetime retentionDateTime;
retentionDateTime = DateTimeUtil::addDays(DateTimeUtil::getSystemDateTime(), -retentionDays);
Info(strFmt("Retention days: %1", retentionDays));
Info(strFmt("Retention date/time: %1", retentionDateTime));
tutorialLog tutorialLog;
delete_from tutorialLog
where tutorialLog.createdDateTime <= retentionDateTime;
}
}
Parameters, Defaults, Validation, Mandatory and UIBuilder
Please see these other articles for more advanced SysOperation Framework functionality.
Next, override the drop-downs to show only validate options. D365 SysOperation Framework Override Lookups
After adding parameters to a SysOperation Framework batch job, you may want to set those parameters to start with an initial value. Learn how to set a D365 SysOperation Framework default value.
Additionally, add validation to the parameters. D365 SysOperation Framework Validation
Lastly, learn to add D365 SysOperation Framework mandatory parameters that show a red outline and a star to indicate the field must be populated.
For another great reference on how to create classes using the SysOperation Framework in D365, see this article.
Conclusion
It is actually quite simple to add D365 SysOperation Framework parameters. To add parameters to batch job, we simply need to add ‘parm‘ methods to the Contract class, and add the write ‘attributes‘. The system will automatically use the extended data type used in those methods to display the right type of parameters. Developers then use the values entered to control what data the batch job processes. Allowing a single batch job to be used to process the right data at the right time.
Finally, there are times when the parameter fields created by the system are not quite right. Either the lookup needs to work differently. Or, validation should be added. Or, the parameter should have a default value already set. Learn how to do this in the next tutorial.
how I set caption to dialog class sys operation?
tank you!
Your articles are very very good, i have learned a lot from your articles, i have started learning x++ inspired by your articles, sometime i confused what sequence i will read your articles, if possible please guide me.
Yes. Typically I would say you can start at the oldest article and move forward in order to you can skip the first five or so as those are more advanced. But let me see if I can create a page that better specifies an order by topic. That is a good idea.