Alexa Skill With Java — Using variables and Persistence in Database

Rohit Sharma
Voice Tech Podcast
Published in
5 min readNov 3, 2019

Hello again, I hope you have read the previous article which was Developing Alexa skill with Java.

Alexa Skill with Attributes and Persistence

In this article, we will learn on how to use the variables and pass them through different requests. Other than that, I will also tell you on how you can save the data to the DynamoDb provided by AWS.

So, the requirements are the same. You need to have :

  1. Eclipse (Or Any other IDE compatible with Maven)
  2. Maven
  3. An account on Amazon AWS
  4. An Amazon Developer Account

To test this out, you can create an Alexa skill using the previous article in which I mentioned how can you develop an Alexa skill in 20 minutes.

Alexa Attributes :

There are 3 types of attributes present in Alexa and they are :

  1. Session Attribute : These attributes or variable will save the data throughout the session and will be cleared automatically either when the session ends or session timed out.
  2. Request Attribute : These attribute or variable will be saved only for the request. So, you can also call them as temporary variables. These are useful when you have to use the input for some util method or something like that.
  3. Persistent Attribute : These are the attributes that will be used for the persistence. That means, that these values or variables are the one that are going to store in the database.

Well, I think we should go in detail for these attributes :

Session Attributes :

As explained above, these variables will be stored in the session until it ends. To access them, or to change them you have to use the object of HandlerInput.

If you have cloned the above GitHub code, then it would be better. So in that open the LaunchRequestHandler class and enter the below lines of code in the handle method.

Map<String,Object> sessionMap = input.getAttributesManager().getSessionAttributes();sessionMap.put(“test”, “Hello”);input.getAttributesManager().setSessionAttributes(sessionMap);

As you can see, first we are extracting the complete map and putting a value of “Hello with a key “test”. Now this approach has several disadvantages. First of all, we have to extract the map, after that we have to set the map again. So instead of the above approach, we can also use the below code :

input.getAttributesManager().getSessionAttributes().put(“test”, “Hello”);

Both of the above code will work the same, so it is up to you to choose whatever approach you want.

So, the complete code will look like :

public class LaunchRequestHandler implements RequestHandler{public boolean canHandle(HandlerInput input) {
return input.matches(Predicates.requestType(LaunchRequest.class));
}
public Optional<Response> handle(HandlerInput input) {

String speechText = “Hello to test your skills, Say yes to check the session variable.”;

input.getAttributesManager().getSessionAttributes().put(“test”, “Hello”);

return input.getResponseBuilder()
.withSpeech(speechText)
.withSimpleCard(“LaunchRequest”, speechText)
.withReprompt(speechText)
.build();
}
}

After this, if the you say “Yes”, it will directly go to the Amazon.YesIntent. So, open the PositiveIntentHandler and enter the below code :

String helloString = (String) input.getAttributesManager().getSessionAttributes().get(“test”);String speechText = “The variable which I got from session is, “+helloString;

So, as you can see that we are extracting the variable which we have already set in LaunchRequest and using that to output.

The complete code will look like :

public class PositiveIntentHandler implements RequestHandler{public boolean canHandle(HandlerInput input) {return input.matches(intentName(“AMAZON.YesIntent”));}public Optional<Response> handle(HandlerInput input) {String helloString = (String) input.getAttributesManager().getSessionAttributes().get(“test”);String speechText = “The variable which I got from session is, “+helloString;return input.getResponseBuilder().withSpeech(speechText).withSimpleCard(“YesIntent”, speechText).build();}}

You can also use :

System.out.println(helloString);

As all the console print are saved in Cloudwatch logs, you can check the value there.

Build better voice apps. Get more articles & interviews from voice technology experts at voicetechpodcast.com

Request Attribute :

As explained above, the request attribute are valid only for a request and they can accessed from HandlerInput object as well.

To access the RequestAttribute you can use :

Map<String,Object> requestMap = input.getAttributesManager().getRequestAttributes();

And to put values, you can go something like this:

input.getAttributesManager().getRequestAttributes().put(“temp”, “check”);

As this is nearly the same as SessionAttribute so, I encourage you to try this your self.

Persistent Attribute :

The last one and an important one as well. So, I guessed if you have read the article then you may know that it is also a map. This will store all the data present in this in key-value pair in the DynamoDB of AWS.

The first key or the primary key will be the device Id, so you don’t have to write the code to fetch the details. As they will be automatically fetched from the DB when your skill starts.

Now to use this, lets continue from the last step where we were in the PositiveIntent. So, here we will put something in the PersistentMap and input the stop so that the StopIntent will trigger. In that, we will store the values.

So, in the PositiveIntent enter this line :

input.getAttributesManager().getPersistentAttributes().put(“CheckPersistence”, “I think its checked”);

Now, come down to CancelandStopIntentHandler and enter these lines :

input.getAttributesManager().savePersistentAttributes();

This command will trigger the saving of data. So, the complete code of CancelandStopIntentHandler will look like this :

public class CancelandStopIntentHandler implements RequestHandler{public boolean canHandle(HandlerInput input) {return input.matches(intentName(“AMAZON.StopIntent”).or(intentName(“AMAZON.CancelIntent”)));}public Optional<Response> handle(HandlerInput input) {input.getAttributesManager().savePersistentAttributes();return input.getResponseBuilder().withSpeech(“Goodbye”).withSimpleCard(“StopSkill”, “Goodbye”).build();}}

You just have to do one more thing. In the StreamHandler class, in this case which is HelloWorldStreamHandler you have to add these lines:

private static Skill getSkill() {return Skills.standard().addRequestHandlers(new LaunchRequestHandler(),new CancelandStopIntentHandler(),new FallbackIntentHandler(),new SessionEndedRequestHandler(),new HelpIntentHandler(),new PositiveIntentHandler(),new NegativeIntentHandler()).withTableName(“HelloWorld”).withAutoCreateTable(true).build();}

So, as you can see in the end, we have added two new property. One is withTableName in which as the name suggest we have to enter the table name for our skill.

And the other property, that is withAutoCreateTable we are putting as true so that the table will be created automatically.

POINT TO NOTE :

One thing you should do carefully is to provide the permission to the skill to use DynamoDB and Cloudwatch. If permissions are not applied, then it will throw an Exception.

Getting Values From DynamoDB :

Now, to get values from DynamoDB, you just have to use the persistent attribute. That means, that Alexa will automatically send you back the data for the specific user.

All the data in DynamoDB is stored with keeping the user id as the primary key. So by that, whenever the user is coming back and a match is found in the database, the data will be sent back.

So, lets say we check for the persistent attribute in our LaunchRequest class. So, the code would go something like this:

public class LaunchRequestHandler implements RequestHandler{public boolean canHandle(HandlerInput input) {return input.matches(Predicates.requestType(LaunchRequest.class));}public Optional<Response> handle(HandlerInput input) {Map<String, Object> persistentAttributes = input.getAttributesManager().getPersistentAttributes();String speechText = “This is the case, when we didn't get values”if (persistentAttributes.containsKey("CheckPersistence")) {
speechText = “Yes !! We got the values”
}return input.getResponseBuilder().withSpeech(speechText).withSimpleCard(“LaunchRequest”, speechText).withReprompt(speechText).build();}}

So, I think we have covered all the parts for attributes and persisted in Alexa with Java.

If you have any problem in understanding any of them, just put a comment and I will try to clarify it as soon as possible.

Something just for you

--

--

Rohit Sharma
Voice Tech Podcast

A Java Developer who loves to learn new things and making new friends.