You need to sign in to do that
Don't have an account?
pradeep kumar s 1
SOAP API integration with batch apex and scheduler
friends,
i have written schedule apex for calling webservice every hour,batch apex is invoked inside the schedule apex.from this service response will be got and records are inserted from that response.i am using soap api webservice.now i am writing test classes for this.but iam getting this error.
how can i fix it?
here is the error---
'System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out '
i have written schedule apex for calling webservice every hour,batch apex is invoked inside the schedule apex.from this service response will be got and records are inserted from that response.i am using soap api webservice.now i am writing test classes for this.but iam getting this error.
how can i fix it?
here is the error---
'System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out '
You just make sure, you are not doing any insert or update(DML operation) before web service test call. Otherwise you will get this error always.
e.g.
@isTest static void testBatchCallout() {
My_Custom_Object__c foo = new My_Custom_Object__c(Name='test');
insert foo;
// The above insert/update should notbe there before WS call.
MyClient client = new MyClient();
MyWSMock mywsMockImpl = new MyWSMock();
Test.setMock(HttpCalloutMock.class,mywsMockImpl);
Test.startTest();
client.bar(foo.Id);
Test.stopTest();
}
Workaround: You prepare all your test data inside testSetup() method in your test class.
e.g.
@testSetup
static void methodName() {
My_Custom_Object__c foo = new My_Custom_Object__c(Name='test');
insert foo;
}
@isTest static void testBatchCallout() {
// you query your created data in your test setup method here
// the above query will give only data created in your test setup method(not all the data available in your salesforce instance)
My_Custom_Object__c foo = [select Id,otherfield from My_Custom_Object__c ];
MyClient client = new MyClient();
MyWSMock mywsMockImpl = new MyWSMock();
Test.setMock(HttpCalloutMock.class,mywsMockImpl);
Test.startTest();
client.bar(foo.Id);
Test.stopTest();
}
Regards,
Pawan Kumar
i have checked and inserted some records in testsetup but still i am getting the same error and how can we pass id of that record,actually i have written batch apex and in execute method the webservice is called with a webservice method.
and the class which is generated by apex wsdl2 tool is not globally mentioned.i am calling that one locally and the method i.e webservice method needs some parameters those are given already inside the execute method only.so i can not pass parameters locally.
Thanks for explanation.
If you can share your batch code then i can try to help you further.
Regards,
Pawan Kumar
No Problem. I have seen some insert in your code. Inside for loop, you are doing web service callout if something contains in Existing_Shipment_Facts and if something does not found then you are inserting the record then calling webservice. So what i would suggest You should store the object in List then in last you should do bulk insert. Then you will not get any error.
for (String S: TrackingNumbers.keySet()) {
if (Existing_Shipment_Facts.containsKey(S)) {
if (Existing_Shipment_Facts.get(S).Delivery_Status__c != 'Delivered') {
PackageIdentifier.Value = Existing_Shipment_Facts.get(S).TrackingNumber__c;
fedexComWsTrackV14.TrackReply TrackReply = new fedexComWsTrackV14.TrackReply();
TrackReply = TrackServicePort.track(WebAuthenticationDetail, Details, TransactionDetail, Version, SelectionDetails, 10, ProcessingOptions);
if (TrackReply != null) Fedex_TrackReply.put(PackageIdentifier.Value, TrackReply);
if (TrackReply.CompletedTrackDetails != null) CompletedTrackDetails.put(PackageIdentifier.Value, TrackReply.CompletedTrackDetails);
Old_Shipment_Facts.put(PackageIdentifier.Value, Existing_Shipment_Facts.get(S));
}
} else {
//insert new Shipment_Facts__c(
// add list.(Shipment_Facts__c);
}
}
Regards,
Pawan Kumar
hi pawan this is my web service mok callout class.
this is the test class for that batch apex.so please let me know,what should i do now?
can you try below code from line#96 to 103. I have just changed the sequence as you are caling your batch first then you are setting Mock.
Test.setMock(WebServiceMock.class, new WebServiceMockCallOut_Test());
Test.startTest();
Database.executeBatch(new TrackingStatus_BatchApex(),10);
//FedexWebservice2 f1=new FedexWebservice2();
//f1.sendRequest();
Test.stopTest();
Regards,
Pawan Kumar
but it is working with this class--""//FedexWebservice2 f1=new FedexWebservice2();
//f1.sendRequest(); ""successfully.-it takes 100 % code coverage but in this code no insert or update operation is doing.
can i know what the reason is?
The class is working synchrously because when you call your class it does not have DML operation(Insert/Update/delete/upsert). You are calling your web service independently. But when you call your batch class this is failing because before calling your web service class there is a insert/update in your execute method/ in dependent class. To identify just run below line in your developer class as anonymous block and see the debug log for the below bold items in the last.
// run below line as anonymous block from develoer console.
Database.executeBatch(new TrackingStatus_BatchApex(), 10);
Note : If Number of DML statements is not 0 out 150, it means in your batch somewhere dml has been performed before calling your web service.
Number of SOQL queries: 2 out of 100
Number of query rows: 2 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 1 out of 150
Number of DML rows: 1 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 100
Number of Email Invocations: 0 out of 10
Number of future calls: 0 out of 50
Number of queueable jobs added to the queue: 0 out of 50
Number of Mobile Apex push calls: 0 out of 10
Please let me know the output.
Good Day Pradeep and Pawan,
I'm a novice salesforce developer and wasn't sure if this was even possible. This makes me very hopeful. I was wondering if you could just perhaps advice me on whether or not I am understanding the flow of processes.
I have an apex class in which I do my SOAP Api callout. Then I have a class in which I do a batch processing. And a schedule class in which I schedule the actual callout.
The scheduler calls the batch who in return calls the batch who then calls the web service class.
See code below.
Thank you in advance for the advice