Your SlideShare is downloading. ×
  • Like
Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA

  • 9,609 views
Published

2012 Java Developer Day

2012 Java Developer Day

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
9,609
On SlideShare
0
From Embeds
0
Number of Embeds
7

Actions

Shares
Downloads
187
Comments
1
Likes
15

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. 葉政達 Cheng Ta Yeh12年7月19日星期四
  • 2. Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA12年7月19日星期四
  • 3. Who Am I • 葉政達 Cheng-Ta Yeh • Co-founder of Humus Technology (優沃科技) • Founder of GOGOSamba (Android app & Calorie Management Service) • Speaker of TWJUG 2012/5 • Speaker of Google Developer Day 2008 • Speaker of Java One Tokyo 2005 • 12 years Java related experiences12年7月19日星期四
  • 4. Once upon a time...12年7月19日星期四
  • 5. The Dream...12年7月19日星期四
  • 6. Start lean, get bigger later12年7月19日星期四
  • 7. What Am I Going To Talk About? Building a Scalable Single-Page app from front-end to backend. erview Ov My Les sons L earne d12年7月19日星期四
  • 8. Outlines • Front-end development • Integrate Backbone with Spring MVC • Diving into Spring Data JPA12年7月19日星期四
  • 9. Front-end development12年7月19日星期四
  • 10. Problems ... • Few conventions and standards12年7月19日星期四
  • 11. Problems ... • jQuery is cool, it has plenty of selectors and callbacks, but ... ily We have to tie d ata to the DOM heav , ca llbacks’ callbacks’... We have to deal with ts...... to manipulate DO M, animations, even http://mysistersjar.wordpress.com/2008/04/02/wanted-moving-boxes/12年7月19日星期四
  • 12. Problems ... • Between server-side and client-side, we need efficient tools.12年7月19日星期四
  • 13. Backbone.js12年7月19日星期四
  • 14. Who Use Backbone.js Basecamp Mobile12年7月19日星期四
  • 15. Backbone Components Template Render DOM UI Use DOM events Hash tag View Talks Model / Data Router Fragment routing Model events Collection sync Source Morning hashchange Dispatching routers History Event12年7月19日星期四
  • 16. Backbone View • Owns a DOM element • Talks to its model or collection • Observe model events (change,...) • Handle user’s inputs (DOM events)12年7月19日星期四
  • 17. Backbone Model • Data storage and business logic • Changes on the attributes will fire `change` event • Talks to server uses RESTful JSON12年7月19日星期四
  • 18. My Real Case12年7月19日星期四
  • 19. My Real Case12年7月19日星期四
  • 20. Backbone Sample Code ItemDetailView ItemView Use window.ItemModel = Backbone.Model.extend(); ItemModel12年7月19日星期四
  • 21. Backbone Sample Code ItemDetailView window.itemModel.save( {name: this.$(#input).val()} );change name change event window.ItemDetailView = Backbone.View.extend({ ItemView events: { "click #item_input": "doEdit" }, initialize: function() {window.ItemView = Backbone.View.extend({ this.model.bind(change, this.setTitle, this); initialize: function() { }, this.model.bind(change, this.setItemName, this); setTitle: function() { }, $(this.el).html(this.model.get(name)); setItemName: function() { }, $(this.el).html(this.model.get(name)); }, //....}); //.... }); window.ItemModel = Backbone.Model.extend(); ItemModel12年7月19日星期四
  • 22. That’s It?12年7月19日星期四
  • 23. How to build loose coupling scalable applications?12年7月19日星期四
  • 24. Apply “Module Pattern”, but ... var testModule = (function () { var _counter = 0; //private variable function privateMethod(){ //..... } return { incrementCounter: function () { return __counter++; }, resetCounter: function () { console.log( "counter value prior to reset: " + _counter ); _counter = 0; } }; })();12年7月19日星期四
  • 25. Real life application • Lots of Screens • Lots of Modules • Complex dependency12年7月19日星期四
  • 26. RequireJS12年7月19日星期四
  • 27. Standards for Modules • CommonJS Modules 1.1.1 • Targeted at server-side environments • AMD (Asynchronous Module Definition) • A format for writing modular javascript in the browser on JS m m Co12年7月19日星期四
  • 28. RequirJS AMD Loader Other AMD loaders: • curl • lsjs • Dojo 1.7 and MooTools 2.0 each have their own12年7月19日星期四
  • 29. AMD APIs • Facilitating module definition • define (module_id?, dependencies?, factory); • Handling dependency async loading • require (dependencies?, callback);12年7月19日星期四
  • 30. Defining Backbone’s Classes into Modules define(function () {   return new Backbone.Model.extend({   // ...   }); }); ./models/itemModel.js define([../models/itemModel],function (itemModel) {   return new Backbone.View.extend({ model: itemModel; render: function(){ this.model.fetch(); //... }, // ...   }); }); ./views/itemView.js12年7月19日星期四
  • 31. Your App’s Entry Point require.config({ // ..... }) ./views/itemView.js require([jquery,app], function ($,app) { app.initial(); }); Load Load ./main.js define([../views/itemView],function (itemView) {   return { 1. Set up requireJS configuration. 2. Start to run your app. Execute initial: function(){ // Do initialization..... // Render first App’s screen. itemView.render(); 1. As a top level container. }, 2. Initialize your app. 4. Render your first screen.   }; }); ./app.js12年7月19日星期四
  • 32. Set up your HTML Page <!DOCTYPE html> <html> <head> <title>jQuery+RequireJS Sample Page</title> <script data-main="scripts/main" src="scripts/require-jquery.js"></script> </head> <body> <h1>Single Page Application Sample Page</h1> <div id=”app_body”> Your DOM elements will be inserted dynamically. </div> </body> </html>12年7月19日星期四
  • 33. Using requireJS Optimizer • Optimizing all the CSS and JS files in your project > r.js -o app.build.js ({ appDir: "../", baseUrl: "scripts", dir: "../../appdirectory-build", modules: [ { name: "main" } ] }) app.build.js12年7月19日星期四
  • 34. Tips & Lessons Learned • Prevent Memory Leaks • All models, collections, views implement destructors. • Create an abstraction layer for those destructors. Backbone.View.prototype.close = function () { console.log("Closing a View...”); if (this.beforeClose) { this.beforeClose(); } this.remove(); this.unbind(); };12年7月19日星期四
  • 35. Tips & Lessons Learned • Package Pattern • File structure • src/ui/widgets.js < Just like Java’s package • src/ui/widgets/ooxx.js define([./widgets/selectors, ./widgets/slider, ./widgets/button],         function(selectors, slider, button) {     return {         ToolSelector: selectors.ToolSelector,         OptionSelector: selectors.OptionSelector,         Slider: slider.Slider,         Button: button.Button     }; }); src/ui/widgets.js12年7月19日星期四
  • 36. http://s.ctyeh.me/LGW3ug Integrates Backbone.js with Spring MVC12年7月19日星期四
  • 37. Backbone Model & RESTful JSON Inteface C itemModel.save(); • POST /items R itemModel.fetch(); • GET /items[/{id}] U itemModel.save(); • PUT /items/{id} D itemModel.clear(); • DELETE /items/{id} * POST or PUT base on the id value of Model. * Global ajax error handler is useful12年7月19日星期四
  • 38. Define RESTful Interface • Nouns: URI, addressed resources • /sites • /sites/{id} • /sites/{id}/items • /sites/{id}/items/{todoId}. Find your resources BEFORE designing Backbone Models and The REST Triangle Spring MVC Controller methods.12年7月19日星期四
  • 39. Spring MVC as REST Server12年7月19日星期四
  • 40. Receiving Values in the URL Path • The RESTful way • @PathVariable in Controller methods @RequestMapping(value="/sites/{siteId}/item/{itemId}",method= {RequestMethod.PUT}) public @ResponseBody UIJentoItem updateModule(@PathVariable long siteId,@PathVariable Long itemId,@Valid @RequestBody UIJentoItem item) { UIJentoItem uiObject = new UIJentoItem(); //...... return uiObject; }12年7月19日星期四
  • 41. Sending HTTP Response Codes to Clients AbstractController • @ResponseStatus extends • @ExecptionHandler. Controller Controller Controller A B C public class AbstractController { @ExceptionHandler(UserNotSigninException.class) @ResponseStatus(UNAUTHORIZED) // HTTP 401 public @ResponseBody UIMessage handleUserNotSigninException(UserNotSigninException e, HttpServletResponse response) { return UIMessage.fail("err.data.usernotsignin"); } @ExceptionHandler(DataNotFoundException.class) @ResponseStatus(NOT_FOUND) // HTTP 404 public @ResponseBody UIMessage handleDataNotFoundException(DataNotFoundException e, HttpServletResponse response) { return UIMessage.fail("err.data.notfound"); } @ExceptionHandler(Exception.class) @ResponseStatus(INTERNAL_SERVER_ERROR)// HTTP 505 public @ResponseBody UIMessage handleException(Exception e, HttpServletResponse response) { return UIMessage.fail("err.internal"); } }12年7月19日星期四
  • 42. Rarely Need Custom Parsers• Automatically registers several converters.12年7月19日星期四
  • 43. Controller Methods’ Parameters and Return Values ween s bet ing MVC he b ullet Spr T del & bon e Mo Back12年7月19日星期四
  • 44. Parameters and Return Values • Domain Entity Controller @RequestMapping(value="/sites/{id}/items",method= {RequestMethod.GET}) @ResponseStatus(OK) public @ResponseBody List<Item> getItems(@PathVariable long id) { //.... Out return itemList; } @RequestMapping(value="/sites/{id}/items",method= {RequestMethod.POST}) @ResponseStatus(OK) public @ResponseBody String createItem( @PathVariable long id,@RequestBody Item item) { //.... In } Controller12年7月19日星期四
  • 45. Parameters and Return Values • DTO (Data Transfer Object) Controller @RequestMapping(value="/sites/{id}/items",method= {RequestMethod.GET}) @ResponseStatus(OK) public @ResponseBody List<DTOItem> getItems(@PathVariable long id) { //.... Out return itemList; } @RequestMapping(value="/sites/{id}/items",method= {RequestMethod.POST}) @ResponseStatus(OK) public @ResponseBody String createItem( @PathVariable long id,@RequestBody DTOItem item) { //.... } In Controller12年7月19日星期四
  • 46. Parameters and Return Values • JSONObject Controller import net.sf.json.JSONObject; @RequestMapping(value="/sites/{id}/items",method= {RequestMethod.GET}) @ResponseStatus(OK) public @ResponseBody List<JSONObject> getItems(@PathVariable long id) { //.... Out return itemList; } @RequestMapping(value="/sites/{id}/items",method= {RequestMethod.POST}) @ResponseStatus(OK) public @ResponseBody String createItem( @PathVariable long id, @RequestBody JSONObject itemJSON) { //.... In } Controller12年7月19日星期四
  • 47. Parameters and Return Values • Domain Entity • Pros: No extra effort for creation and maintenance & readable • Cons: Might waste extra bandwidth for transferring • DTO • Pros: readable • Cons: Extra efforts for maintenance, transferring from domain object to DTO. • JSONObject • Pros: No extra effort for creation and maintenance • Cons: Not readable, Unit testing is mandatory, transferring from domain entity to JSONObject!12年7月19日星期四
  • 48. Unit Test for Spring MVC Controller • mockito - Mocking framework • http://code.google.com/p/mockito/ • Spring MVC Test Support • https://github.com/SpringSource/spring-test-mvc12年7月19日星期四
  • 49. Unit Test for Spring MVC Controller public class ItemControllerTest { ItemController private static MockMvc mockMvc; use use private UserSerivce userService; private ItemSerivce itemService; ItemService UserService @Before public void setUp() { userService = mock(UserService.class); itemService = mock(ItemService.class); Create a mock service Setup mockMVC for target Controller mockMvc = standaloneSetup(new ItemController()).build(); // userService.getCurrentUser() will be called in ItemController for URI "/sites/{id}/items" when(userService.getCurrentUser()).thenReturn(new User()); Item item = new Item(); item.setName("This is item name"); when(itemService.getItem(any(Long.class))).thenReturn(item); } tell mocks when some calls happened return something @Test public void getItemsBySiteId() throws Exception { mockMvc.perform(get("/sites/1/items")) .andExpect(status().isOk()) Your URI .andExpect(content().type("application/json;charset=UTF-8")) .andExpect(jsonPath("$.[0].id").value(1)) .andExpect(jsonPath("$.[0].itemName").value("This is item name")) ;12年7月19日星期四
  • 50. Diving into Spring Data JPA12年7月19日星期四
  • 51. Layer Architecture Backbone.js requireJS HTML Spring MVC Domain Model Spring Data JPA12年7月19日星期四
  • 52. Between Spring MVC and Spring Data JPA • Data conversion • Design concept12年7月19日星期四
  • 53. Between Spring MVC and Spring Data JPA • Data conversion • Using Factory Method in Domain entity or separate Factory classes. DTO JSONObject Spring MVC Domain Object Spring Data JPA12年7月19日星期四
  • 54. Between Spring MVC and Spring Data JPA • Data conversion • Using Factory Method in Domain entity or separate Factory classes. @Entity public class Item implements Serializable { private String name; //..... public JSONObject toJSON(){ DTO JSONObject JSONObject object = new JSONObject(); //Converting Item to JSONObject. object.put("name", this.name); return object; } Domain Object public static Item fromJSON(JSONObject json){ //Converting JSONObject to Item. return item; } }12年7月19日星期四
  • 55. Between Spring MVC and Spring Data JPA • Design concept • Domain driven design in Domain Layer • Entity • Service • Value Object • Aggregate • Repository Spring Data borrows this concept.12年7月19日星期四
  • 56. Spring Data Overview • Abstracts away basic data management concepts • Support for RDB, NoSQL: Graph, Key-Value and Map-Reduce types. • Current implementations • JPA/JDBC • Hadoop • GemFire • REST • Redis/Riak • MongoDB • Neo4j • Blob (AWS S3, Rackspace, Azure,...) • Plan for HBase and Cassandra12年7月19日星期四
  • 57. Let’s Begin With Plain JPA12年7月19日星期四
  • 58. The Domain Entities @Entity public class Site { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; // … methods omitted } @Entity public class Item {   @Id @GeneratedValue(strategy = GenerationType.AUTO) 1 private Long id; Site * Item @ManyToOne private Site site;      // … methods omitted }12年7月19日星期四
  • 59. The DAO @Repository public class TodoDAO {"   @PersistenceContext   private EntityManager em;     @Override   @Transactional   public Item save(Item item) {       if (item.getId() == null) {       em.persist(item);       return item;     } else {       return em.merge(item);     }   }     @Override   public List<Item> findBySiteId(Long siteId) {       TypedQuery query = em.createQuery("select i from Item a where i.site.id = ?1", Item.class);     query.setParameter(1, siteId);       return query.getResultList();   } }12年7月19日星期四
  • 60. The Domain Service @Service @Transactional(readOnly = true) class ItemListServiceImpl implements ItemListService {     @Autowired   private ItemDAO itemDAO;     @Override   @Transactional   public Item save(Item item) {       return itemDAO.save(item);   }   @Override   public List<Item> findItems(Long siteId) {       return itemDAO.findBySiteId(siteId);   }   }12年7月19日星期四
  • 61. Refactoring to Spring Data JPA12年7月19日星期四
  • 62. The Repository (DAO) public interface ItemRepository extends JpaRepository<Item, Long> {     List<Item> findBySite(Site site); }12年7月19日星期四
  • 63. The Service @Service @Transactional(readOnly = true) class ItemListServiceImpl implements ItemListService {     @Autowired   private ItemRepository repository;     @Override   @Transactional   public Item save(Item item) {       return repository.save(item);   }   @Override   public List<Item> findItems(Site site) {       return repository.findBySite(site);   }   }12年7月19日星期四
  • 64. Strategy: CREATE • Split your query methods by prefix and property names.12年7月19日星期四
  • 65. Strategy: USE_DECLARED_QUERY • @Query public interface UserRepository extends JpaRepository<User, Long> { @Query("select u from User u where u.emailAddress = ?1") User findByEmailAddress(String emailAddress); } From Spring Data JPA 1.1.0, native SQL is allowed to be executed. Just set nativeQuery flag to true. But, not support pagination and dynamic sort12年7月19日星期四
  • 66. Strategy: USE_DECLARED_QUERY • @Modify @Modifying @Query("update User u set u.firstname = ?1 where u.lastname = ?2") int setFixedFirstnameFor(String firstname, String lastname); @Modifying @Query("update User u set u.firstname = :firstName where u.lastname = :lastName") int setFixedFirstnameFor(@Param("firstName") String firstname, @Param("lastName") String lastname);12年7月19日星期四
  • 67. Configurations in Spring 3.1 <!-- Activate Spring Data JPA repository support --> <jpa:repositories base-package="com.humus.domain.repo" /> <!-- Declare a JPA entityManagerFactory --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true" /> </bean> </property> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop> <prop key="hibernate.hbm2ddl.auto">create</prop> </props> </property> <property name="packagesToScan"> <list> <value>com.humus.domain.entity</value> </list> </property> </bean> No persistence.xml any more~12年7月19日星期四
  • 68. Put It All Together Backbone.js requireJS Spring MVC Spring Data JPA12年7月19日星期四
  • 69. The End & Thank You http://about.me/ctyeh12年7月19日星期四