Tuesday, April 23, 2013

SaaS(Multitenant) Application Design Best Practices

Overviw: Now-a-days with the increasing popularity and penetration of the cloud, SaaS (Software as a Service) is rapidly becoming the preferred software delivery model for organizations across the world - software buyers as well as vendors. In SaaS model, software is centrally hosted by the vendor (service provider) in the cloud and accessed by the users over the Internet using a thin client e.g. a web-browser or a smartphone. There are many business benefits of adopting SaaS. For the customer, it means reduced cost of ownership, fast deployment, no maintenance headaches, and a smaller learning curve leading to a higher adoption rate in the user community. For the vendor, it means reduced cost of customer acquisitions, faster sales cycles, more upsell opportunities and an easier rollout of new features.

SaaS model has emerged to give companies a cheaper alternative to in-house solutions: Software-as-a-Service (SaaS). A client pays a per-user fee for a pre defined period of time to access the solution. In exchange, the software resides in one central location, managed outside of each client. All clients access the same software, though certain features may be enabled or disabled for specific clients depending on what they choose to pay for. As the software is upgraded, all clients receive the upgrade without any physical intervention on their end. Hardware, networking, even disaster recovery are all handled without any staffing costs.

At the core of most reliable SaaS offerings is a well-designed, secure, fault-tolerant database design. Perhaps more so than for their enterprise counterparts, SaaS databases must be able to keep problems isolated as much as possible. While it is true that a database crash could bring down an enterprise application, causing a company to lose productivity until the issue is remedied, a crash of a poorly-designed SaaS database could cause an outage for multiple companies, possibly causing all of them to lose faith in the product and take their business elsewhere. On the other hand, if reliability is favored at the expense of performance, companies may not feel that the application can scale to their needs and will refuse to sign up in the first place. Finally, as a SaaS database will contain data from multiple companies, it is imperative to design it in a secure, isolated fashion. Failing to ensure that no client can see another's data could spell the end for a SaaS offering.
From an engineering perspective also, SaaS is a great way to build and deliver software. It is a perfect fit for software delivery teams that have adopted an agile development model. As the software is centrally hosted, you can:
  • Deliver new features to your customers faster than before
  • Receive user feedback and implement changes in real time
  • Fix production issues quickly
  • No need to worry about any environment dependencies, different software versions, their upgrades, etc.
  • Focus on single application instance instead of 100 customers with 100 instances in 100 different location.
  • You can reach to new clients from all over the world.
So, excited about building a SaaS application? OK, let's see what you must know for building SaaS software. The following are the key architecture/design blocks of a SaaS application:

Multi-tenancy: Multi-tenancy is the ability to serve different customers from a shared hardware or software instance. It gives you economics of scale by catering to a growing customer base without any significant increase in your resources. From a software design perspective, multi-tenancy influences all aspects of software including database model, application logic, user interface, etc. At the database level, multi-tenancy can be achieved either by storing data for each customer in a separate schema or by partitioning the customer data by adding a customer qualifier field to all entities (i.e., Customer ID should be part of all tables as a primary key field). The second approach is straightforward and can be implemented very easily. It may suffice for systems that do not have a large volume of data. However, for systems that deal with large data volume it is best to store each customer's data in a schema of its own. In both cases, you must spend some time building data access frameworks to hide the underlying data partitioning scheme from developers. This not only makes your developers' lives easier but also helps you to migrate from one scheme to another when the need arises. Mainly you can design your SaaS application in any one approach from below list:
  • Shared Application with Shared DB (True SaaS but Maintainance and Security problem)
  • Shared Application with Shared DB and separate Schema (Maintainance problem)
  • Shared Application with Separate DB (Recomended for big applications)
  • Separate Application with Separate DB (This is not an multitenant application)
