Developer forum

Forum » Development » Live integration error

Live integration error

Tomas Gomez
Reply
Hi:
 
We have a DW solution that gets live prices from an ERP via a Web Service. This is a requirement of a customer.
 
 
After that, we modified the code to obtain the live prices from the ERP.
 
It usually works well, but sometimes the prices are not fetched from the ERP system. The error happens at random times, there is not a clear pattern of failure, 
 
To fix this issue, sometimes we have to restart the server, and some othe times we have to clear the Chrome cache. Inside the live integration configuration we have the cache level configured as 'Session'

Does anybody know what could be the reason and how to solve it?
 
Regards,
Tomas

Replies

 
Unnsteinn Garðarsson
Unnsteinn Garðarsson
Reply

Some information about the error is necessary for anyone to help with this.

 
Arnór Halldórsson
Arnór Halldórsson
Reply

Hi Tomas,

Without more details it's really hard to narrow down your problem, if you're still having this issue I would start by:

  1. Checking the GetEcomData request and response logs (See Files/System/Log/LiveIntegration/ERPLiveIntegrationAddIn.log).
    1. If the request is never logged then the problem is somewhere in your version of the LiveIntegration code, you could add more logs to try and detect it, but if it's an exception / system error the EventViewer should catch it.
    2. If the response is failing on the ERP side you should get an error logged after the request line.
    3. If both request and response lines are logged the problem is likely in the ProcessResponse or at least down that pipe until you hit the NotificationSubscribers / TemplateExtenders.
  2. Checking the Dynamicweb EventViewer (Settings -> System -> EventViewer) or query the GeneralLog table in your database. If you find an exception / error matching your problem you can then check the log file (path found in LogFilePath column in GeneralLog) for that event to see the stack trace. How useful the stacktrace is can depend on the way you build your release build.

Generally there shouldn't be that many points of contact for problems to occur in the GetEcomData request pipeline, unlike CalculateOrder which triggers from all sorts of redirects, callbacks, orders from the Queen, and Odin's ravens.

Also, using the standard ERPResponseCache Session cache means that the data is only stored until the frontend completes rendering from the current request. So that should not be preventing the prices from being fetched.

Hope this helps.

Best regards,
Arnór

 
Tomas Gomez
Reply

Hi,

Thanks Arnór for your suggestions.

1) The login to the ERP is ok, and the ERP sends responses with normal behaviour. The error is not triggered by the login. It is triggered by a function in a notification that asks the price to the ERP (see below the error image and the function code)

2) I didn't see any error in the logs of the EventViewer

About the type of cache, we use session cache. Formerly we tried page cache but we got some issues with it. Should it be better to use page cache?

Regards,
Tomas

 
image.png
 
