rest api design and construction with java ee - pages from my work diary

28

Upload: vineet-reynolds-l-p

Post on 18-Nov-2014

1.031 views

Category:

Technology


4 download

DESCRIPTION

When developers use JPA, Bean Validation and other features with JAX-RS, they start off with only a faint indication of the problems they would run into. There is more than one way to use these in conjunction with each other. Some are good, some are okay, and some are downright awful. This talk will explore practical solutions and patterns for REST APIs built with Java EE. Attendees will learn of contextual rules so they're more effective at constructing and designing JAX-RS based REST APIs.

TRANSCRIPT

Page 1: REST API design and construction with Java EE - pages from my work diary
Page 2: REST API design and construction with Java EE - pages from my work diary

REST API DESIGN AND CONSTRUCTION WITHJAVA EE

PAGES FROM MY WORK DIARYBy / Vineet Reynolds L P @VineetReynolds

Senior Software EngineerJBoss Developer Experience, Red Hat

Page 3: REST API design and construction with Java EE - pages from my work diary

ABOUT THE SPEAKEREngineer in the JBoss Developer Experience teamCurrently, contributor to :JBoss Forge 1.x and 2.0AngularJS scaffolding for JBoss ForgeJDF quickstartsTicketMonster

Others:Arquillian (GlassFish, WebLogic container adapters)

Page 4: REST API design and construction with Java EE - pages from my work diary

AGENDAA 10 minute guide to RESTJPA and JAX­RSWriting a data­driven REST API with JPA and JAX­RSComposite keysCyclic and bi­directional relationshipsLazy­fetchingClass hierarchies (java.sql.Date)Bean Validation and error reporting

Page 5: REST API design and construction with Java EE - pages from my work diary

A 10 MINUTE GUIDE TO RESTNote ­ this is really a 10 minute guide. This is not a deep­dive

into .Roy Fielding's doctoral dissertation

Page 6: REST API design and construction with Java EE - pages from my work diary

WHAT IS REST ?REST = REpresentational State TransferIt is an architectural style.It describes the design of a hypermedia system (the web).It intends to conceptualize how a well designed Webapplication should behave.

Page 7: REST API design and construction with Java EE - pages from my work diary

EXAMPLESGET /events returns all Events.GET /events/1 returns the Event with ID 1.POST /events creates a new Event.PUT /events/1 updates the Event.DELETE /events/1 deletes the Event.

Page 8: REST API design and construction with Java EE - pages from my work diary

EXAMPLESAssuming GET /events/1 returns

What kind of updates can be made in a PUT ?Session names could be updated.New Sessions could be added.Existing sessions could be deleted.

"name" : "JUDCON", "sessions" : [ "name" : "Aerogear" , "name" : "Infinispan" , "name" : "OpenShift" , "name" : "WildFly" ]

Page 9: REST API design and construction with Java EE - pages from my work diary

JAX-RS + JPA + EJB : THE BASICSLet's expose a JPA entity as a REST resource.

@Entitypublic class Event

@Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id = null;

@Version private int version = 0;

@Column private String name;

// Getters, Setters, equals() and hashCode() ...

Page 10: REST API design and construction with Java EE - pages from my work diary

JAX-RS + JPA + EJB : THE BASICSCREATING NEW EVENTS

POST /simple­event/rest/events HTTP/1.1Host: localhost:8080Content­Type: application/json;charset=UTF­8...

"name":"JUDCON"

HTTP/1.1 201 CreatedLocation: http://localhost:8080/simple­event/rest/events/1...

Page 11: REST API design and construction with Java EE - pages from my work diary

JAX-RS + JPA + EJB : THE BASICSFETCHING ALL EVENTS

GET /simple­event/rest/events HTTP/1.1Host: localhost:8080Accept: application/json, text/plain, */*...

HTTP/1.1 200 OKContent­Type: application/json...["id":1,"version":0,"name":"JUDCON"]

Page 12: REST API design and construction with Java EE - pages from my work diary

JAX-RS + JPA + EJB : THE BASICSFETCHING ONE SPECIFIC EVENT

GET /simple­event/rest/events/1 HTTP/1.1Host: localhost:8080Accept: application/json, text/plain, */*...

HTTP/1.1 200 OKContent­Type: application/json...

"id":1,"version":0,"name":"JUDCON"

Page 13: REST API design and construction with Java EE - pages from my work diary

JAX-RS + JPA + EJB : THE BASICSUPDATING AN EVENT

PUT /simple­event/rest/events/1 HTTP/1.1Host: localhost:8080Accept: application/json, text/plain, */*..."id":1,"version":0,"name":"JUDCON India"

HTTP/1.1 204 No Content...

Page 14: REST API design and construction with Java EE - pages from my work diary

JAX-RS + JPA + EJB : THE BASICSDELETING AN EVENT

DELETE /simple­event/rest/events/1 HTTP/1.1Host: localhost:8080Accept: application/json, text/plain, */*...

HTTP/1.1 204 No Content...

Page 15: REST API design and construction with Java EE - pages from my work diary

COMPOSITE KEYS ARE NOT FUNAddressability suffers. Matrix parameters will help with

