db[mr.result].distinct("_id")
["foo", "bar", "baz", "_id", ...]

Friday, 21 June 2013

Introduction

One of the unsung heros in the HTML5 universe is XMLHttpRequest.
Strictly speaking XHR2 isn't HTML5. However, it's part of the incremental improvements
browser vendors are making to the core platform. I'm including XHR2 in our new bag of
goodies because it plays such an integral part in today's complex web apps.

Turns out our old friend got a huge makeover but many folks
are unaware of its new features. XMLHttpRequest Level 2
introduces a slew of new capabilities which put an end to crazy hacks in our web apps;
things like cross-origin requests, uploading progress events,
and support for uploading/downloading binary data. These allow AJAX
to work in concert with many of the bleeding edge HTML5 APIs such as File System API,
Web Audio API,
and WebGL.

Fetching data

Fetching a file as a binary blob has been painful with XHR. Technically,
it wasn't even possible. One trick that has been well documented involves
overriding the mime type with a user-defined charset as seen below.

Wednesday, 12 June 2013

For CRUD operations, a PUT request to a URL is common and usually
overwrites the entire object. In our case however, this is not possible:
some object properties are read-only, and others can only be written if
the object has a certain status. So what we need is a _partial_ update.
And although it is usually possible to omit fields from the request body, this does not do what we want. What happens is for missing fields, use the default value from the constructor. But what we want is: for missing fields, to not change the value in the database.
We’ve created an annotation @RequestEntity to handle these parameters. Like @PathEntity,
a URL template is tied to a domain entity, but now the request body is
used to update the (detached) record. An example usage would be:

CRUD applications

The provided examples show the building blocks to reduce a CRUD application to almost no code beyond searching:

Create

The @RequestBody annotation combined with @Valid (see the first example) ensure that the controller only needs to save the record.

Read

The @PathEntity annotation in the second example
already provides a loaded record, so the controller can simply return
it. Only returning multiple records (i.e. searches) requires more code.

Update

The @RequestEntity annotation in the third example provides a detached, updated and optionally validated record. This includes partial updates The controller method only has to save it.

Delete

The @PathEntity annotation provides a record, so it can simply be removed.

As you can see, this means that implementing CRUD has become as
trivial as calling your persistence layer. And as an added bonus, the
more complex use cases are now also easier to implement: only the call
to your business method is needed.

Conclusion

The examples in this article show that it is easy to extend the default
Spring functionality to extract any information you want from the
request. You can augment the existing functionality with, for example,
JSR-303 validations. Or you can completely roll your own solution,
including merging the request information with existing data. Combined
with the generic Spring concept that any REST call is a method
invocation, anything is possible. Your business needs are in control, not the technology.

Another thing we encounter regularly, is that we want to issue a POST
request to a URL to execute an action on a domain object. As we prefer
not to repeat the code to retrieve the domain object, we’ve created an
annotation @PathEntity so we can do this:

Granted, we could also do this by overriding the Spring
ConversionService, but as we’ll see in the next example this approach
has it’s advantages. The code for the @PathEntity annotation and the PathEntityMethodArgumentResolver to handle it is this:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

package com.jay.demo;

import java.lang.annotation.Documented;

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

* Annotation to indicate a method parameter should be bound to a URL template, and retrieved as a domain entity.

* Used for annotated methods.

*/

@Target(ElementType.PARAMETER)

@Retention(RetentionPolicy.RUNTIME)

@Documented

public@interfacePathEntity{

/**

* The name of the URL template that contains the

* .

*

* @return the name of the URL template that is the entity id

*/

Stringvalue();

}

And this is the class to resolve parameters annotated with @PathEntity:

String.format("Cannot find a %s with id=%d",entityType.getSimpleName(),entityId));

}

returnentity;

}

}

Registering this MethodHandlerArgumentResolver is as usual:

1

2

3

4

5

<mvc:annotation-driven>

<mvc:argument-resolvers>

<bean class="nl.t42.spring31.PathEntityMethodArgumentResolver"/>

</mvc:argument-resolvers>

</mvc:annotation-driven>

With these two classes in place, we can identify our domain objects
with our REST resources (URL’s). When the controller method is invoked,
we have an instance of the domain entity the URL represents. Note that
outside a transaction, this entity is a detached entity (this is
prescribed by the JPA specification). So we still need to call EntityManager.merge(Object) to persist any changes.