Closed michael-sanderson closed 4 years ago
Could you share your code of the package.json
?
I am using Lambda layers - the ask-sdk-core
package.json is:
"name": "ask-sdk-core-layer",
"version": "1.0.0",
"description": "A layer for aws alexa core",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Michael Sanderson",
"license": "ISC",
"dependencies": {
"ask-sdk-core": "^2.7.0",
"ask-sdk-model": "^1.25.1"
}
}
I also have a layer for csv-parser
Hi @michael-sanderson
I used the same version of ask-sdk-core and tried to reproduce the issue. I write some simple code to get my isp info by using monetizationServiceClient
, which is retrieved by using handlerInput.serviceClientFactory.
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
async handle(handlerInput) {
const ms = handlerInput.serviceClientFactory.getMonetizationServiceClient()
const locale = 'en-US'
const speechText = 'Welcome to the Alexa Skills Kit, you can say hello!';
const result = await ms.getInSkillProducts(locale)
console.log(result);
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
},
};
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequestHandler,
ByeIntentHandler,
)
.addErrorHandlers(ErrorHandler)
.withApiClient(new Alexa.DefaultApiClient())
.lambda();
And I can successfully get the Alexa service response
{ inSkillProducts: [], nextToken: null, truncated: false }
Your case seems weird. As I cannot reproduce with the current info, could you please paste some code here show how you use the serviceClientFactory ?
So the below code attempts to make a reminders client by invoking: handlerInput.serviceClientFactory.getReminderManagementServiceClient()
const CreateReminderIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === C.intentRequest
&& handlerInput.requestEnvelope.request.intent.name === C.yesIntent
},
async handle(handlerInput) {
const remindersApiClient = handlerInput.serviceClientFactory.getReminderManagementServiceClient(),
{ permissions } = handlerInput.requestEnvelope.context.System.user
if(!permissions) {
return handlerInput.responseBuilder
.speak("Please enable reminders permissions in the Amazon Alexa app")
.withAskForPermissionsConsentCard(["alexa::alerts:reminders:skill:readwrite"])
.getResponse()
}
try {
const now = new Date()
const nextMonday = new Date(now.setDate(now.getDate() + (1 + 7 - now.getDay()) % 7))
const reminderParams = {
requestTime : now,
trigger: {
type : 'SCHEDULED_ABSOLUTE',
scheduledTime : new Date(nextMonday.setHours(20,00,00,00)),
timeZoneId : 'Europe/Belfast',
recurrence : {
freq : 'WEEKLY',
byDay: ['Mo']
}
},
alertInfo: {
spokenInfo: {
content: [{
locale: 'en-US',
text: await getBinResponse()
}]
}
},
pushNotification : {
status : 'ENABLED'
}
}
await remindersApiClient.createReminder(reminderParams)
return handlerInput.responseBuilder
.speak(C.reminderSetMessage)
.getResponse()
} catch (error) {
return handlerInput.responseBuilder
.speak(C.reminderError)
.getResponse()
}
}
}
The skillbuilder passes the api client via the following from index.js:
const Alexa = require('ask-sdk-core')
const csv = require('csv-parser')
const initGetBinResponse = require('./helpers/getBinResponse')
const buildBinMessage = require('./helpers/buildBinMessage')
const C = require('./constants')
const getHandlers = require('./helpers/getHandlers')
const s3 = require('./aws')
const log = console.log
const getBinResponse = initGetBinResponse(
buildBinMessage,
C,
csv,
log,
s3
)
const {
LaunchRequestHandler,
CreateReminderIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
ErrorHandler
} = getHandlers(C, getBinResponse)
const skillBuilder = Alexa.SkillBuilders.custom()
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequestHandler,
CreateReminderIntentHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
)
.addErrorHandlers(ErrorHandler)
.withApiClient(new Alexa.DefaultApiClient())
.lambda()
The problem is that invoking DefaultApiClient is building an empty object. I know this because logging it out serviceClientFactor gives me:
ServiceClientFactory {
apiConfiguration: {
apiClient: DefaultApiClient {},
apiEndpoint: undefined,
authorizationValue: undefined
}
As a result of this, I get the following error when trying to call the reminders api endpoint Cannot read property 'apiEndpoint' of undefined
I dont know whether it helps but here is the Alexa object in its entirety.
{
AttributesManagerFactory: [Function: AttributesManagerFactory] { init: [Function] },
ImageHelper: [Function: ImageHelper],
PlainTextContentHelper: [Function: PlainTextContentHelper],
ResponseFactory: [Function: ResponseFactory] { init: [Function] },
RichTextContentHelper: [Function: RichTextContentHelper],
TextContentHelper: [Function: TextContentHelper],
DefaultApiClient: [Function: DefaultApiClient],
Skill: [Function: CustomSkill],
BaseSkillFactory: [Function: BaseSkillFactory] { init: [Function] },
CustomSkillFactory: [Function: CustomSkillFactory] { init: [Function] },
SkillBuilders: { custom: [Function: custom] },
getViewportDpiGroup: [Function: getViewportDpiGroup],
getViewportOrientation: [Function: getViewportOrientation],
getViewportProfile: [Function: getViewportProfile],
getViewportSizeGroup: [Function: getViewportSizeGroup],
ViewportDpiGroupOrder: [ 'XLOW', 'LOW', 'MEDIUM', 'HIGH', 'XHIGH', 'XXHIGH' ],
ViewportSizeGroupOrder: [ 'XSMALL', 'SMALL', 'MEDIUM', 'LARGE', 'XLARGE' ],
escapeXmlCharacters: [Function: escapeXmlCharacters],
getAccountLinkingAccessToken: [Function: getAccountLinkingAccessToken],
getApiAccessToken: [Function: getApiAccessToken],
getDeviceId: [Function: getDeviceId],
getUserId: [Function: getUserId],
getDialogState: [Function: getDialogState],
getIntentName: [Function: getIntentName],
getLocale: [Function: getLocale],
getRequestType: [Function: getRequestType],
getSlot: [Function: getSlot],
getSlotValue: [Function: getSlotValue],
getSupportedInterfaces: [Function: getSupportedInterfaces],
isNewSession: [Function: isNewSession],
createAskSdkError: [Function: createAskSdkError],
createAskSdkUserAgent: [Function: createAskSdkUserAgent]
}
I believe the problem lies in the fact I am using lambda layers but not sure why.
Hi, @michael-sanderson Thanks for replying and providing the necessary info.
From the serviceClient object log you provided, it seems apiEndpoint and authorizationValue is missing. From our source code here, our SDK directly copy the apiEndpoint and apiAccessToken from original Alexa request and paste them into the serviceClientFactory. Hence I guess those info are missing in your requestEnvelope, you could directly do console.log(handlerInput.requestEnvelope)
to confirm it.
If it is true that those info are not exist in the requestEnvelope, there could be multiple reasons, I am not sure if lambda layer will influence the original request, could you try to test it without lambda layer and see if problem still exist ? Also I am curious the way how you do the test, are you using the developer console and did the simulation ? If so could you also check if apiEndpoint and accessToken are exist in the original request ? I find one similar issue can be a reference here
Please let me know the result of your investigation :)
Thanks, Shen
Yeah so this answers my questions. My test object in Lambda, which is how I am testing it, doesn't include this information. So I need to add this to the test object.
The problem I have been describing is unique to testing in the lambda console so my guess is the problem doesnt actually replicate in live. I will check this and confirm
Hi,
using
ask-sdk-core
I have the following code for a custom skill:But I am getting the following error:
Cannot read property 'apiEndpoint' of undefined
and it turns out this is becauseserviceClientFactory
is empty in thehandlerInput
as a result of DefaultApiClient making an empty object?At a complete loss here.