DI API as we know is an important component in SAP Business One which allows other third party applications to interact with the ERP system. It allows to push and receive data to/from SAP Business One. Though new integration components are available like DI Server which allows the data to be synced in batch provides greater performance, still DI API is widely used in many solutions offered by SAP Partner. One of the biggest reason of using this is no additional license requirement, while DI Server License comes up at an additional cost of few hundred euros.
But in current release of SAP Business One 9.0, it is reported by several SAP Partners and consultants that DI API faces a fatal bug of Memory Leak while exchanging the data. Let’s have a detail look of incidents reported in several forums regarding the DI API Memory Leak in SAP Business One 9.0.
Problem
With each API calls DI API exceeding the usage of RAM even when running the same process, eventually reaching the threshold point of getting free RAM and crashing the subsequent process which accessing the DI API. So in this way the worker process finally hang the application and crashes it.
Example 1:
Reported in SCN, below Sales Order creation process before running has an available free RAM of 6GB. This is a dummy Sales Order Creation Process in SAP Business One through DI API:
-------------------------
Declaring SAP objects...
-------------------------
SAPbobsCOM.Company CurrentCompany = null;
SAPbobsCOM.Documents Order = null;
SAPbobsCOM.BusinessPartners bp = null;
SAPbobsCOM.Items Items = null;
SAPbobsCOM. AdditionalExpenses Expenses = null;
//-------------------------
Opening a company object
-------------------------
SAPbobsCOM.Company CurrentCompany = GetSAPCompany (SessionID);
if (CurrentCompany != null)
{
Order = (SAPbobsCOM.Documents) CurrentCompany.GetBusinessObject (BoObjectTypes.oOrders);
bp = (SAPbobsCOM.BusinessPartners) CurrentCompany.GetBusinessObject (BoObjectTypes.oBusinessPartners);
Items = (SAPbobsCOM.Items) CurrentCompany.GetBusinessObject (BoObjectTypes.oItems);
Expenses = (SAPbobsCOM. AdditionalExpenses) CurrentCompany.GetBusinessObject (BoObjectTypes. oAdditionalExpenses) ;
}
//--------------------------------------------------
Here would be the code to create a Sales Order...
//--------------------------------------------------
//------------------------
// Releasing everything...
//------------------------
if (Order != null)
{
System.Runtime.InteropServices. Marshal.ReleaseComObject (Order);
Order = null;
}
if (bp != null)
{
System.Runtime.InteropServices. Marshal.ReleaseComObject (bp);
bp = null;
}
if (Items != null)
{
System.Runtime.InteropServices. Marshal.ReleaseComObject (Items);
Items = null;
}
if (Expenses != null)
{
System.Runtime.InteropServices. Marshal.ReleaseComObject(Expenses);
Expenses = null;
}
if (CurrentCompany != null)
{
if(CurrentCompany.Connected)
CurrentCompany.Disconnect();
System.Runtime.InteropServices. Marshal.ReleaseComObject (CurrentCompany);
CurrentCompany = null;
}
Initially memory taken was 40 MB, releasing 36 MB after each time execution and 4 MB of memory usage is growing with each Sales Order creation. Eventually in some system integration such as eCommerce where there is a need to push thousands of Sales Order per hour, this process will shorten the Free RAM in no time and hangs or crashes the application like below
Faulting
application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7afa2
Faulting module
name: B1_DIInternalFields90Ace.dll, version: 9.0.56.0, time stamp: 0x51799cf5
Exception code:
0xc0000005
Fault offset:
0x0000000000017917
Faulting process
id: 0x1a74
Faulting
application start time: 0x01ceb48157da7b5d
Faulting
application path: c:\windows\system32\inetsrv \w3wp.exe
Faulting module
path: C:\Program Files\SAP\SAP Business One DI API\DI API
90\B1_DIInternalFields90Ace.dll
Report Id:
744a7aa3-207a-11e3-ad28-00155d400702
Solution
It is mostly advised by other consultants not to use DI API until there is some updated patch level released with this fix, still below solutions are mentioned. You can take a look and try if this helps:
Garbage Collector
Force the system garbage collector
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Alternative Method
.Net franmework won’t let you unload any loaded assembly and DI-proxy is only an assembly. The solution is using alternative method like:
- Going at a minimum to DI-Server – B1WS which consumes less memory, but for which you can force the unload of the service and by doing so to force it to release all its memory,
- Going ideally to B1if, which with its own DI-proxy mechanism will be able to restart periodically,
If can’t change from API, move all the business logic in a separate process (exe, not web-service neither DLL) which will be called by your web page and removed from memory when its job is ended.
You may also like:
How to Manage Discounts from Shopify to SAP Business One
Data Transfer in SAP Business One version for HANA
SAP Business One Sales App for Android and iOS: In-depth Feature List