rest api design for jax-rs and jersey
DESCRIPTION
Designing and building a really clean and intuitive ReST API is no small feat. You have to worry about resources, collections of resources, pagination, query parameters, references to other resources, which HTTP methods to use, HTTP caching, security, and more. And you have to make sure it lasts and doesn’t break clients as you add features over time. Furthermore, although there are many references on creating REST APIs with XML, there are far fewer references on REST + JSON. It is enough to drive you crazy. This session demonstrates how to design and implement an elegant REST API.TRANSCRIPT
![Page 1: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/1.jpg)
REST + JSON APIswith JAX-RS
Les HazlewoodCTO, Stormpathstormpath.com
![Page 2: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/2.jpg)
.com
• Identity Management andAccess Control API
• Security for your applications• User security workflows• Security best practices• Developer tools, SDKs, libraries
![Page 3: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/3.jpg)
Outline• REST Fundamentals• Design:
Base URLVersioningResource FormatReturn ValuesContent NegotiationReferences (Linking)PaginationQuery ParametersAssociations
ErrorsIDsMethod OverloadingResource ExpansionPartial ResponsesCaching & EtagsSecurityMulti TenancyMaintenance
• Coding Time! (JAX-RS-based App)
![Page 4: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/4.jpg)
Why REST?
• Scalability• Generality• Independence• Latency (Caching)• Security• Encapsulation
Learn more at Stormpath.com
![Page 5: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/5.jpg)
HATEOAS
• Hypermedia
• As
• The
• Engine
• Of
• Application
• State
Further restriction on REST architectures.Learn more at Stormpath.com
![Page 8: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/8.jpg)
REST can be easy
(if you follow some guidelines)
Learn more at Stormpath.com
![Page 9: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/9.jpg)
Example Domain: Stormpath
• Applications• Directories• Accounts• Groups• Associations• Workflows
![Page 11: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/11.jpg)
Resources
Nouns, not Verbs
Coarse Grained, not Fine Grained
Architectural style for use-case scalability
Learn more at Stormpath.com
![Page 12: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/12.jpg)
/getAccount
/createDirectory
/updateGroup
/verifyAccountEmailAddress
What If?
Learn more at Stormpath.com
![Page 13: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/13.jpg)
/getAccount/getAllAccounts/searchAccounts/createDirectory/createLdapDirectory/updateGroup/updateGroupName/findGroupsByDirectory/searchGroupsByName/verifyAccountEmailAddress/verifyAccountEmailAddressByToken…Smells like bad RPC. DON’T DO THIS.
What If?
Learn more at Stormpath.com
![Page 15: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/15.jpg)
The Answer
Fundamentally two types of resources:
Collection Resource
Instance Resource
Learn more at Stormpath.com
![Page 19: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/19.jpg)
Behavior
POST, GET, PUT, DELETE
≠ 1:1Create, Read, Update, Delete
Learn more at Stormpath.com
![Page 20: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/20.jpg)
Behavior
As you would expect:
GET = ReadDELETE = DeleteHEAD = Headers, no Body
Learn more at Stormpath.com
![Page 21: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/21.jpg)
Behavior
Not so obvious:
PUT and POST can both be used forCreate and Update
Learn more at Stormpath.com
![Page 22: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/22.jpg)
PUT for Create
Identifier is known by the client:
PUT /applications/clientSpecifiedId
{ …}
Learn more at Stormpath.com
![Page 23: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/23.jpg)
PUT for Update
Full Replacement
PUT /applications/existingId{ “name”: “Best App Ever”, “description”: “Awesomeness”}
Learn more at Stormpath.com
![Page 25: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/25.jpg)
POST as CreateOn a parent resource
POST /applications{ “name”: “Best App Ever”}
Response:
201 CreatedLocation: https://api.stormpath.com/applications/a1b2c3
Learn more at Stormpath.com
![Page 26: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/26.jpg)
POST as UpdateOn instance resource
POST /applications/a1b2c3
{ “name”: “Best App Ever. Srsly.”}
Response:
200 OK
Learn more at Stormpath.com
![Page 28: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/28.jpg)
Media Types
• Format Specification + Parsing Rules• Request: Accept header• Response: Content-Type header
• application/json• application/foo+json• application/foo+json;application• …
Learn more at Stormpath.com
![Page 31: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/31.jpg)
http(s)://api.foo.com
vs
http://www.foo.com/dev/service/api/rest
Learn more at Stormpath.com
![Page 34: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/34.jpg)
URL https://api.stormpath.com/v1
vs.
Media-Type application/json+foo;application&v=1
Learn more at Stormpath.com
![Page 36: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/36.jpg)
Media Type
Content-Type: application/json
When time allows:
application/foo+jsonapplication/foo+json;bar=baz&v=1…
Learn more at Stormpath.com
![Page 37: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/37.jpg)
camelCase
‘JS’ in ‘JSON’ = JavaScript
myArray.forEach Not myArray.for_each
account.givenNameNot account.given_name
Underscores for property/function names are unconventional for JS. Stay consistent.
Learn more at Stormpath.com
![Page 38: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/38.jpg)
Date/Time/Timestamp
There’s already a standard. Use it: ISO 8601
Example:
{ …, “createdTimestamp”: “2012-07-10T18:02:24.343Z”}
Use UTC!
Learn more at Stormpath.com
![Page 39: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/39.jpg)
HREF
• Distributed Hypermedia is paramount!• Every accessible Resource has a unique URL.• Replaces IDs (IDs exist, but are opaque).
{ “href”: https://api.stormpath.com/v1/accounts/x7y8z9”, …}
Critical for linking, as we’ll soon see
Learn more at Stormpath.com
![Page 41: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/41.jpg)
GET obvious
What about POST?
Return the representation in the response when feasible.
Add override (?_body=false) for control
Learn more at Stormpath.com
![Page 43: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/43.jpg)
Header
• Accept header
• Header values comma delimited in order of preference
GET /applications/a1b2c3Accept: application/json, text/plain
Learn more at Stormpath.com
![Page 44: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/44.jpg)
Resource Extension
/applications/a1b2c3.json/applications/a1b2c3.csv…
Conventionally overrides Accept header
Learn more at Stormpath.com
![Page 46: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/46.jpg)
• Hypermedia is paramount. • Linking is fundamental to scalability.
• Tricky in JSON• XML has it (XLink), JSON doesn’t• How do we do it?
Learn more at Stormpath.com
![Page 47: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/47.jpg)
Instance Reference
GET /accounts/x7y8z9
200 OK{ “href”: “https://api.stormpath.com/v1/accounts/x7y8z9”, “givenName”: “Tony”, “surname”: “Stark”, …, “directory”: ????}
Learn more at Stormpath.com
![Page 48: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/48.jpg)
Instance Reference
GET /accounts/x7y8z9
200 OK{ “href”: “https://api.stormpath.com/v1/accounts/x7y8z9”, “givenName”: “Tony”, “surname”: “Stark”, …, “directory”: { “href”: “https://api.stormpath.com/v1/directories/g4h5i6” }}
Learn more at Stormpath.com
![Page 49: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/49.jpg)
Collection Reference
GET /accounts/x7y8z9
200 OK{ “href”: “https://api.stormpath.com/v1/accounts/x7y8z9”, “givenName”: “Tony”, “surname”: “Stark”, …, “groups”: { “href”: “https://api.stormpath.com/v1/accounts/x7y8z9/groups” }}
Learn more at Stormpath.com
![Page 50: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/50.jpg)
Reference Expansion
(aka Entity Expansion, Link Expansion)
Learn more at Stormpath.com
![Page 52: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/52.jpg)
GET /accounts/x7y8z9?expand=directory
200 OK{ “href”: “https://api.stormpath.com/v1/accounts/x7y8z9”, “givenName”: “Tony”, “surname”: “Stark”, …, “directory”: { “href”: “https://api.stormpath.com/v1/directories/g4h5i6”, “name”: “Avengers”, “creationDate”: “2012-07-01T14:22:18.029Z”, … }}
Learn more at Stormpath.com
![Page 54: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/54.jpg)
GET /accounts/x7y8z9?fields=givenName,surname,directory(name)
Learn more at Stormpath.com
![Page 56: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/56.jpg)
Collection Resource supports query params:• Offset• Limit
…/applications?offset=50&limit=25
Learn more at Stormpath.com
![Page 57: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/57.jpg)
GET /accounts/x7y8z9/groups
200 OK{ “href”: “…/accounts/x7y8z9/groups”, “offset”: 0, “limit”: 25, “first”: { “href”: “…/accounts/x7y8z9/groups?offset=0” }, “previous”: null, “next”: { “href”: “…/accounts/x7y8z9/groups?offset=25” }, “last”: { “href”: “…”}, “items”: [ { “href”: “…” }, { “href”: “…” }, … ]}
Learn more at Stormpath.com
![Page 59: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/59.jpg)
Group to Account
• A group can have many accounts• An account can be in many groups• Each mapping is a resource:
GroupMembership
Learn more at Stormpath.com
![Page 60: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/60.jpg)
GET /groupMemberships/23lk3j2j3
200 OK{ “href”: “…/groupMemberships/23lk3j2j3”, “account”: { “href”: “…” }, “group”: { “href”: “…” }, …}
Learn more at Stormpath.com
![Page 61: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/61.jpg)
GET /accounts/x7y8z9
200 OK{ “href”: “…/accounts/x7y8z9”, “givenName”: “Tony”, “surname”: “Stark”, …, “groups”: { “href”: “…/accounts/x7y8z9/groups” }, “groupMemberships”: { “href”: “…/groupMemberships?accountId=x7y8z9” }}
Learn more at Stormpath.com
![Page 63: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/63.jpg)
• As descriptive as possible• As much information as possible• Developers are your customers
Learn more at Stormpath.com
![Page 64: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/64.jpg)
POST /directories
409 Conflict{ “status”: 409, “code”: 40924, “property”: “name”, “message”: “A Directory named ‘Avengers’ already exists.”, “developerMessage”: “A directory named ‘Avengers’ already exists. If you have a stale local cache, please expire it now.”, “moreInfo”: “https://www.stormpath.com/docs/api/errors/40924”} Learn more at Stormpath.com
![Page 66: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/66.jpg)
Avoid sessions when possibleAuthenticate every request if necessaryStateless
Authorize based on resource content, NOT URL!
Use Existing Protocol:Oauth 1.0a, Oauth2, Basic over SSL only
Custom Authentication Scheme:Only if you provide client code / SDKOnly if you really, really know what you’re doing
Use API Keys instead of Username/Passwords
Learn more at Stormpath.com
![Page 67: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/67.jpg)
HTTP Authentication Schemes
• Server response to issue challenge:
WWW-Authenticate: <scheme name> realm=“Application Name”
• Client request to submit credentials:
Authorization: <scheme name> <data>
Learn more at Stormpath.com
![Page 68: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/68.jpg)
401 vs 403
• 401 “Unauthorized” really means Unauthenticated
“You need valid credentials for me to respond to this request”
• 403 “Forbidden” really means Unauthorized
“I understood your credentials, but so sorry, you’re not allowed!”
Learn more at Stormpath.com
![Page 69: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/69.jpg)
API Keys
• Entropy• Password Reset• Independence• Speed• Limited Exposure• Traceability
Learn more at Stormpath.com
![Page 71: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/71.jpg)
• IDs should be opaque• Should be globally unique• Avoid sequential numbers
(contention, fusking)• Good candidates: UUIDs, ‘Url64’
Learn more at Stormpath.com
![Page 75: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/75.jpg)
Server (initial response): ETag: "686897696a7c876b7e”
Client (later request):If-None-Match: "686897696a7c876b7e”
Server (later response):304 Not Modified
Learn more at Stormpath.com
![Page 77: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/77.jpg)
Use HTTP Redirects
Create abstraction layer / endpoints when migrating
Use well defined custom Media Types
Learn more at Stormpath.com
![Page 78: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/78.jpg)
IT’S CODING TIME!!!
• Let’s build a JAX-RS REST App!
• git clone https://github.com/stormpath/todos-jersey.git
Learn more at Stormpath.com
![Page 79: REST API Design for JAX-RS And Jersey](https://reader038.vdocument.in/reader038/viewer/2022102722/554f592cb4c905524c8b53a9/html5/thumbnails/79.jpg)
.com
• Free for any application• Eliminate months of development• Automatic security best practices
Sign Up Now: Stormpath.com
Les Hazlewood | @lhazlewood