Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 8,843 views

2012 Java Developer Day

2012 Java Developer Day

Statistics

Views

Total Views
8,843
Views on SlideShare
8,566
Embed Views
277

Actions

Likes
15
Downloads
178
Comments
1

7 Embeds 277

http://www.ctyeh.me 170
http://ctyeh.me 63
http://ctyeh.wordpress.com 38
http://twitter.com 2
https://twitter.com 2
http://translate.googleusercontent.com 1
http://cloud.feedly.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

    • 葉政達 Cheng Ta Yeh12年7月19日星期四
    • Integrate Spring MVC with RequireJS & Backbone.js & Spring Data JPA12年7月19日星期四
    • 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日星期四
    • Once upon a time...12年7月19日星期四
    • The Dream...12年7月19日星期四
    • Start lean, get bigger later12年7月19日星期四
    • 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日星期四
    • Outlines • Front-end development • Integrate Backbone with Spring MVC • Diving into Spring Data JPA12年7月19日星期四
    • Front-end development12年7月19日星期四
    • Problems ... • Few conventions and standards12年7月19日星期四
    • 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日星期四
    • Problems ... • Between server-side and client-side, we need efficient tools.12年7月19日星期四
    • Backbone.js12年7月19日星期四
    • Who Use Backbone.js Basecamp Mobile12年7月19日星期四
    • 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日星期四
    • 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日星期四
    • Backbone Model • Data storage and business logic • Changes on the attributes will fire `change` event • Talks to server uses RESTful JSON12年7月19日星期四
    • My Real Case12年7月19日星期四
    • My Real Case12年7月19日星期四
    • Backbone Sample Code ItemDetailView ItemView Use window.ItemModel = Backbone.Model.extend(); ItemModel12年7月19日星期四
    • 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日星期四
    • That’s It?12年7月19日星期四
    • How to build loose coupling scalable applications?12年7月19日星期四
    • 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日星期四
    • Real life application • Lots of Screens • Lots of Modules • Complex dependency12年7月19日星期四
    • RequireJS12年7月19日星期四
    • 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日星期四
    • RequirJS AMD Loader Other AMD loaders: • curl • lsjs • Dojo 1.7 and MooTools 2.0 each have their own12年7月19日星期四
    • AMD APIs • Facilitating module definition • define (module_id?, dependencies?, factory); • Handling dependency async loading • require (dependencies?, callback);12年7月19日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • http://s.ctyeh.me/LGW3ug Integrates Backbone.js with Spring MVC12年7月19日星期四
    • 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日星期四
    • 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日星期四
    • Spring MVC as REST Server12年7月19日星期四
    • 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日星期四
    • 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日星期四
    • Rarely Need Custom Parsers• Automatically registers several converters.12年7月19日星期四
    • Controller Methods’ Parameters and Return Values ween s bet ing MVC he b ullet Spr T del & bon e Mo Back12年7月19日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • Diving into Spring Data JPA12年7月19日星期四
    • Layer Architecture Backbone.js requireJS HTML Spring MVC Domain Model Spring Data JPA12年7月19日星期四
    • Between Spring MVC and Spring Data JPA • Data conversion • Design concept12年7月19日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • Let’s Begin With Plain JPA12年7月19日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • Refactoring to Spring Data JPA12年7月19日星期四
    • The Repository (DAO) public interface ItemRepository extends JpaRepository<Item, Long> {     List<Item> findBySite(Site site); }12年7月19日星期四
    • 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日星期四
    • Strategy: CREATE • Split your query methods by prefix and property names.12年7月19日星期四
    • 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日星期四
    • 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日星期四
    • 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日星期四
    • Put It All Together Backbone.js requireJS Spring MVC Spring Data JPA12年7月19日星期四
    • The End & Thank You http://about.me/ctyeh12年7月19日星期四