Let's say we want to query an external REST API, and will use LocalServiceRegistry for this. What is the best approach for creating our service with a proper encapsulation?
With our service implementation we want to archieve the following goals:
- don't throw an error in case the service isn't created in the Business Manager yet
- keep any errors within the service, so the success status is available on the
dw.svc.Resultobject - read mock responses from an ISML template
- have the communication log available on production if required
- have a flexible way for calling multiple endpoints of the same service
Our actual implementation could now look like this.
let LocalServiceRegistry = require('dw/svc/LocalServiceRegistry');
let myQueryService;
function getDetails(operation) {
switch (operation) {
case module.exports.OPERATION_QUERY:
return {
method: 'GET',
resourceURL: '/query',
mockType: 'query'
};
default:
throw new Error('Operation unknown: ' + operation);
}
}
function getMyQueryService() {
return LocalServiceRegistry.createService('my.query.service', {
mockFull : function(service, operation) {
log.info('Doing mock call for: {0}', operation);
let Template = require('dw/util/Template');
let details = getDetails(operation);
let template = new Template('query/mock_' + details.mockType + '.isml');
return template.render();
},
createRequest: function(service, operation, params) {
const details = getDetails(operation);
service.setRequestMethod(details.method);
let baseUrl = service.configuration.credential.URL;
let resourceUrl = operationDetails.resourceURL;
if (operation === module.exports.OPERATION_QUERY) {
resourceUrl += '?param1=' + encodeURIComponent(params.param1);
}
service.setURL(baseUrl + resourceUrl);
return null;
},
parseResponse: function(service, responseObject) {
if (responseObject.statusCode !== 200) {
throw new Error('Invalid service response: ' + responseObject.statusCode);
}
return responseObject.text;
},
filterLogMessage: function(msg) {
return msg;
}
});
};
module.exports.get = function get() {
if (empty(myQueryService)) {
myQueryService = getMyQueryService();
}
return myQueryService;
};
module.exports.OPERATION_QUERY = 'OPERATION_QUERY';
With this service in place, we can use it and call our query endpoint with the following snippet:
let MyQueryService = require('*/.../MyQueryService');
let myQueryService = MyQueryService.get();
let queryResultStatus = myQueryService.call(
MyQueryService.OPERATION_QUERY,
{
'param1': one
}
);
If queryResultStatus.ok is true, our call was successful. This will archieve our defined goals, keeps the overall architecture fairly simple and makes our service maintainable in the long run!