応答のビルド
応答ビルダー
SDKには応答を作成するためのヘルパーメソッドが含まれています。Response
には複数の要素が含まれる場合があり、ヘルパーメソッドによって、各応答の要素を初期化したり設定したりする必要がなくなり、応答を生成しやすくなります。
使用できるヘルパーメソッド
withSpeech(String speechText)
withSimpleCard(String cardTitle, String cardText)
withStandardCard(String cardTitle, String cardText, Image image)
withReprompt(String text)
withShouldEndSession(Boolean shouldEndSession)
addHintDirective(String hintText)
addVideoAppLaunchDirective(String source, String title, String subTitle)
addTemplateDirective(Template template)
addAudioPlayerPlayDirective(PlayBehavior playBehavior, Long offsetInMilliseconds, String expectedPreviousToken, String token, String url)
addAudioPlayerStopDirective()
addAudioPlayerClearQueueDirective(ClearBehavior clearBehavior)
addDirective(Directive directive)
withCanFulfillIntent(CanFulfillIntent canFulfillIntent)
(パブリックベータSDKでのみ使用可能)
目的の応答要素を追加したら、build()
メソッドを呼び出してResponse
を生成できます。
応答ビルダーの使用例
以下の例は、ResponseBuilder
ヘルパーメソッドを使用して応答を作成する方法を示しています。
@Override
public Optional<Response> handle(HandlerInput input) {
return input.getResponseBuilder()
.withSimpleCard("title", "cardText")
.withSpeech("foo")
.withReprompt("bar")
.build();
}
テンプレートを使用して応答を作成する
SDKを使うと、テンプレートを使用してスキルの応答を作成できます。テンプレートは、動的なウェブページの作成によく使用される、モデルビューコントローラー(MVC)パターンのビューに似ています。テンプレートを使用した応答の作成には、次のメリットがあります。
- プレゼンテーションロジックをリクエスト処理ロジックから分離して、
Response
を生成できます。 - たとえば、Alexa Presentation Languageを使用する際に、複雑な入れ子構造を持つ
Response
を簡単に生成できます。 - 複数のスキルに共通のテンプレートを再利用して、コードの重複を減らすことができます。
1つのテンプレートに、outputSpeech
、card
、shouldEndSession
、directives
などの複数の応答コンポーネントを含めることができます。これらのコンポーネントは、動的データのプレースホルダーや静的データを含むことができ、スキルの完全な応答に組み込まれます。
テンプレートを使用して応答
を生成するには、スキルのビルド時にTemplate Factory
のコンフィギュレーションを行う必要があります。
Template Factory
Template Factoryインターフェースは、動的データを挿入して応答テンプレートを処理し、スキルの応答を生成します。これはRequestHandler
内でスキルの応答をビルドするときに呼び出す必要があるエントリーポイントです。独自のテンプレートファクトリーを実装することも、SDKで提供されるBaseTemplateFactory
(Template Loader
オブジェクトとTemplate Renderer
オブジェクトのリストで構成されています)を活用することもできます。
Template Loader
Template Loaderインターフェースは、データストレージからテンプレートコンテンツを読み込みます。SDKは、ローカルファイルシステムからテンプレートファイルを読み込むLocalTemplateFileLoader
を提供します。独自のローダーを実装して、別のデータストレージの場所からテンプレートを読み込むことができます。
LocalTemplateFileLoader
を使用するには、テンプレートファイルのディレクトリパスとファイル拡張子を指定する必要があります。スキルをAWS Lambdaでホスティングする場合は、テンプレートファイルをリソースとしてスキルプロジェクトのJARに含め、Maven POMでリソースディレクトリのコンフィギュレーションを行う必要があります。
Mavenリソースのコンフィギュレーション
<resources>
<resource>
<directory>src/resources</directory>
</resource>
</resources>
テンプレート列挙子
ロケールごとに異なる応答を生成できます。ロケールごとに異なるテンプレートファイルを使用するために、SDKはTemplateEnumerator
インターフェースとLocaleTemplateEnumerator
実装を提供しています。これにより、スキルリクエストのロケールプロパティに基づいて、使用可能なテンプレートの場所と名前を列挙できます。たとえば、en-US
は、template/en/US
にあるテンプレートファイルまたはtemplate_en_US
という名前のテンプレートファイルのロケールプロパティです。
前のスクリーンショットに示すように、テンプレートファイルにexample_response
という名前を付けたり、テンプレートファイルをbase_response_template
フォルダ内のロケール固有のフォルダに配置したりできます。LocaleTemplateEnumerator
は、まず最も固有性の高いテンプレートファイル(例:base_response_template/de/DE
)を探し、より固有性の低いファイル(base_response_template/de
)、グローバルなファイル(base_response_template
)へとフォールバックしていきます。
ユーザー定義のテンプレート列挙子を実装して、好みに応じてテンプレートを列挙することができます。
Template Cache
テンプレートの読み込みプロセスを簡単にするため、SDKにはTemplateCache
インターフェースとConcurrentLRUTemplateCache
が用意されており、読み込んだテンプレートを後で利用できるようにキャッシュします。ConcurrentLRUTemplateCache
は、同時キャッシュをサポートしていて、容量は5MB、有効期限(TTL)はデフォルトで24時間です。必要に応じてこれらの値を変更したり、独自のテンプレートキャッシュを実装したりできます。
Template Renderer
Template Rendererインターフェースは、動的データを含む完全なテンプレートをレンダリングして、スキルのResponse
に変換します。SDKはFreeMarkerテンプレートをレンダリングするためのFreeMarkerTemplateRenderer
を実装します。これにより、マクロやインポートなどのFreeMarkerの機能を活用することができます。独自のテンプレートレンダラーを実装して、他のテンプレートエンジンをサポートすることもできます。
FreeMarkerTemplateRenderer
を使用するには、Mavenプロジェクトのask-sdk-freemarker
に依存関係を追加する必要があります。
<dependency>
<groupId>com.amazon.alexa</groupId>
<artifactId>ask-sdk-freemarker</artifactId>
<version>${version}</version>
</dependency>
Template Factoryの使用例
以下は、Template Factoryの基本的なセットアップの例です。テンプレートのルートパスを指定するだけで、SDKがTemplate Factoryのデフォルト実装を生成します。
private static Skill getSkill() {
// スキルをビルドします
return Skills.standard()
.withTemplateDirectoryPath("/com/amazon/ask/example/")
.addRequestHandlers(
new LaunchRequestHandler(),
... ...
new SessionEndedRequestHandler())
.build();
}
Template Factoryのカスタム実装を提供することもできます。
private static Skill getSkill() {
// LocalTemplateFileLoaderのコンフィギュレーション
TemplateLoader loader = LocalTemplateFileLoader.builder()
.withDirectoryPath("com/amazon/ask/example/")
.withFileExtension("ftl")
.build();
// FreeMarkerTemplateRendererのコンフィギュレーション
JacksonJsonUnmarshaller jacksonJsonUnmarshaller = JacksonJsonUnmarshaller
.withTypeBinding(Response.class);
TemplateRenderer renderer = FreeMarkerTemplateRenderer.builder()
.withUnmarshaller(jacksonJsonUnmarshaller)
.build();
// BaseTemplateFactoryのコンフィギュレーション
TemplateFactory templateFactory = BaseTemplateFactory.builder()
.withTemplateRenderer(renderer)
.addTemplateLoader(loader)
.build();
// スキルをビルドします
return Skills.standard()
.withTemplateFactory(templateFactory)
.addRequestHandlers(
new LaunchRequestHandler(),
... ...
new SessionEndedRequestHandler())
.build();
}
テンプレートのディレクトリパスとTemplate Factoryのカスタムオブジェクトの両方を指定すると、例外がスローされます。
private static Skill getSkill() {
// ローダーとレンダラーをビルドして、Template Factoryに渡します
TemplateFactory templateFactory = BaseTemplateFactory.builder()
.withTemplateRenderer(renderer)
.addTemplateLoader(loader)
.build();
// 例外をスローします
return Skills.standard()
.withTemplateDirectoryPath("/com/amazon/ask/example/")
.withTemplateFactory(templateFactory)
.addRequestHandlers(
new LaunchRequestHandler(),
... ...
new SessionEndedRequestHandler())
.build();
}
リクエストハンドラーでテンプレートを使用して応答を生成する
@Override
public Optional<Response> handle(HandlerInput input) {
String speechText = "テンプレート応答へようこそ。";
// 動的データをテンプレートに提供します
Map<String, Object> datamap = new HashMap<>();
datamap.put("outputSpeechText", speechText);
return input.generateTemplateResponse("base_response_template", datamap);
}
上記のコード例を使用すると、次のFreeMarkerテンプレートの例では、完全なリソースパスとして/com/amazon/ask/example/base_response_template/en/US.ftl
、ディレクトリパスとして/com/amazon/ask/example/
、ファイル拡張子としてftl
がLocalTemplateFileLoader
に渡され、ロケールプロパティとしてen-US
がRequest
からLocaleTemplateEnumerator
に渡されます。
FreeMarkerテンプレートの例
以下は、スキルの応答のOutputSpeechコンポーネント用のFreeMarkerテンプレートの例です。
{
"outputSpeech": {
"type": "PlainText",
"text": "${outputSpeechText}"
}
}