Sunday, 27 November 2016

Communication between Backbone Views

There are few ways to communicate between two backbone views and model.
Consider an application contains Menu view and you want to update the application area based on the menu selection.
For example, consider an e-commerce application which contains the following views.
1. MenuView
2. Recharge View
3. Shopping View
4. Book Ticket View

For this the very basic approach or the easiest way is that creating the object for all other three views in MenuView. But by doing this, all views are tightly coupled with one another.
To overcome this we’re going to use Event aggregator pattern. 
Backbone provides Router concept for event aggregator.

In index.html we’ve included all the html templates.

index.html


 


After that, related Backbone view files are created with the basic information.

MenuView.js

var MenuView = Backbone.View.extend({
 
 model : new MenuModel(),
 initialize : function(){
  
 },
 events : {
  
 },
 render : function(){
  var menuTemplate = _.template($('#menu-template').html());
  this.$el.html(menuTemplate(this.model.toJSON()));
  return this;
 }
});


RCView.js

var RCView = Backbone.View.extend({
 el: '#contentArea',
 initialize : function(){
  
 },
 
 events : {
  'click #rcSubmitButton':'doOnRCSubmitButton'
 },
 render : function(){
  var rcTemplate = _.template($('#recharge-template').html());
  this.$el.html(rcTemplate(null));
  return this;
 },
 
 doOnRCSubmitButton : function(){
  alert("RC click!!");
 }
});
As of now, views are containing only the render part which renders the corresponding template into the application area.

We’ve defined three links in the index.html menu area. For every menu item, there are independent actions. The event should be passed to corresponding views without any dependency. For this purpose we’ve created the router in the main.js file. Once the routes and its functions are defined, for all the menu selection it’ll redirected to its route.

main.js

$(document).ready(function(){
 var menuView = new MenuView();
 menuView.setElement($('#menuArea'));
 menuView.render();
 new MyRouter();
 Backbone.history.start();
});

var MyRouter = Backbone.Router.extend({
 routes : {
  "recharge":"onRecharge",
  "bookticket" : "onBookTicket",
  "shop":"whileShopping"
 },

 viewFactory : function(){
  return{
   rcView : typeof rcView == 'undefined' ? new RCView() : rcView,
   ticketView : typeof ticketView == 'undefined' ? new TicketView() : ticketView,
   shopView : typeof shopView == 'undefined' ? new ShopView() : shopView
  };
  
 },
 onRecharge : function(){
  this.viewFactory().rcView.render();
 },
 
 onBookTicket : function(){
  this.viewFactory().ticketView.render();
 },
 
 whileShopping : function(){
  this.viewFactory().shopView.render();
 }
});



You can download this working sample in this Github URL.

Reference for event aggregator pattern :  http://martinfowler.com/eaaDev/EventAggregator.html

Wednesday, 16 November 2016

Spring Singleton vs Prototype

                            Bean scopes will be specified by the scope attribute of the <bean/> element. We will see the example as we go down to this article. Spring bean has 5 different scopes which we listed below,
  1. Singleton
  2. Prototype 
  3. Global
  4. Session
  5. Application
When it comes to standalone application, we don't have the last three scopes that are applicable only for web applications. Here, In this article, we'll just look at the first two, singleton and the prototype.

                            Singleton beans are created by the spring container only once which means you will have only one instance of the bean through out our application. Prototype beans are right opposite to this. It's a multiton bean which means more than one instance can be created. When we call the getBean method of ApplicationContext or inject in other beans, we will get a new instance of it. Let's see this by an example,

ApplicationContext.xml
 <?xml version="1.0" encoding="UTF-8"?>  
 <beans xmlns="http://www.springframework.org/schema/beans"  
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  

   <bean id="student" class="com.studentact.model.Student" scope="prototype" destroy-method="destroy" init-method="init"/>  

   <bean id="studentDao" class="com.studentact.dao.StudentDaoImpl" destroy-method="destroy" init-method="init">  
     <property name="student" ref="student"/>  
   </bean>  

   <bean id="studentServiceProxy" class="com.studentact.proxy.StudentServiceProxy" init-method="init" destroy-method="destroy">  
     <property name="student" ref="student"/>  
   </bean>  

   <bean id="studentService" class="com.studentact.service.StudentService" destroy-method="destroy" init-method="init">  
      <property name="studentServiceProxy" ref="studentServiceProxy"/>  
      <property name="studentDao" ref="studentDao"/>  
   </bean>  

 </beans>  

