Custom marshalling with Gson - part 1

Today, I’ll extend our project to add temporary storage of uploaded users in a HashMap<String,User> and allow retrieval of that HashMap as json. First, the new UserMap class. This class will be needed to register custom marshalling.

1
2
3
4
5
6
7
package com.ideoplex.tutorial;

import java.util.concurrent.ConcurrentHashMap;


public class UserMap extends ConcurrentHashMap<String,User> {
}

And three changes to the MyResource class. First, a static UserMap member to store the uploaded users. Second, a new getUserMap method to return the static member. And finally, an update to the postUser method to throw a WebApplicationException when uploading a duplicate email address and add the user to the static UserMap otherwise.

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
diff --git a/src/main/java/com/ideoplex/tutorial/MyResource.java b/src/main/java/com/ideoplex/tutorial/MyResource.java
index 8a932e5..60f818f 100644
--- a/src/main/java/com/ideoplex/tutorial/MyResource.java
+++ b/src/main/java/com/ideoplex/tutorial/MyResource.java
@@ -5,6 +5,8 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
import javax.ws.rs.core.MediaType;

/**
@@ -12,6 +14,10 @@
*/

@Path("myresource")
public class MyResource {
+ /**
+ * HashMap<String,User> containing all Users known to the system
+ */

+ protected static UserMap users = new UserMap();

/**
* Method handling HTTP GET requests. The returned object will be sent
@@ -26,6 +32,16 @@ public class MyResource {
}

/**
+ */

+ @GET
+ @Path("user/map")
+ @Produces(MediaType.APPLICATION_JSON)
+ public UserMap getUserMap()
+ {
+ return users;
+ }
+
+ /**
* Methods to get and post a json User object
*/

@GET
@@ -43,6 +59,17 @@ public class MyResource {
@Path("user/post")
@Consumes(MediaType.APPLICATION_JSON)
public User postUser(User user) {
- return user;
+ String email = user.getEmail();
+ if ( users.containsKey(email) ) {
+ throw new WebApplicationException(Response
+ .status(Response.Status.BAD_REQUEST)
+ .type(MediaType.TEXT_PLAIN)
+ .entity("User email \"" + email + "\" already exists")
+ .build());
+ }
+ else {
+ users.put(email, user);
+ return user;
+ }
}
}

Run mvn install to deploy the new web application and then I can post our first user to the webapp.

1
2
3
4
$ curl http://xxxxxx-nnnnnn.use1-2.nitrousbox.com:8080/jersey-gson/webapi/myresource/user/post \
--header 'Content-type: application/json' \
--data '{"email":"noone@example.com","surName":"Doe","givenName":"John"}'
{"email":"noone@example.com","surName":"Doe","givenName":"John"}

My attempt to post the same email address again fails.

1
2
3
4
$ curl http://xxxxxx-nnnnnn.use1-2.nitrousbox.com:8080/jersey-gson/webapi/myresource/user/post \
--header 'Content-type: application/json' \
--data '{"email":"noone@example.com","surName":"Doe","givenName":"John"}'
User email "noone@example.com" already exists

I post a second user.

1
2
3
4
$ curl http://xxxxxx-nnnnnn.use1-2.nitrousbox.com:8080/jersey-gson/webapi/myresource/user/post \
--header 'Content-type: application/json' \
--data '{"email":"john@example.com","surName":"Public","givenName":"John"}'
{"email":"john@example.com","surName":"Public","givenName":"John"}

And I retrieve the user map – with a little formatting for clarity:

1
2
3
4
$ curl http://xxxxxx-nnnnnn.use1-2.nitrousbox.com:8080/jersey-gson/webapi/myresource/user/map
{"john@example.com":{"email":"john@example.com","surName":"Public","givenName":"John"},
"noone@example.com":{"email":"noone@example.com","surName":"Doe","givenName":"John"}
}

I’ll continue this post tomorrow. Meanwhile, you can browse the source for jersey-gson on GitHub.

28 Sep: Jersey and Gson
30 Sep Custom marshalling with Gson - part 2