composite keys.

// Key for event = name, locationGET /events;name=JUDCON;location=India

But ...They're not a standard. Just a W3C design note.Lack of client support (but improving). Among popular JSlibraries, only Dojo, AngularJS, Backbone.js has support.If cheap, establish a mapping scheme for composite keys.

Page 16: REST API design and construction with Java EE - pages from my work diary

RELATIONSHIPSHandling modifications to relationships in JPA entities can get

difficult.

Page 17: REST API design and construction with Java EE - pages from my work diary

CREATE A NEW EVENT

POST /bidi­event/rest/events HTTP/1.1Host: localhost:8080Accept: application/json, text/plain, */*...

"name":"JUDCON","location":"Bangalore"

HTTP/1.1 201 CreatedLocation: http://localhost:8080/bidi­event/rest/events/1...

Page 18: REST API design and construction with Java EE - pages from my work diary

FETCH AN EXISTING EVENT

GET /bidi­event/rest/events/1 HTTP/1.1Host: localhost:8080Accept: application/json, text/plain, */*...

HTTP/1.1 200 OKContent­Type: application/json..."id":1,"version":0,"name":"JUDCON","location":"Bangalore","sessions":[]

Page 19: REST API design and construction with Java EE - pages from my work diary

CREATE A NEW SESSION

POST /bidi­event/rest/sessions HTTP/1.1Host: localhost:8080Accept: application/json, text/plain, */*

"sessionName":"Aerogear", "speaker":"Sebastian", "event":"id":1, "version":0, "name":"JUDCON", "location":"Bangalore", "sessions":[]

HTTP/1.1 201 CreatedLocation: http://localhost:8080/bidi­event/rest/sessions/2...

Page 20: REST API design and construction with Java EE - pages from my work diary

FETCH THE NEWLY CREATED SESSION

GET /bidi­event/rest/sessions/2 HTTP/1.1Host: localhost:8080Accept: application/json, text/plain, */*...

HTTP/1.1 500 Internal Server ErrorContent­Type: text/html;charset=utf­8

JBWEB000065: HTTP Status 500 ­ org.codehaus.jackson.map.JsonMappingExceptionfailed to lazily initialize a collection of role: com.example.bidievent.modelno Session (through reference chain: com.example.bidievent.model.Session["event"

Page 21: REST API design and construction with Java EE - pages from my work diary

WHAT JUST HAPPENED?Event.sessions is lazily fetched.During serialization, the proxy does not find an activesession.Let's try and solve this crudely, using eager fetching ...

"id":2,"version":0,"sessionName":"Aerogear","speaker":"Sebastian","event":["id":2,"version":0,"sessionName":"Aerogear","speaker":"Sebastian","event":["id":2,"version":0,"sessionName":"Aerogear","speaker":"Sebastian","event":...// This never terminates

Page 22: REST API design and construction with Java EE - pages from my work diary

HOW DO YOU SOLVE THIS ?If you can, do not expose collection members of JPA entitiesdirectly.Use sub­resources for dependent collections (1:M).Use a mapping layer. Create Representation classes to mapJPA object graphs.The mappings translate RESTful actions into operations inthe domain model.Or, use different representations of the same JPA entity fordifferent operations (not a good idea).One to create an entity with collections, another to updateonly the entity.Model collections as a separate resource.Makes sense for M:N relationships.

Page 23: REST API design and construction with Java EE - pages from my work diary

JAVA.SQL.* HATES YOUConsider the following

During serialization, startTime's type is java.sql.Time.Given a value of 2:00 PM IST, the field will be serialized as"startTime":"14:00:00".When deserializing back, "startTime":"1970­01­01T14:00:00.000+05:30" should be supplied.

@Temporal(TemporalType.TIME)java.util.Date startTime;

Page 24: REST API design and construction with Java EE - pages from my work diary

JAVA.SQL.* HATES YOUBefore, we discuss solutions, let's talk about:

ISO8601 vs Unix timestamps. Which one to use ?The former is almost always better.Date, time and timestamp formats. Omit unnecessary info inISO8601 formats (like time values for Dates).

Page 25: REST API design and construction with Java EE - pages from my work diary

JAVA.SQL.* HATES YOULessons learnt ­Be aware of the actual types of the objects duringserialization and deserialization.Constrain the actual types and hence theserializers/deserializers used.When writing custom serializers, design them for classhierarchies.Think of the equals() contract, but for serialized forms.And of course, avoid java.util.Date/Calendar. Use specifictypes in Joda­Time and eventually JSR­310 (Java 8).Using a specific type binds a serializer + deserializer to thefield.

Page 26: REST API design and construction with Java EE - pages from my work diary

BEAN VALIDATION AND VIOLATION REPORTINGResponses for Constraint violation errors on JPA entities arenot standardized.By default, HTML responses will be provided if noExceptionMappers exist forConstraintViolationExceptions.Bean Validation for request parameters is available out­of­the­box, but requires activation.RESTEasy has one format, Jersey has another.

Page 27: REST API design and construction with Java EE - pages from my work diary

QUESTIONS ?

Page 28: REST API design and construction with Java EE - pages from my work diary