We can see that the scope of student bean is specified as prototype and other beans don't have this scope attribute which means they are all singleton.
Let's say StudentServiceProxy's method getVOCTopStudent gets student data from some web service and assign them in student object. Likewise StudentDaoImpl's method getGovtStudent gets the from DB and assign them in student object. StudentService will call these methods and store the return student object in a list as below,

StudentService.java
 public class StudentService implements IStudentService {  
      private IStudentDao studentDao;  
      private IStudentServiceProxy studentServiceProxy;  
      public IStudentDao getStudentDao() {  
           return studentDao;  
      }  
      public void setStudentDao(IStudentDao studentDao) {  
           this.studentDao = studentDao;  
      }  
      public IStudentServiceProxy getStudentServiceProxy() {  
           return studentServiceProxy;  
      }  
      public void setStudentServiceProxy(IStudentServiceProxy studentServiceProxy) {  
           this.studentServiceProxy = studentServiceProxy;  
      }  
      @Override  
      public List<Student> getTopStudents() {  
           List<Student> topStudents = new ArrayList<Student>();  
           topStudents.add(studentDao.getGovtStudent());  
           topStudents.add(studentServiceProxy.getVOCTopStudent());  
           return topStudents;  
      }  
      public void destroy(){  
           System.out.println("detroy method of StudentService");  
      }  
      public void init(){  
           System.out.println("init method of StudentService");  
      }  
      //Other operations go here  
 }  

We can use the below code to test whether the list has same student object or different objects.
 StudentService studentService = (StudentService) applicationContext.getBean("studentService");  
 List<Student> students = studentService.getTopStudents();  
 System.out.println(students);  
 Student aStudent = null;  
 for(Student student:students){  
      if(null == aStudent){  
           aStudent = student;                      
      } else if(student == aStudent) {  
           Assert.assertFalse(true);  
      }  
 }  
We mentioned student bean scope as prototype and injected it in other beans like studentDao and studentServiceProxy. So the resultant list will have different student objects. If it’s a singleton, then both studentDao and studentServiceProxy will have the same object and the resultant list will have the same student objects.

Initialization and destruction:
                            If you assign any method to init-method attribute of bean element, the method will be called after the bean properties is set, but before the bean is completely initialized. We can use this, when we need to initialize something like opening file, creating or checking the database connections. This method will be called by spring container regardless of singleton or prototype beans. 
                            But destroy-method will be called by the spring container, only if the bean is singleton. It will never be called in case of the bean scope is prototype. The methods which we assign to this destroy-method attribute will be called by the spring container, before the object is destroyed. But we have to use this AbstractApplicationContext interface and call the registerShutdownHook method as we used in below test class,
 public class StudentServiceTest extends BaseTest {  
      protected AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");  
      @Test  
      public void testGetTopStudents() {  
           applicationContext.registerShutdownHook();  
           StudentService studentService = (StudentService) applicationContext.getBean("studentService");  
           List<Student> students = studentService.getTopStudents();  
           System.out.println(students);  
           Student aStudent = null;  
           for(Student student:students){  
                if(null == aStudent){  
                     aStudent = student;                      
                } else if(student == aStudent) {  
                     Assert.assertFalse(true);  
                }  
           }  
      }  
 }  
                            The methods we use as init-method and destroy-method should not accept any arguments, but can be defined to throw exceptions. We can define initialization and destruction methods in all beans with same method signature and can specify it in default-init-method and default-destroy-method of beans elements, instead of specifying it in all the bean elements. Also please have a look at other beans attribute like default-autowire-candidates and default-lazy-init.

                            Singleton bean objects will be created when application context is loaded. Though it’s not used anywhere. Prototype scoped bean objects will always be created when it’s needed. But if we want singleton objects to be created when it’s needed, we can use the lazy-init attribute of bean element. 

Please do more examples like singleton-scoped bean has prototype-scoped beans and vice versa.

Click here to download this example project from GitHub.