Saturday, December 31, 2011

Coding JSON REST JAX-RS Service Application to Access Neo4j Database in Scala

Spring Data Neo4j makes it easy to accessing graph data in Neo4j graph database.

After separating the AspectJ-enhanced Spring Data Neo4j node entities, relationship entities, and repositories, it's very fun to access the entities from a Scala web application. In this case, I'll show you a JAX-RS application written in Scala programming language, consuming and producing JSON in REST-style. The application exposes Spring Data Neo4j through HTTP, which can be accessed via curl or any other web client.

Java programming language version:

@Path("node") @Stateless
public class NodeResource {

    private transient Logger logger = LoggerFactory.getLogger(NodeResource.class);
    @Inject Neo4jTemplate neo4j;
    @Inject InterestRepository interestRepo;
   
    @GET @Path("interest") @Produces(MediaType.APPLICATION_JSON)
    public Iterable<Interest> interest() {
        ClosableIterable<Interest> records = neo4j.findAll(Interest.class);
        return records;
    }

    @GET @Path("user") @Produces(MediaType.APPLICATION_JSON)
    public Payload<User> getUser() {
        return new Payload<User>(neo4j.findOne(5L, User.class));
    }

    @POST @Path("interest")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createInterest(Payload<Interest> payload) {
        logger.debug("createInterest {}", payload.data);
        Interest interest = payload.data;
        interest.persist();
        return Response.created(URI.create(String.format("interest/%d", interest.getNodeId())))
                .entity(new Payload<Interest>(interest)).build();
    }

    @DELETE @Path("interest/{id}")
    public Response deleteInterest(@PathParam("id") long id) {
        try {
            Interest node = neo4j.findOne(id,  Interest.class);
            node.remove();
            return Response.ok("deleted").build();
        } catch (DataRetrievalFailureException e) {
            return Response.status(Status.NOT_FOUND).entity(e.getMessage()).build();
        }
    }

    @GET @Path("interest/by/facebookId/{facebookId}")
    @Produces(MediaType.APPLICATION_JSON)
    public Payload<Interest> findInterestByFacebookId(@PathParam("facebookId") long facebookId) {
        logger.debug("findInterestByFacebookId {}", facebookId);
        Interest interest = interestRepo.findByFacebookId(facebookId);
        if (interest == null)
            throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity("Interest with facebookId="+ facebookId +" not found").build());
        return new Payload<Interest>(interest);
    }

}


Scala programming language version:

@Path("node") @Stateless
class NodeResource {

    private lazy val logger = LoggerFactory.getLogger(classOf[NodeResource])
    @Inject var neo4j: Neo4jTemplate = _
    @Inject var interestRepo: InterestRepository = _
    
    @GET @Path("interest") @Produces(Array(MediaType.APPLICATION_JSON))
    def interest: Iterable[Interest] = neo4j.findAll(classOf[Interest])

    @GET @Path("user") @Produces(Array(MediaType.APPLICATION_JSON))
    def getUser: Payload[User] = new Payload[User](neo4j.findOne(5L, classOf[User]))

    @POST @Path("interest")
    @Consumes(Array(MediaType.APPLICATION_JSON))
    @Produces(Array(MediaType.APPLICATION_JSON))
    def createInterest(payload: Payload[Interest]): Response = {
        logger.debug("createInterest {}", payload.data)
        val interest = payload.data
        interest.persist
        Response.created(URI.create(String.format("interest/%d", interest.getNodeId)))
                .entity(new Payload[Interest](interest)).build
    }

    @DELETE @Path("interest/{id}")
    def deleteInterest(@PathParam("id") id: Long): Response = {
        try {
            val node = neo4j.findOne(id, classOf[Interest])
            node.remove
            Response.ok("deleted").build
        } catch {
          case e: DataRetrievalFailureException =>
            Response.status(Status.NOT_FOUND).entity(e.getMessage).build
        }
    }

    @GET @Path("interest/by/facebookId/{facebookId}")
    @Produces(Array(MediaType.APPLICATION_JSON))
    def findInterestByFacebookId(@PathParam("facebookId") facebookId: Long): Payload[Interest] = {
        logger.debug("findInterestByFacebookId {}", facebookId)
        val interest = interestRepo.findByFacebookId(facebookId)
        if (interest == null)
            throw new WebApplicationException(Response.status(Status.NOT_FOUND).entity("Interest with facebookId="+ facebookId +" not found").build
        new Payload[Interest](interest)
    }

}


Apart from less code and cruft, Scala code is not much different in structure.

If there are list processing functions or closures, then Scala code will read much easier, while the Java code will use Guava library and clunky syntax (at least until Java 8 arrives).

To learn more about Scala programming, I recommend Programming in Scala: A Comprehensive Step-by-Step Guide, 2nd Edition.

1 comment:

  1. Hi,Different users and build in content relationships into the interface with Web Design Cochin using collaborative filtering techniques. In this book practical design methodologies underpinned by common information models can be adapted by web design and development teams.thanks.............

    ReplyDelete