Scalability: Well, scalability is important for any software system worth its salt. However, it becomes extremely important for a SaaS system because any performance impact directly affects all your customers. If one of your customers starts uploading large volumes of data, it should not start impacting other customers. Database multi-tenancy discussed above takes care of scalability from the database operations side. To ensure that your application servers are scalable, you must ensure that your applications are cluster enabled and you can add cluster nodes as your data volumes grow. It is best to make all your application services stateless so that you do not need to worry about session persistence/replication, etc. Another design principle to follow, while designing scalable systems, is modularizing your services. This not only makes your system more fault-tolerant but also allows you to scale the different components based on the number of requests each component receives. Another important tool you should exploit is cache. In a SaaS system there is a lot of data that is common across customers (e.g. country codes). Such meta data can be cached and be made accessible across the system. This will avoid unnecessary database operations and boost system performance.

Security: As the data for all customers is stored in the same data-store, it is very important to ensure that one customer's data is not accessible by another. This means deploying several levels of defenses. For instance:
  • At the database level, you must encrypt all confidential data - preferably by using a unique key for each customer.
  • At the network level, you must ensure that all the communication happens on a secured channel (e.g., HTTPS should be used for all requests from the browser to application server).
  • At the application level, you must ensure that all the workflows authorize the user before granting access to any data. Authorization must be performed on the server side for each request rather than depending on the client for it. Also, ensure that your website conforms to security best practices.
  • All the application layers(Controller, Service, DAO, Client etc) should be well secured.
Customizability: If you have been in the enterprise application space for more than a few months, you would know that no two customers are the same. Each customer has different requirements for data modeling, UI workflows, integration with legacy systems, etc. As a SaaS system developer, you should realize this early and ensure that the system provides customization capability for all important elements, e.g., the UI look and feel, data interchange formats, definition of entities and business logic, as well. When designing your data model, think how your users can extend it. When designing your business logic, think how the user can alter it. It is a good practice to model business logic as a template that can be changed by your users. When designing your UI look and feel, think of different themes, logos, icons, etc. Customization becomes very important if your business model involves partners to resell your solution; they'll probably want to rebrand your solution and customize the workflows.

Saturday, November 12, 2011

Introduction to X-Path


XPath

XPath is a language for finding information in an XML document. XPath uses path expressions to navigate in XML documents. XPath is a W3C recommendation


The basic XPath syntax is similar to filesystem addressing. If the path starts with the slash / , then it represents an absolute path to the required element.
 
/AAA
Select the root element AAA

     <
AAA>
          <bbb>        
     
AAA>
 
/AAA/CCC
Select all elements CCC which are children of the root element AAA
    
          <
CCC/>      
          <
CCC/>
     
 
/AAA/DDD/BBB
Select all elements BBB which are children of DDD which are children of the root element AAA
      
               <
BBB/>
      

Question:
  1. What will be the XPath to select the all the parenet elements?
  2. Which of the elements will be selected by XPath - /parent/child


If the path starts with // then all elements in the document which fulfill following criteria are selected.
 
//BBB
Select all elements BBB

          <
BBB/>
          
          <
BBB/>
          
               <
BBB/>
             
                    <
BBB/>
                    <
BBB/>
              
 
//DDD/BBB
Select all elements BBB which are children of DDD

               <
BBB/>
          
                    <
BBB/>
                    <
BBB/>
     

Question:
1) Which XPath will select all grandchild elements?


The star * selects all elements located by preceeding path
 
