{"id":15619163,"url":"https://github.com/xavidop/alexa-java-springboot-helloworld","last_synced_at":"2025-04-28T17:51:10.813Z","repository":{"id":45160764,"uuid":"248588987","full_name":"xavidop/alexa-java-springboot-helloworld","owner":"xavidop","description":"Alexa Skill template using SpringBoot","archived":false,"fork":false,"pushed_at":"2024-01-02T12:33:37.000Z","size":29,"stargazers_count":10,"open_issues_count":0,"forks_count":6,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-30T11:41:41.534Z","etag":null,"topics":["alexa","alexa-skill","java","skill-sample","spring","spring-boot"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xavidop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"xavidop","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-03-19T19:34:51.000Z","updated_at":"2024-10-05T00:42:51.000Z","dependencies_parsed_at":"2024-12-09T13:41:26.222Z","dependency_job_id":"fb91847e-35de-45b4-be06-862bfee1815f","html_url":"https://github.com/xavidop/alexa-java-springboot-helloworld","commit_stats":{"total_commits":11,"total_committers":2,"mean_commits":5.5,"dds":0.4545454545454546,"last_synced_commit":"900d7026a69f47e2c9efaf788fb81a323b3efbe4"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xavidop%2Falexa-java-springboot-helloworld","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xavidop%2Falexa-java-springboot-helloworld/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xavidop%2Falexa-java-springboot-helloworld/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xavidop%2Falexa-java-springboot-helloworld/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xavidop","download_url":"https://codeload.github.com/xavidop/alexa-java-springboot-helloworld/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251360991,"owners_count":21577363,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alexa","alexa-skill","java","skill-sample","spring","spring-boot"],"created_at":"2024-10-03T08:03:06.004Z","updated_at":"2025-04-28T17:51:10.796Z","avatar_url":"https://github.com/xavidop.png","language":"Java","funding_links":["https://github.com/sponsors/xavidop"],"categories":[],"sub_categories":[],"readme":"# Alexa Skill with Spring Boot\n\nYou can build a custom skill for Alexa by extending a servlet that accepts requests from and sends responses to the Alexa service in the cloud.\n\nThis project will walk through how to build a Alexa Skill with Spring Boot and Http Servlet mapping example.\n \nServlet mapping can be achieved either by using `ServletRegistrationBean` in Spring Boot as well as using Spring annotations. \nIn this example we are going to use the `ServletRegistrationBean` class to register the Alexa Servlet as a Spring bean.\n\n## Prerequisites\n\nHere you have the technologies used in this project\n1. Java 1.8\n2. Alexa Skill Kit 2.29.0\n3. Spring Boot 2.5.0.RELEASE\n4. Maven 3.6.1\n5. IntelliJ IDEA\n6. ngrok\n\n## Structure of the project\nFind below the structure of this project:\n\n```bash\n  ├────src\n  │    └───main\n  │        ├───java\n  │        │   └───com\n  │        │       └───xavidop\n  │        │           └───alexa\n  │        │               ├───configuration\n  │        │               ├───handlers\n  │        │               ├───interceptors\n  │        │               ├───localization\n  │        │               ├───properties\n  │        │               └───servlet\n  │        │\n  │        └───resources\n  │                └───locales\n  │                application.properties\n  │                log4j2.xml\n  └── pom.xml\n```\n\nThese are the main folders and files of this project:\n* **configuration**: this folder has the `WebConfig` class which will register the Alexa Http Servlet.\n* **handlers**: all the Alexa handlers. They will be process all Alexa requests.\n* **properties**: here you can find the `PropertiesUtils` class that read Spring `application.propeties` file.\n* **interceptors**: loggers and localization interceptors.\n* **localization**: Manager that will manage i18n.\n* **servlet**: the entry point of POST Requests is here. This is the `AlexaServlet`.\n* **resources**: Alexa, Spring and Log4j2 configurations.\n* **pom.xml**: dependencies of this project.\n\n## Maven dependencies\n\nThese are the dependencies used in this example. You can find them in `pom.xml` file:\n\n* Spring Boot:\n```xml\n   \u003cparent\u003e\n        \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n        \u003cartifactId\u003espring-boot-starter-parent\u003c/artifactId\u003e\n        \u003cversion\u003e2.2.5.RELEASE\u003c/version\u003e\n  \u003c/parent\u003e\n```\n\n* Alexa Skill Kit:\n```xml\n  \u003cdependency\u003e\n      \u003cgroupId\u003ecom.amazon.alexa\u003c/groupId\u003e\n      \u003cartifactId\u003eask-sdk\u003c/artifactId\u003e\n      \u003cversion\u003e2.29.0\u003c/version\u003e\n  \u003c/dependency\u003e\n```\n\n* Spring Boot starter web:\n```xml\n  \u003cdependency\u003e\n      \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n      \u003cartifactId\u003espring-boot-starter-web\u003c/artifactId\u003e\n  \u003c/dependency\u003e\n```\n\n* Log4j2:\n```xml\n  \u003cdependency\u003e\n      \u003cgroupId\u003eorg.apache.logging.log4j\u003c/groupId\u003e\n      \u003cartifactId\u003elog4j-api\u003c/artifactId\u003e\n      \u003cversion\u003e2.13.1\u003c/version\u003e\n  \u003c/dependency\u003e\n  \u003cdependency\u003e\n      \u003cgroupId\u003eorg.apache.logging.log4j\u003c/groupId\u003e\n      \u003cartifactId\u003elog4j-core\u003c/artifactId\u003e\n      \u003cversion\u003e2.13.1\u003c/version\u003e\n  \u003c/dependency\u003e\n```\n\n* Spring Boot Maven build plug-in:\n```xml\n  \u003cbuild\u003e\n        \u003cplugins\u003e\n            \u003cplugin\u003e\n                \u003cgroupId\u003eorg.springframework.boot\u003c/groupId\u003e\n                \u003cartifactId\u003espring-boot-maven-plugin\u003c/artifactId\u003e\n            \u003c/plugin\u003e\n        \u003c/plugins\u003e\n    \u003c/build\u003e\n```\n\n## The Alexa Http Servlet\n\nThanks to Alexa Http Servlet Support that you can find in the [Alexa official GitHub repository](https://github.com/alexa/alexa-skills-kit-sdk-for-java/tree/2.0.x/ask-sdk-servlet-support) and its  `SkillServlet` class we can register it with Spring Boot using `ServletRegistrationBean` as following.\n\nThe `SkillServlet` class registers the skill instance from the SkillBuilder object, and provides a doPost method which is responsible for deserialization of the incoming request, verification of the input request before invoking the skill, and serialization of the generated response.\n\nOur `AlexaServlet` class, located in the `servlet` folder, extends `SkillServlet` and after its registrations as a servlet, it will be our main entry point. \n\nThis is how this class looks like:\n\n```java\n    public class AlexaServlet extends SkillServlet {\n    \n        public AlexaServlet() {\n            super(getSkill());\n        }\n    \n        private static Skill getSkill() {\n            return Skills.standard()\n                    .addRequestHandlers(\n                            new CancelandStopIntentHandler(),\n                            new HelloWorldIntentHandler(),\n                            new HelpIntentHandler(),\n                            new LaunchRequestHandler(),\n                            new SessionEndedRequestHandler(),\n                            new FallbackIntentHandler(),\n                            new ErrorHandler())\n                    .addExceptionHandler(new MyExceptionHandler())\n                    .addRequestInterceptors(\n                            new LogRequestInterceptor(),\n                            new LocalizationRequestInterceptor())\n                    .addResponseInterceptors(new LogResponseInterceptor())\n                    // Add your skill id below\n                    //.withSkillId(\"[unique-value-here]\")\n                    .build();\n        }\n    \n    }\n```\n\nIt will receive all POST requests from Alexa and will send them to a specific handler, located in `handlers` folders, that can manage those requests.\n\n## Registering the Alexa Http Servlet as Spring Beans using ServletRegistrationBean\n\n`ServletRegistrationBean` is used to register Servlets. We need to create a bean of this class in `WebConfig`, our Spring Configuration class. \nThe most relevant methods of the `ServletRegistrationBean` class that we used in this project are:\n* `setServlet`: Sets the servlet to be registered. In our case, `AlexaServlet`.\n* `addUrlMappings`: Add URL mappings for the Servlet. We used `/alexa`.\n* `setLoadOnStartup`: Sets priority to load Servlet on startup. It is not as important as the two methods above because we only have one http Servlet in this example.\n\nThe `WebConfig` class is where we register the Alexa Http Servlet. This is how we register the servlet:\n\n```Java\n  @Bean\n  public ServletRegistrationBean\u003cHttpServlet\u003e alexaServlet() {\n\n      loadProperties();\n\n      ServletRegistrationBean\u003cHttpServlet\u003e servRegBean = new ServletRegistrationBean\u003c\u003e();\n      servRegBean.setServlet(new AlexaServlet());\n      servRegBean.addUrlMappings(\"/alexa/*\");\n      servRegBean.setLoadOnStartup(1);\n      return servRegBean;\n  }\n```\n## Setting properties\n\nThe servlet must meet certain requirements to handle requests sent by Alexa and adhere to the Alexa Skills Kit interface standards. \nFor more information, see Host a Custom Skill as a Web Service in the [Alexa Skills Kit technical documentation](https://developer.amazon.com/es-ES/docs/alexa/custom-skills/host-a-custom-skill-as-a-web-service.html).\n\nIn this example you have 4 properties that you can set in `application.properties` file:\n\n* server.port: the port that the Spring Boot app will be use.\n* com.amazon.ask.servlet.disableRequestSignatureCheck: disable/enable security.\n* com.amazon.speech.speechlet.servlet.timestampTolerance: the maximum gap between the timestamps of the request and the current local time of execution. In miliseconds.\n* javax.net.ssl.keyStore: if the first property is set to `false` then you have to specify the path of your keystore file.\n* javax.net.ssl.keyStorePassword: if the first property is set to `false` then you have to specify the password of your keystore.\n\n## Build the Skill with Spring Boot\n\nAs it is a maven project, you can build the Spring Boot application running this command:\n\n```bash\n  mvn clean package\n```\n\n## Run the Skill with Spring Boot\n\nRun the AlexaSkillAppStarter.java class as Java application i.e. go to Run→ Run as → Java Application\n\nOr, you can use\n```bash\nmvn spring-boot:run\n```\n\nAfter executing the main class, you can send Alexa POST requests to http://localhost:8080/alexa.\n\n## Debug the Skill with Spring Boot\n\nFor debugging the Spring boot app as Java application i.e. go to Debug→ Debug as → Java Application\n\nOr, if you use IntelliJ IDEA, you can do a right click in Main method of `AlexaSkillAppStarter` class:\n\n![image](https://xavidop.github.io/assets/img/blog/tutorials/alexa-springboot/debug.png)\n\nAfter executing the main class in debug mode, you can send Alexa POST requests to http://localhost:8080/alexa and debug the Skill.\n\n## Test requests locally\n\nI'm sure you already know the famous tool call [Postman](https://www.postman.com/). REST APIs have become the new standard in providing a public and secure interface for your service. Though REST has become ubiquitous, it's not always easy to test. Postman, makes it easier to test and manage HTTP REST APIs. Postman gives us multiple features to import, test and share APIs, which will help you and your team be more productive in the long run.\n\nAfter run your application you will have an endpoint available at http://localhost:8080/alexa. With Postman you can emulate any Alexa Request. \n\nFor example, you can test a `LaunchRequest`:\n\n```json\n  {\n    \"version\": \"1.0\",\n    \"session\": {\n      \"new\": true,\n      \"sessionId\": \"amzn1.echo-api.session.[unique-value-here]\",\n      \"application\": {\n        \"applicationId\": \"amzn1.ask.skill.[unique-value-here]\"\n      },\n      \"user\": {\n        \"userId\": \"amzn1.ask.account.[unique-value-here]\"\n      },\n      \"attributes\": {}\n    },\n    \"context\": {\n      \"AudioPlayer\": {\n        \"playerActivity\": \"IDLE\"\n      },\n      \"System\": {\n        \"application\": {\n          \"applicationId\": \"amzn1.ask.skill.[unique-value-here]\"\n        },\n        \"user\": {\n          \"userId\": \"amzn1.ask.account.[unique-value-here]\"\n        },\n        \"device\": {\n          \"supportedInterfaces\": {\n            \"AudioPlayer\": {}\n          }\n        }\n      }\n    },\n    \"request\": {\n      \"type\": \"LaunchRequest\",\n      \"requestId\": \"amzn1.echo-api.request.[unique-value-here]\",\n      \"timestamp\": \"2020-03-22T17:24:44Z\",\n      \"locale\": \"en-US\"\n    }\n  }\n\n```\n\nPay attention with the timestamp field of the request to accomplish with the property `com.amazon.speech.speechlet.servlet.timestampTolerance`.\n\n## Test requests directly from Alexa\n\nngrok is a very cool, lightweight tool that creates a secure tunnel on your local machine along with a public URL you can use for browsing your local site or APIs.\n\nWhen ngrok is running, it listens on the same port that you’re local web server is running on and proxies external requests to your local machine\n\nFrom there, it’s a simple step to get it to listen to your web server. Say you’re running your local web server on port 8080. In terminal, you’d type in: `ngrok http 8080`. This starts ngrok listening on port 8080 and creates the secure tunnel:\n\n![image](https://xavidop.github.io/assets/img/blog/tutorials/alexa-springboot/tunnel.png)\n\nSo now you have to go to [Alexa Developer console](https://developer.amazon.com/alexa/console/ask), go to your skill \u003e endpoints \u003e https, add the https url generated above followed by /alexa. Eg: https://fe8ee91c.ngrok.io/alexa.\n\nSelect the My development endpoint is a sub-domain.... option from the dropdown and click save endpoint at the top of the page.\n\nGo to Test tab in the Alexa Developer Console and launch your skill.\n\nThe Alexa Developer Console will send a HTTPS request to the ngrok endpoint (https://fe8ee91c.ngrok.io/alexa) which will route it to your skill running on Spring Boot server at http://localhost:8080/alexa.\n\n\n## Conclusion \n\nThis example can be useful for all those developers who do not want to host their code in the cloud or do not want to use AWS Lambda functions. This is not a problem since, as you have seen in this example, Alexa gives you the possibility to create skills in different ways. I hope this example project is useful to you.\n\nThat's all folks!\n\nHappy coding!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxavidop%2Falexa-java-springboot-helloworld","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxavidop%2Falexa-java-springboot-helloworld","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxavidop%2Falexa-java-springboot-helloworld/lists"}