michaellavelle / spring-data-dynamodb

Simplifies the development of creating an Amazon DynamoDB-based Java data access layer
https://derjust.github.io/spring-data-dynamodb/
Apache License 2.0
169 stars 284 forks source link

IllegalArgumentException thrown when CRUD find has 0 result #26

Closed jnngrm closed 9 years ago

jnngrm commented 10 years ago

When using CRUD operation:

@Override
public <T> T load(Class<T> domainClass, Object hashKey) {
    T entity =  dynamoDBMapper.load(domainClass, hashKey);
    maybeEmitEvent(new AfterLoadEvent<Object>(entity));
    return entity;
}

It is possible that Amazon API will return null Entity if no entity found. However the instantation of AfterLoadEvent specifically checks for null argument and throws exception if argument found. Perhaps an artifact of newer spring 4.x versions?

/* * Constructs a prototypical Event. * @param source The object on which the Event initially occurred. * @exception IllegalArgumentException if source is null. */ public EventObject(Object source) { if (source == null) throw new IllegalArgumentException("null source");

    this.source = source;
}
jnngrm commented 10 years ago

Little more info on this...if you drill down into AWS SDK to the method used, it states null is a valid response:

/**
 * Returns an object whose keys match those of the prototype key object given,
 * or null if no such item exists.
 *
 * @param keyObject
 *            An object of the class to load with the keys values to match.
 * @param config
 *            Configuration for the service call to retrieve the object from
 *            DynamoDB. This configuration overrides the default given at
 *            construction.
 */
public <T extends Object> T load(T keyObject, DynamoDBMapperConfig config) {
    @SuppressWarnings("unchecked")
    Class<T> clazz = (Class<T>) keyObject.getClass();

    config = mergeConfig(config);

    String tableName = getTableName(clazz, config);

    GetItemRequest rq = new GetItemRequest()
        .withRequestMetricCollector(config.getRequestMetricCollector());

    Map<String, AttributeValue> key = getKey(keyObject, clazz);

    rq.setKey(key);
    rq.setTableName(tableName);
    rq.setConsistentRead(config.getConsistentReads() == ConsistentReads.CONSISTENT);

    GetItemResult item = db.getItem(applyUserAgent(rq));
    Map<String, AttributeValue> itemAttributes = item.getItem();
    if ( itemAttributes == null ) {
        return null;
    }

    T object = marshalIntoObject(toParameters(itemAttributes, clazz, config));
    return object;
}

Also, for a little more context, here's the exception that is thrown:

java.lang.IllegalArgumentException: null source at java.util.EventObject.(EventObject.java:56) at org.springframework.context.ApplicationEvent.(ApplicationEvent.java:42) at org.socialsignin.spring.data.dynamodb.mapping.event.DynamoDBMappingEvent.(DynamoDBMappingEvent.java:29) at org.socialsignin.spring.data.dynamodb.mapping.event.AfterLoadEvent.(AfterLoadEvent.java:28) at org.socialsignin.spring.data.dynamodb.core.DynamoDBTemplate.load(DynamoDBTemplate.java:98) at org.socialsignin.spring.data.dynamodb.query.SingleEntityLoadByHashKeyQuery.getSingleResult(SingleEntityLoadByHashKeyQuery.java:34) at org.socialsignin.spring.data.dynamodb.query.AbstractSingleEntityQuery.getResultList(AbstractSingleEntityQuery.java:32) at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery$CollectionExecution.execute(AbstractDynamoDBQuery.java:88) at org.socialsignin.spring.data.dynamodb.repository.query.AbstractDynamoDBQuery.execute(AbstractDynamoDBQuery.java:234)

michaellavelle commented 10 years ago

Hi jnngrm

Thank you for raising this and for describing the issue and cause so comprehensively.

I've committed a change which now only emits AfterLoadEvent if loaded entity is non-null - the tests I've added reproduced the issue and with this fix I think the issue is resolved.

Are you able to confirm?

Thanks again,

Michael

jnngrm commented 10 years ago

Mi Michael,

Nice, fix looks great. Unfortunately Maven is complaining about the repo right now:

[WARNING] Checksum validation failed, expected <!DOCTYPE but is 12aa592dc7660b2b9d408d80c1759416596ed4e3 for http://repo.opensourceagility.com/snapshots/org/socialsignin/spring-data-dynamodb/1.0.1-SNAPSHOT/maven-metadata.xml
Downloaded: http://repo.opensourceagility.com/snapshots/org/socialsignin/spring-data-dynamodb/1.0.1-SNAPSHOT/maven-metadata.xml (413 B at 0.6 KB/sec)
[WARNING] The metadata /Users/jingram/.m2/repository/org/socialsignin/spring-data-dynamodb/1.0.1-SNAPSHOT/maven-metadata-opensourceagility-snapshots.xml is invalid: end tag name </body> must match start tag name <hr> from line 7 (position: TEXT seen ...</address>\n</body>... @9:8)
[WARNING] The metadata /Users/jingram/.m2/repository/org/socialsignin/spring-data-dynamodb/1.0.1-SNAPSHOT/maven-metadata-opensourceagility-snapshots.xml is invalid: end tag name </body> must match start tag name <hr> from line 7 (position: TEXT seen ...</address>\n</body>... @9:8)

Not sure if this is my environment or this projects repo.

jnngrm commented 10 years ago

I was able to build the project locally and test, working great now. Just wish the repo was working :-). FYI, I had to modify the POM in a minor way to build successfully:

Users-MacBook-Pro:spring-data-dynamodb jingram$ git diff
diff --git a/pom.xml b/pom.xml
index 3134cbe..63a4d28 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
                <groupId>org.springframework.data.build</groupId>
                <artifactId>spring-data-parent</artifactId>
                <version>1.4.0.M1</version>
-               <relativePath>../spring-data-build/parent/pom.xml</relativePath>
+               <!--<relativePath>../spring-data-build/parent/pom.xml</relativePath>-->
        </parent>

         <distributionManagement>
@@ -235,6 +235,10 @@
                                <enabled>false</enabled>
                        </snapshots>
                </pluginRepository>
+                <pluginRepository>
+                        <id>Maven Plugin Repository</id>
+                        <url>http://repo2.maven.org/maven2</url>
+                </pluginRepository>
        </pluginRepositories>

 </project>