namespace Dynamicweb.Ecommerce.LiveIntegration.Products
{
    /// <summary>
    /// PriceProvider to find prices and other information for products.
    /// </summary>
    /// <seealso cref="PriceProvider" />
    public class ProductPriceProvider : PriceProvider
    {
        /// <summary>
        /// Finds the price..
        /// </summary>
        /// <param name="product">The product.</param>
        /// <param name="quantity">The quantity.</param>
        /// <param name="variantId">The variant id.</param>
        /// <param name="currency">The currency.</param>
        /// <param name="unitId">The unit id.</param>
        /// <param name="user">The user.</param>
        /// <returns>The <see cref="T:Dynamicweb.Ecommerce.Prices.PriceRaw" />.</returns>
        public override PriceRaw FindPrice(Product product, double quantity, string variantId, International.Currency currency, string unitId, User user)
        {
            if (!Global.IsIntegrationActive
              || !Settings.Instance.EnableLivePrices
              || (user == null && !Settings.Instance.LiveProductInfoForAnonymousUsers)
              || (user != null && user.IsLivePricesDisabled)
              || !Connector.IsWebServiceConnectionAvailable()
              || product == null
              || string.IsNullOrEmpty(product.Id)
              || string.IsNullOrEmpty(product.Number))
            {
                return null;
            }            try
            {
                ProductService productService = new ProductService();
                string productIdentifier = ProductManager.ProductProvider.GetProductIdentifier(product);
                // If Product is not in the cache, then get it from Erp
                if (!ErpResponseCache.IsProductInCache(ProductManager.ProductCacheLevel, productIdentifier))
                {
                    Dictionary<Product, double> products = new Dictionary<Product, double>();
                    products.Add(ProductManager.ProductProvider.GetProductFromVariantComboId(product), quantity);
                    if (ProductManager.FetchProductInfos(products, User.GetCurrentExtranetUser()))
                    {
                        // Check if requested product was not received from response
                        if (!ErpResponseCache.IsProductInCache(ProductManager.ProductCacheLevel, product.Id))
                        {                            Logger.Instance.Log(ErrorLevel.Error, $"Error receiving product info for product: {ProductManager.ProductProvider.GetProductIdentifier(product)}.");
                            return null;
                        }
                    }
                    else
                    {
                        // No price from ERP so read DW default price
                        var priceProvider = new DefaultPriceProvider();                        return priceProvider.FindPrice(product, quantity, variantId, currency, unitId, user);
                    }
                }
 
Arnór Halldórsson
Arnór Halldórsson
Reply

No problem mate :)

I would continue using the Session Cache, I've tried the Page cache and never found a suitable case for it.

But the problem seems to be variant related, it seems that after calling GetProductFromVariantComboId and creating a new ProductIdentifier (used to store ProductInformation in the session cache) based on the results from GetProductFromVariantComboId the code stops and can't find the row in the cache.

When the ERP response comes in, there's an XML node named ProductIdentifier:

The value from this node is used as the key for the ProductInformation dictionary written into the cache at the end of ProductManager.ProcessResponse():

However, inside ProductPriceProvider.FindPrice, after calling

Product changedProduct = ProductManager.ProductProvider.GetProductFromVariantComboId(product);

and then passing that product into 

productIdentifier = ProductManager.ProductProvider.GetProductIdentifier(changedProduct)

you're being left with bupkiss :) Something is causing a mismatch between the ProductIdentifier value in your response XML and the value returned from ProductManager.ProductProvider.GetProductIdentifier(changedProduct)... Check the XML returned from the ERP, and add more logging into GetProductFromVariantComboId to see the productId, variant id and languageid etc that the code is working with at that time, and what the function is returning.

Hope this helps :)

Best regards,
Arnór

 
Tomas Gomez
Reply
 
Hi Arnór,
 
I found something inside the ProductBeforeRender and ProductPriceProvider notifications. Both classes have the piece of code that I attach below.
 
If you take a look to the highlighted line, the second parameter is "product.id". This should be "productIdentifier" (ont of the function parameters).
As far as my tests, the error is avoided when performing this change.
 
Thanks for your help!
Tomas
 
 
if (!ErpResponseCache.IsProductInCache(ProductManager.ProductCacheLevel, productIdentifier))
                {
                    Logger.Instance.Log(ErrorLevel.Error, $"TEST IsProductInCache ok.");                    Dictionary<Product, double> products = new Dictionary<Product, double>();
                    products.Add(ProductManager.ProductProvider.GetProductFromVariantComboId(product), quantity);
                    if (ProductManager.FetchProductInfos(products, User.GetCurrentExtranetUser()))
                    {
                        Logger.Instance.Log(ErrorLevel.Error, $"TEST FetchProductInfos ok.");                        // Check if requested product was not received from response
                        if (!ErpResponseCache.IsProductInCache(ProductManager.ProductCacheLevel, product.Id))
                        {                            Logger.Instance.Log(ErrorLevel.Error, $"Error receiving product info for product: {ProductManager.ProductProvider.GetProductIdentifier(product)}.");
                            return null;
                        }
                    }
                    else
                    {
                        // No price from ERP so read DW default price
                        var priceProvider = new DefaultPriceProvider();                        return priceProvider.FindPrice(product, quantity, variantId, currency, unitId, user);
                    }
                }
 
 
Arnór Halldórsson
Arnór Halldórsson
Reply

Awesome :) 

No problem dude!

 

You must be logged in to post in the forum