1

I`m trying to execute Continuation from LWC action. The thing is that I use it for SOAP API.

It is a long-time running request, but I have to show a loading spinner until the response will be returned to populate it. Continuation method works just fine from VF page, but not from LWC.

JFYI, this code runs in the Community. Means, it is executed under Portal user. But I believe, it does not have any impact here.

JS code:

import getTotalNetPriceFromSAP from '@salesforce/apexContinuation/SFMS_SubscriptionsOverviewController.getTotalNetPriceFromSAP';
    //other code
    proceedToBillingData() {
        //other code          
        this.isLoading = true;
        getCart({ paymentData: JSON.stringify(this.pricingOption) })
            .then(cartResult => {
                getCCLogs(cartResult.logs);
                this.isCartAvailable = true;
                this.cartEncryptedId = cartResult.cartEncId;
                return getTotalNetPriceFromSAP({ cartEncId: cartResult.cartEncId });
            })
            .then(sapResult => {
                //TODO: obtain result from SAP
                this.totalPrice = this.userFormatter.format(sapResult['ccrz__Price__c']);
                this.vat = ((sapResult['ccrz__Price__c'] - this.pricingOption.exclVATPrice) / sapResult['ccrz__Price__c']) * 100;
                this.isLoading = false;
            })
            .catch(error => {
                console.error('error --- ', error);
                this.isLoading = false;
                this.isError   = true;
                this.errors    = error.body.message;
            });
    }

Controller method:

    @AuraEnabled(continuation=true)
    public static Map<String, Object> getTotalNetPriceFromSAP(final String cartEncId) {
        List<ccrz__E_Cart__c> openCart = [SELECT ccrz__Account__r.SAP_Customer_Number__c,(SELECT ccrz__Quantity__c FROM ccrz__E_CartItems__r)
                                          FROM ccrz__E_Cart__c WHERE ccrz__EncryptedId__c = :cartEncId];
        if (openCart[0].ccrz__E_CartItems__r.isEmpty()) {
            throw CustomException.setErrorMessage(String.format(CustomException.NO_CART_ITEMS_BY_USER_ID, new String[] { currentUser.Id }));
        }

        try {
            Continuation continuation = (Continuation) new CC_EpayVatSimulate().callOrderSimulateFuture(openCart[0]);
            System.debug('getTotalNetPriceFromSAP --- ' + continuation);
            return null;
        } catch (Exception e) {
            CustomException.setErrorMessage(e.getMessage());
        }
    }

Service method:

//variables & other unnecessary code
public Continuation callOrderSimulateFuture(ccrz__E_Cart__c openCart) {
    this.userCart = openCart;
    Continuation cont = new Continuation(60);
    AsyncCC_SAP_eCommerce.AsynceCommercePortTypeEndpoint endpoint = new AsyncCC_SAP_eCommerce.AsynceCommercePortTypeEndpoint();
    cont.continuationMethod = 'orderSimulateFutureComplete';

    WS_Configuration__c configuration = WS_Configuration__c.getInstance('CC_Callout');
    String username = configuration.Username__c;
    String password = configuration.Password__c;
    endPoint.endpoint_x = 'https://ws-dev.sb.wabco-auto.com/weaiServices/eCommerce/Order';

    endPoint.inputHttpHeaders_x = new Map<String, String>();
    endPoint.inputHttpHeaders_x.put('Username', username);
    endPoint.inputHttpHeaders_x.put('Password', password);

    this.responseFuture = endPoint.beginStdSalesOrderSimulate(cont, buildHeader(), buildOrderHeaderIn(userCart), buildOrderItems(userCart.ccrz__E_CartItems__r), buildOrderPartners(userCart));
    System.debug('responseFuture --- ' + responseFuture);
    System.debug('cont.getRequs --- ' + cont.getRequests());
    return cont;
}

public Object orderSimulateFutureComplete() {
    System.debug('callback');
    this.res = this.responseFuture.getValue();
    if (this.res != null && this.userCart != null) {
        System.debug('response --- ' + this.res);
    }
    return null;
}

From internal VF page, it is executed and I can verify the logs in the callback method.

But, when @AuraEnabled method is executed I never receive callback method logs, it is not being executed. I`m sure that Continuation is working fine with Lightning + Http requests, as per latest SUM 19 release.


What could be the issue here?

Is there any workaround that I can use instead of Continuation in this scenario?

Perhaps, I can use Platform events or Stream API as an alternative in Community?

0

Not a duplicate (Unable to delete the comment before about duplicate - sorry). I just observed you are running into different issue here.

It works in visualforce because vf page needs instance of continuation BUT not working in lightning because LWC needs static (not instance).

But when you modify the instance method to static for continuation, you need to preserve the state of continuation or else continuation will not know to which callback apex method the response has to be returned. So in your case you need below changes:

  1. Make callOrderSimulateFuture static and invoke it through class variable instead of instance
  2. Store the state of continuation using state in continuation.
  3. Pass the state object to callback function - orderSimulateFutureComplete.
  4. orderSimulateFutureComplete should be annotated @AuraEnabled.
  5. You cant use username and pwd directly in apex. Use named credential.

    cont.state = cont.addHttpRequest(req);

Remember that state is an object. So you can pass a map as well to state if you want to store additional information which can be retrieved later in callback function. See below simple example for your reference.

Understanding continuation: Apex method sends request to external system and forgets about it (it does not wait for response). In below method, startRequest returns continuation. Observe con.continuationMethod='processResponse'. This means whenever the response is returned, method processResponse is invoked.

@AuraEnabled(continuation=true cacheable=true)
public static Object startRequest() {
    Continuation con = new Continuation(40);
    con.continuationMethod='processResponse';
    HttpRequest req = new HttpRequest();
    req.setMethod('GET');
    req.setEndpoint(LONG_RUNNING_SERVICE_URL);
    con.state = con.addHttpRequest(req);
    return con;  
}

processResponse method:

@AuraEnabled(cacheable=true)
public static Object processResponse(Object state) {
    HttpResponse response = Continuation.getResponse((String)state);
    return response.getBody();
}

Note: timeout mentioned while initialising continuation is stored by continuation server, not apex method and hence I said it forgets the request.

  • thank you. I`ll try this and let you know. – m_konyk Jul 18 at 8:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.