Home > Blockchain >  Lambda Error: @DynamoDBIndexHashKey must specify one of HASH GSI name/names
Lambda Error: @DynamoDBIndexHashKey must specify one of HASH GSI name/names

Time:01-27

I have the following class:

@DynamoDBTable(tableName = "PodcastReviewService-Episodes")
public class Episode {

    private String podcast;
    private int episodeNr;
    private String name;
    private int avgRating;
    private String episodeId;
    private List<Review> reviews;

    public Episode() {}

    @DynamoDBIndexHashKey(attributeName = "podcast")
    public String getPodcast() {return podcast;}

    @DynamoDBRangeKey(attributeName = "episodeNr")
    public int getEpisodeNr() {return episodeNr;}

    @DynamoDBAttribute(attributeName = "name")
    public String getName() {
        return name;
    }
    @DynamoDBIndexHashKey(attributeName = "avgRating", globalSecondaryIndexName = "avgRating")
    public int getAvgRating() {
        return avgRating;
    }

    @DynamoDBIndexRangeKey(attributeName = "episodeId", globalSecondaryIndexName = "episodeId")
    public String getEpisodeId() {
        return episodeId;
    }

    @DynamoDBAttribute(attributeName = "reviews")
    public List<Review> getReviews() {
        return reviews;
    }

The class that attempts to add an object Episode to my DynamoDB table is :

public class EpisodeDao {
    private final DynamoDBMapper dynamoDBMapper;


    public EpisodeDao() {
        this.dynamoDBMapper = new DynamoDBMapper(AmazonDynamoDBClientBuilder.standard().withCredentials(DefaultAWSCredentialsProviderChain.getInstance()).withRegion(Regions.US_WEST_2).build());
    }

    public Episode getEpisode(String podcast, int episodeNr) {
        Episode episode = this.dynamoDBMapper.load(Episode.class, podcast, episodeNr);

        if (episode == null) {
            throw new EpisodeNotFoundException("Could not find episode of "   podcast   " nr."   episodeNr);
        }
        return episode;
    }


    public Episode saveEpisode(String podcast, String name, int episodeNr) {
        Episode episode = new Episode();

        //Check if episode already exists, if so return an DuplicateEpisodeException
        //We initialize average rating at 0 since no reviews have been submitted
        if (getEpisode(podcast, episodeNr) == null) {
            episode.setPodcast(podcast);
            episode.setName(name);
            episode.setEpisodeNr(episodeNr);
            episode.setEpisodeId(podcast.charAt(0)   name.charAt(0)   PodcastReviewsUtils.generateRandomID());
            episode.setAvgRating(0);
            episode.setReviews(new ArrayList<>());
        } else throw new DuplicateEpisodeException("The episode that you are trying to add seems to already exist.");
        return episode;
    }

This is the output I get on Lambda:

  "errorMessage": "@DynamoDBIndexHashKey must specify one of HASH GSI name/names",
  "errorType": "com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMappingException",
  "stackTrace": [
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardAnnotationMaps$FieldMap.globalSecondaryIndexNames(StandardAnnotationMaps.java:345)",
    "com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel$Properties$Immutable.<init>(DynamoDBMapperFieldModel.java:459)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$Bean.<init>(StandardBeanProperties.java:92)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$Bean.<init>(StandardBeanProperties.java:86)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$BeanMap.putOrFlatten(StandardBeanProperties.java:217)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$BeanMap.putAll(StandardBeanProperties.java:207)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$BeanMap.<init>(StandardBeanProperties.java:198)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$CachedBeans.getBeans(StandardBeanProperties.java:55)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties$CachedBeans.access$100(StandardBeanProperties.java:48)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardBeanProperties.of(StandardBeanProperties.java:42)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardModelFactories$TableBuilder.<init>(StandardModelFactories.java:132)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardModelFactories$TableBuilder.<init>(StandardModelFactories.java:116)",
    "com.amazonaws.services.dynamodbv2.datamodeling.StandardModelFactories$StandardTableFactory.getTable(StandardModelFactories.java:107)",
    "com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.getTableModel(DynamoDBMapper.java:409)",
    "com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.load(DynamoDBMapper.java:447)",
    "com.amazonaws.services.dynamodbv2.datamodeling.AbstractDynamoDBMapper.load(AbstractDynamoDBMapper.java:85)",
    "com.podcast_reviews_service.dynamodb.EpisodeDao.getEpisode(EpisodeDao.java:35)",
    "com.podcast_reviews_service.dynamodb.EpisodeDao.saveEpisode(EpisodeDao.java:50)",
    "com.podcast_reviews_service.activity.AddEpisodeActivity.handleRequest(AddEpisodeActivity.java:35)",
    "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)",
    "java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)",
    "java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)",
    "java.base/java.lang.reflect.Method.invoke(Unknown Source)"
  ]

I haven't yet implemented the class that utilizes the GSI. I tried without the secondary index annotation but since my table has them I get the same error.

The error makes me think that I either annotated the Episode class wrong or I'm sending a null value as HASH key for the GSI, which I'm pretty sure I'm not.

CodePudding user response:

You must define the name of your index for the indexhashkey.

@DynamoDBIndexHashKey(attributeName = "podcast",globalSecondaryIndexNames={  "my-index-name"})
    public String getPodcast() {return podcast;}
  • Related