users@jersey.java.net

[Jersey] Producing cleaner code

From: Ron <webron_at_gmail.com>
Date: Sat, 23 Jun 2012 17:55:21 +0300

Hi everyone,

I'm trying to find a way to write some cleaner code than we currently have
in our application.

Part of our application is used to persist several different entities in
our database.

Here's a sample code for the basic structures:

abstract class SuperEntity {}
>
> class EntityA extends SuperEntity {}
>
> class EntityB extends SuperEntity {}
>
> interface EntityService<T extends SuperEntity> {
> void doMagic(T t);
> }
>
> interface EntityAService extends EntityService<EntityA> {}
>
> interface EntityBService extends EntityService<EntityB> {}
>

As you can see, a basic entity hierarchy and a basic service hierarchy
corresponding to it.

Now, assume the following REST class:

class EntityRestService {
>
> @POST
> @Path("/EntityA")
> public void saveEntityA(EntityA entityA) {
> entityAService.doMagic(entityA);
> }
>
> @POST
> @Path("/EntityB")
> public void saveEntityB(EntityA entityB) {
> entityAService.doMagic(entityB);
> }
> }


You can see that there's some code duplication there. Since this is a
simple test case, it may not seem that bad, but imagine over 10 different
entities and quite a few additional operations and you easily get a huge
class with duplicated code.

What I'd like to be able to do is something along the lines of:

Enum EntityType {
> ENTITY_A, ENTITY_B;
> }
>
> class EntityRestService {
>
> @POST
> @Path("/{entityType}")
> public void saveEntityA(SuperEntity entity, @PathParam("entityType")
> EntityType entityType) {
> EntityService entityService = resolveService(entityType);
> entityService.doMagic(entity);
> }
>
> }
>

This would lead to a single method per operation, disregarding the entity
type. However, there are two main issues with this solution:
1. How will Jersey know which entity class to use when deserializing the
body? Obviously, SuperEntity is abstract and can't be used. It needs to
know which entity to produce based on the {entityType} path parameter,
though I'm not sure how to manage that. Will that be using a custom
MessageBodyReader or is there any other way?
2. Probably easier to handle, the entity needs to be cast before calling
the doMagic(...) method as it expects to get a specific type. I can
probably figure out to make it neater, but any suggestions would be welcome.

Should it matter, our API is based on JSON serialization and we use Jackson
for the JSON magic.

Thanks,
Ron