/AAA/CCC/DDD/*
Select all elements enclosed by elements /AAA/CCC/DDD
     
                    <
BBB/>
                    <
BBB/>
                    <
EEE/>
                    <
FFF/>         
     
 
/*/*/*/BBB
Select all elements BBB which have 3 ancestors

                    <
BBB/>
                    <
BBB/>
  
                    <
BBB/>
                    <
BBB/>
 
                    <
BBB>
                         
                    
BBB>
   

 
//*
Select all elements

     <
AAA>
          <
XXX>
               <
DDD>
                    <
BBB/>
                    <
BBB/>
                    <
EEE/>
                    <
FFF/>
               
DDD>
          
XXX>
          <
CCC>
               <
DDD>
                    <
BBB/>
                    <
BBB/>
                    <
EEE/>
                    <
FFF/>
               
DDD>
          
CCC>
          <
CCC>
               <
BBB>
                    <
BBB>
                         <
BBB/>
                    
BBB>
               
BBB>
          
CCC>
     
AAA>

Question:
  1. Which XPath will select all the occupants?
  2. Which XPath will select both parent and single elements?

Expresion in square brackets can further specify an element. A number in the brackets gives the position of the element in the selected set. The function last() selects the last element in the selection.

 
/AAA/BBB[1]
Select the first BBB child of element AAA
    
          <
BBB/>
 
 
/AAA/BBB[last()]
Select the last BBB child of element AAA

          <
BBB/>
     


Attributes are specified by @ prefix.
 
//@id
Select all attributes @id

          
id = "b1"/>
          
id = "b2"/>
 


 
//BBB[@id]
Select BBB elements which have attribute id

          <
BBB id = "b1"/>
          <
BBB id = "b2"/>
 
 
//BBB[@name]
Select BBB elements which have attribute name
    
          <
BBB name = "bbb"/>
          
 
//BBB[@*]
Select BBB elements which have any attribute
     
          <
BBB id = "b1"/>
          <
BBB id = "b2"/>
          <
BBB name = "bbb"/>
              
 
//BBB[not(@*)]
Select BBB elements without an attribute

          <
BBB/>
     

Question:
  1. How to select the second grandchild element?
  2. How to select apartment (use @ in the XPath)?

Values of attributes can be used as selection criteria. Function normalize-space removes leading and trailing spaces and replaces sequences of whitespace characters by a single space.
 
//BBB[@id='b1']
Select BBB elements which have attribute id with value b1
   
          <
BBB id = "b1"/>
          
 
//BBB[@name='bbb']
Select BBB elements which have attribute name with value 'bbb'
         
          <
BBB name = "bbb"/>
     
 
//BBB[normalize-space(@name)='bbb']
Select BBB elements which have attribute name with value bbb, leading and trailing spaces are removed before comparison
   
          <
BBB name = " bbb "/>
          <
BBB name = "bbb"/>
     

Question:
1) How to select elements where age is 10?
2) How to select the element where age is 10 and name contais “1.”?

Function count() counts the number of selected elements
 
//*[count(BBB)=2]
Select elements which have two children BBB
            
          <
DDD>
                            
          
DDD>
          

 
//*[count(*)=2]
Select elements which have 2 children

          <
DDD>
                      
          
DDD>
          <
EEE>
                          
          
EEE>
     

 
//*[count(*)=3]
Select elements which have 3 children

     <
AAA>
          <
CCC>
 
          
CCC>
          
     
AAA>

Question:
  1. Select a parent which have 4 children.

Function name() returns name of the element, the starts-with function returns true if the first argument string starts with the second argument string, and the contains function returns true if the first argument string contains the second argument string.
 
//*[name()='BBB']
Select all elements with name BBB, equivalent with //BBB

               <
BBB/>
               <
BBB/>
               <
BBB/>
          
          
               <
BBB/>
               <
BBB/>
 
 
//*[starts-with(name(),'B')]
Select all elements name of which starts with letter B

     
          <
BCC>
               <
BBB/>
               <
BBB/>
               <
BBB/>
          
BCC>
          
               <
BBB/>
               <
BBB/>
          
          <
BEC>
               
               
          
BEC>
     

 
//*[contains(name(),'C')]
Select all elements name of which contain letter C
 
          <
BCC>
     
          
BCC>
     
          <
BEC>
               <
CCC/>
               
          
BEC>
     



The string-length function returns the number of characters in the string.
 
//*[string-length(name()) = 3]
Select elements with three-letter name

     <
AAA>
        
          
          <
CCC/>
          
          
     
AAA>
 
//*[string-length(name()) < 3]
Select elements name of which has one or two characters

          <
Q/>
          
          <
BB/>
          
 
 
//*[string-length(name()) > 3]
Select elements with name longer than three characters

          
          <
SSSS/>
          
          
          <
DDDDDDDD/>
          <
EEEE/>
     

Question
  1. select all the child and grandchild elements (use name to check)?


Several paths can be combined with | separator.
 
//CCC | //BBB
Select all elements CCC and BBB

          <
BBB/>
          <
CCC/>
          
               <
CCC/>
 
     
 
/AAA/EEE | //BBB
Select all elements BBB and elements EEE which are children of root element AAA

     
          <
BBB/>
     
          <
EEE/>
     
 
/AAA/EEE | //DDD/CCC | /AAA | //BBB
Number of combinations is not restricted

     <
AAA>
          <
BBB/>
          
          
               <
CCC/>
          
          <
EEE/>
     
AAA>

Question:
1. Select all the grandchild and child elements (use | operator).


The descendant axis contains the descendants of the context node; a descendant is a child or a child of a child and so on; thus the descendant axis never contains attribute or namespace nodes
 
/AAA/BBB/descendant::*
Select all descendants of /AAA/BBB

 
               <
DDD>
                    <
CCC>
                         <
DDD/>
                         <
EEE/>
                    
CCC>
               
DDD>
   
 

 
//CCC/descendant::*
Select all elements which have CCC among its ancestors

                         <
DDD/>
                         <
EEE/>
                    
          
               <
DDD>
                    <
EEE>
                         <
DDD>
                              <
FFF/>
                         
DDD>
                    
EEE>
               
DDD>
          
     


 
//CCC/descendant::DDD
Select elements DDD which have CCC among its ancestors

                    
                         <
DDD/>
 
          
               <
DDD>
                    
                         <
DDD>
                              
                         
DDD>
                    
               
DDD>
          
     


Question
1. Search from apartment to select all the grandchild elements.

The parent axis contains the parent of the context node, if there is one.
 
//DDD/parent::*
Select all parents of DDD element

     
          <
BBB>
               
                    <
CCC>
                         
                         
                    
CCC>
               
          
BBB>
          <
CCC>
               
                    <
EEE>
                         
                              
                         

                    
EEE>
               
          
CCC>
     



The ancestor axis contains the ancestors of the context node; the ancestors of the context node consist of the parent of context node and the parent's parent and so on; thus, the ancestor axis will always include the root node, unless the context node is the root node.
 
/AAA/BBB/DDD/CCC/EEE/ancestor::*
Select all elements given in this absolute path

     <
AAA>
          <
BBB>
               <
DDD>
                    <
CCC>
                         
                         
                    
CCC>
               
DDD>
          
BBB>
            
          

     
AAA>

 
//FFF/ancestor::*
Select ancestors of FFF element

     <
AAA>
          
              

          <
CCC>
               <
DDD>
                    <
EEE>
                         <
DDD>
                              
                         
DDD>
                    
EEE>
               
DDD>
          
CCC>
     
AAA>




The following-sibling axis contains all the following siblings of the context node.
 
/AAA/BBB/following-sibling::*


          

          <
XXX>
               
 
          
XXX>
          <
CCC>
               
          
CCC>
     

 
//CCC/following-sibling::*



               <
DDD/>
          
 
                    <
FFF/>
                    <
FFF>
                         
                    
FFF>
               
       



The preceding-sibling axis contains all the preceding siblings of the context node
 
/AAA/XXX/preceding-sibling::*



     
          <
BBB>
               
               
          
BBB>
 

 
//CCC/preceding-sibling::*



     
          <
BBB>
               
               
          
BBB>
          <
XXX>
               
                    <
EEE/>
                    <
DDD/>
               
          
XXX>
 



The following axis contains all nodes in the same document as the context node that are after the context node in document order, excluding any descendants and excluding attribute nodes and namespace nodes.
 
/AAA/XXX/following::*

 
          <
CCC>
               <
DDD/>
          
CCC>
     

 
//ZZZ/following::*



 
               <
FFF>
                    <
GGG/>
               
FFF>
          
          <
XXX>
               <
DDD>
                    <
EEE/>
                    <
DDD/>
                    <
CCC/>
                    <
FFF/>
                    <
FFF>
                         <
GGG/>
                    
FFF>
               
DDD>
          
XXX>
          <
CCC>
               <
DDD/>
          
CCC>
     



The preceding axis contains all nodes in the same document as the context node that are before the context node in document order, excluding any ancestors and excluding attribute nodes and namespace nodes
 
/AAA/XXX/preceding::*



     
          <
BBB>
               <
CCC/>
               <
ZZZ>
                    <
DDD/>
               
ZZZ>
          
BBB>
 

 
//GGG/preceding::*



     
          <
BBB>
               <
CCC/>
               <
ZZZ>
                    <
DDD/>
               
ZZZ>
          
BBB>
          
               
                    <
EEE/>
                    <
DDD/>
                    <
CCC/>
                    <
FFF/>
                    



The descendant-or-self axis contains the context node and the descendants of the context node
 
/AAA/XXX/descendant-or-self::*



          <
XXX>
               <
DDD>
                    <
EEE/>
                    <
DDD/>
                    <
CCC/>
                    <
FFF/>
                    <
FFF>
                         <
GGG/>
                    
FFF>
               
DDD>
          
XXX>
          
               
          

     

 
//CCC/descendant-or-self::*


          
               <
CCC/>
               
                    <
CCC/>
 
          <
CCC>
               <
DDD/>
          
CCC>
     



The ancestor-or-self axis contains the context node and the ancestors of the context node; thus, the ancestor-or-self axis will always include the root node.
 
/AAA/XXX/DDD/EEE/ancestor-or-self::*



     <
AAA>
          
          <
XXX>
               <
DDD>
                    <
EEE/>
                    
               
DDD>
          
XXX>
 
     
AAA>

 
//GGG/ancestor-or-self::*



     <
AAA>
 
          <
XXX>
               <
DDD>
 
                    <
FFF>
                         <
GGG/>
                    
FFF>
               
DDD>
          
XXX>
 
     
AAA>



The div operator performs floating-point division, the mod operator returns the remainder from a truncating division. The floor function returns the largest (closest to positive infinity) number that is not greater than the argument and that is an integer.The ceiling function returns the smallest (closest to negative infinity) number that is not less than the argument and that is an integer.
 
//BBB[position() mod 2 = 0 ]
Select even BBB elements

          <
BBB/>
          
          <
BBB/>
          
          <
BBB/>
          
          <
BBB/>
 


Question
  1. Find out child elements whose age is matching with single element.

    Sample XML
     
    <apartment>
      <parent name = "top1">
        <child name="1" age="30">
          <grandchild name="1.1" age="10"></grandchild>
          <grandchild name="1.2" age="15"></grandchild>
        </child>
        <child name="2" age="35">
          <grandchild name="2.1" age="13"></grandchild>
          <grandchild name="2.2" age="16"></grandchild>
        </child>
        <child name="3" age="38">
          <grandchild name="3.1" age="10"></grandchild>
          <grandchild name="3.2" age="12"></grandchild>
        </child>
      </parent>
      <parent name = "top2">
        <child name="4" age="30">
          <grandchild name="4.1" age="3"></grandchild>
          <grandchild name="4.2" age="4"></grandchild>
        </child>
        <child name="5" age="35">
          <grandchild name="5.1" age="5"></grandchild>
          <grandchild name="5.2" age="6"></grandchild>
        </child>
        <child name="6" age="38">
          <grandchild name="6.1" age="10"></grandchild>
          <grandchild name="6.2" age="8"></grandchild>
        </child>
        <child name="7" age="38">
          <grandchild name="7.1" age="10"></grandchild>
          <grandchild name="7.2" age="9"></grandchild>
          <grandchild name="7.3" age="1"></grandchild>
        </child>
      </parent>
      <single name = "sing1" age='38'></single>  
    </apartment>