Upgrade to Pro — share decks privately, control downloads, hide ads and more …

REST API design and construction with Java EE -...

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

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.

Avatar for Vineet Reynolds

Vineet Reynolds

January 30, 2014

More Decks by Vineet Reynolds

Other Decks in Programming

Transcript

  1. REST API DESIGN AND CONSTRUCTION WITH JAVA EE PAGES FROM

    MY WORK DIARY By / Vineet Reynolds L P @VineetReynolds Senior Software Engineer JBoss Developer Experience, Red Hat
  2. ABOUT THE SPEAKER Engineer in the JBoss Developer Experience team

    Currently, contributor to : JBoss Forge 1.x and 2.0 AngularJS scaffolding for JBoss Forge JDF quickstarts TicketMonster Others: Arquillian (GlassFish, WebLogic container adapters)
  3. AGENDA A 10 minute guide to REST JPA and JAX­RS

    Writing a data­driven REST API with JPA and JAX­RS Composite keys Cyclic and bi­directional relationships Lazy­fetching Class hierarchies (java.sql.Date) Bean Validation and error reporting
  4. A 10 MINUTE GUIDE TO REST Note ­ this is

    really a 10 minute guide. This is not a deep­dive into . Roy Fielding's doctoral dissertation
  5. WHAT IS REST ? REST = REpresentational State Transfer It

    is an architectural style. It describes the design of a hypermedia system (the web). It intends to conceptualize how a well designed Web application should behave.
  6. EXAMPLES G E T / e v e n t

    s returns all Events. G E T / e v e n t s / 1 returns the Event with ID 1. P O S T / e v e n t s creates a new Event. P U T / e v e n t s / 1 updates the Event. D E L E T E / e v e n t s / 1 deletes the Event.
  7. EXAMPLES Assuming G E T / e v e n

    t s / 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. { " n a m e " : " J U D C O N " , " s e s s i o n s " : [ { " n a m e " : " A e r o g e a r " } , { " n a m e " : " I n f i n i s p a n " } , { " n a m e " : " O p e n S h i f t " } , { " n a m e " : " W i l d F l y " } ] }
  8. JAX-RS + JPA + EJB : THE BASICS Let's expose

    a JPA entity as a REST resource. @ E n t i t y p u b l i c c l a s s E v e n t { @ I d @ G e n e r a t e d V a l u e ( s t r a t e g y = G e n e r a t i o n T y p e . A U T O ) p r i v a t e L o n g i d = n u l l ; @ V e r s i o n p r i v a t e i n t v e r s i o n = 0 ; @ C o l u m n p r i v a t e S t r i n g n a m e ; / / G e t t e r s , S e t t e r s , e q u a l s ( ) a n d h a s h C o d e ( ) . . . }
  9. JAX-RS + JPA + EJB : THE BASICS CREATING NEW

    EVENTS P O S T / s i m p l e ­ e v e n t / r e s t / e v e n t s H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 C o n t e n t ­ T y p e : a p p l i c a t i o n / j s o n ; c h a r s e t = U T F ­ 8 . . . { " n a m e " : " J U D C O N " } H T T P / 1 . 1 2 0 1 C r e a t e d L o c a t i o n : h t t p : / / l o c a l h o s t : 8 0 8 0 / s i m p l e ­ e v e n t / r e s t / e v e n t s / 1 . . .
  10. JAX-RS + JPA + EJB : THE BASICS FETCHING ALL

    EVENTS G E T / s i m p l e ­ e v e n t / r e s t / e v e n t s H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 A c c e p t : a p p l i c a t i o n / j s o n , t e x t / p l a i n , * / * . . . H T T P / 1 . 1 2 0 0 O K C o n t e n t ­ T y p e : a p p l i c a t i o n / j s o n . . . [ { " i d " : 1 , " v e r s i o n " : 0 , " n a m e " : " J U D C O N " } ]
  11. JAX-RS + JPA + EJB : THE BASICS FETCHING ONE

    SPECIFIC EVENT G E T / s i m p l e ­ e v e n t / r e s t / e v e n t s / 1 H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 A c c e p t : a p p l i c a t i o n / j s o n , t e x t / p l a i n , * / * . . . H T T P / 1 . 1 2 0 0 O K C o n t e n t ­ T y p e : a p p l i c a t i o n / j s o n . . . { " i d " : 1 , " v e r s i o n " : 0 , " n a m e " : " J U D C O N " }
  12. JAX-RS + JPA + EJB : THE BASICS UPDATING AN

    EVENT P U T / s i m p l e ­ e v e n t / r e s t / e v e n t s / 1 H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 A c c e p t : a p p l i c a t i o n / j s o n , t e x t / p l a i n , * / * . . . { " i d " : 1 , " v e r s i o n " : 0 , " n a m e " : " J U D C O N I n d i a " } H T T P / 1 . 1 2 0 4 N o C o n t e n t . . .
  13. JAX-RS + JPA + EJB : THE BASICS DELETING AN

    EVENT D E L E T E / s i m p l e ­ e v e n t / r e s t / e v e n t s / 1 H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 A c c e p t : a p p l i c a t i o n / j s o n , t e x t / p l a i n , * / * . . . H T T P / 1 . 1 2 0 4 N o C o n t e n t . . .
  14. COMPOSITE KEYS ARE NOT FUN Addressability suffers. Matrix parameters will

    help with composite keys. / / K e y f o r e v e n t = n a m e , l o c a t i o n G E T / e v e n t s ; n a m e = J U D C O N ; l o c a t i o n = I n d i a But ... They're not a standard. Just a W3C design note. Lack of client support (but improving). Among popular JS libraries, only Dojo, AngularJS, Backbone.js has support. If cheap, establish a mapping scheme for composite keys.
  15. CREATE A NEW EVENT P O S T / b

    i d i ­ e v e n t / r e s t / e v e n t s H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 A c c e p t : a p p l i c a t i o n / j s o n , t e x t / p l a i n , * / * . . . { " n a m e " : " J U D C O N " , " l o c a t i o n " : " B a n g a l o r e " } H T T P / 1 . 1 2 0 1 C r e a t e d L o c a t i o n : h t t p : / / l o c a l h o s t : 8 0 8 0 / b i d i ­ e v e n t / r e s t / e v e n t s / 1 . . .
  16. FETCH AN EXISTING EVENT G E T / b i

    d i ­ e v e n t / r e s t / e v e n t s / 1 H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 A c c e p t : a p p l i c a t i o n / j s o n , t e x t / p l a i n , * / * . . . H T T P / 1 . 1 2 0 0 O K C o n t e n t ­ T y p e : a p p l i c a t i o n / j s o n . . . { " i d " : 1 , " v e r s i o n " : 0 , " n a m e " : " J U D C O N " , " l o c a t i o n " : " B a n g a l o r e " , " s e s s i o n s " : [ ] }
  17. CREATE A NEW SESSION P O S T / b

    i d i ­ e v e n t / r e s t / s e s s i o n s H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 A c c e p t : a p p l i c a t i o n / j s o n , t e x t / p l a i n , * / * { " s e s s i o n N a m e " : " A e r o g e a r " , " s p e a k e r " : " S e b a s t i a n " , " e v e n t " : { " i d " : 1 , " v e r s i o n " : 0 , " n a m e " : " J U D C O N " , " l o c a t i o n " : " B a n g a l o r e " , " s e s s i o n s " : [ ] } } H T T P / 1 . 1 2 0 1 C r e a t e d L o c a t i o n : h t t p : / / l o c a l h o s t : 8 0 8 0 / b i d i ­ e v e n t / r e s t / s e s s i o n s / 2 . . .
  18. FETCH THE NEWLY CREATED SESSION G E T / b

    i d i ­ e v e n t / r e s t / s e s s i o n s / 2 H T T P / 1 . 1 H o s t : l o c a l h o s t : 8 0 8 0 A c c e p t : a p p l i c a t i o n / j s o n , t e x t / p l a i n , * / * . . . H T T P / 1 . 1 5 0 0 I n t e r n a l S e r v e r E r r o r C o n t e n t ­ T y p e : t e x t / h t m l ; c h a r s e t = u t f ­ 8 J B W E B 0 0 0 0 6 5 : H T T P S t a t u s 5 0 0 ­ o r g . c o d e h a u s . j a c k s o n . m a p . J s o n M a p p i n g E x c e p t i o f a i l e d t o l a z i l y i n i t i a l i z e a c o l l e c t i o n o f r o l e : c o m . e x a m p l e . b i d i e v e n t . m o d n o S e s s i o n ( t h r o u g h r e f e r e n c e c h a i n : c o m . e x a m p l e . b i d i e v e n t . m o d e l . S e s s i o n [ " e
  19. WHAT JUST HAPPENED? E v e n t . s

    e s s i o n s is lazily fetched. During serialization, the proxy does not find an active session. Let's try and solve this crudely, using eager fetching ... { " i d " : 2 , " v e r s i o n " : 0 , " s e s s i o n N a m e " : " A e r o g e a r " , " s p e a k e r " : " S e b a s t i a n " , " e v e n t " : [ { " i d " : 2 , " v e r s i o n " : 0 , " s e s s i o n N a m e " : " A e r o g e a r " , " s p e a k e r " : " S e b a s t i a n " , " e v e n t " [ { " i d " : 2 , " v e r s i o n " : 0 , " s e s s i o n N a m e " : " A e r o g e a r " , " s p e a k e r " : " S e b a s t i a n " , " e v e n t " . . . / / T h i s n e v e r t e r m i n a t e s
  20. HOW DO YOU SOLVE THIS ? If you can, do

    not expose collection members of JPA entities directly. Use sub­resources for dependent collections (1:M). Use a mapping layer. Create Representation classes to map JPA object graphs. The mappings translate RESTful actions into operations in the domain model. Or, use different representations of the same JPA entity for different operations (not a good idea). One to create an entity with collections, another to update only the entity. Model collections as a separate resource. Makes sense for M:N relationships.
  21. JAVA.SQL.* HATES YOU Consider the following During serialization, s t

    a r t T i m e 's type is j a v a . s q l . T i m e . Given a value of 2:00 PM IST, the field will be serialized as { " s t a r t T i m e " : " 1 4 : 0 0 : 0 0 " } . When deserializing back, { " s t a r t T i m e " : " 1 9 7 0 ­ 0 1 ­ 0 1 T 1 4 : 0 0 : 0 0 . 0 0 0 + 0 5 : 3 0 " } should be supplied. @ T e m p o r a l ( T e m p o r a l T y p e . T I M E ) j a v a . u t i l . D a t e s t a r t T i m e ;
  22. JAVA.SQL.* HATES YOU Before, 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 in ISO8601 formats (like time values for Dates).
  23. JAVA.SQL.* HATES YOU Lessons learnt ­ Be aware of the

    actual types of the objects during serialization and deserialization. Constrain the actual types and hence the serializers/deserializers used. When writing custom serializers, design them for class hierarchies. Think of the equals() contract, but for serialized forms. And of course, avoid java.util.Date/Calendar. Use specific types in Joda­Time and eventually JSR­310 (Java 8). Using a specific type binds a serializer + deserializer to the field.
  24. BEAN VALIDATION AND VIOLATION REPORTING Responses for Constraint violation errors

    on JPA entities are not standardized. By default, HTML responses will be provided if no E x c e p t i o n M a p p e r s exist for C o n s t r a i n t V i o l a t i o n E x c e p t i o n s . Bean Validation for request parameters is available out­of­ the­box, but requires activation. RESTEasy has one format, Jersey has another.