Showing posts with label Software Application Design. Show all posts
Showing posts with label Software Application Design. Show all posts

Design Considerations for Audit Trail Implementation

Auditing the operations in any application is a very common requirement for security and auditing purpose. Auditing can be done at various levels with varying level of details. Overall prime requirements for Audit Trail are:
  • Collect enough information to determine, 
    • Who has done the changes, 
    • What are the changes, 
    • When these changes have been done, Locale etc
    • What user scenario was in action, i.e. the operation context
  • To capture all user actions, even if some of these are not reaching to DB or would be interacting with external services directly (rare, but happens in some cases)
  • Successful and unsuccessful logons or other security related operations
  • Management of collected audit data, which could be very large. 
  • Search operations on collected data
  • Display the collected data to Users in presentable format as and when demanded 

Considering above requirements, there are various design approaches to implement the audit trail in system. Few of these are given below (considering a JEE application, however, many of these are generic)

  1. Implement DB triggers to capture any change in data states and log in audit tables
  2. Log audit data in business services, which means collecting the required data in each business service operation and log it using some abstract Audit service to some data store
  3. Using generic logging framework like Log4J to log the auditing information to desired format and data store and later parse these logs to extract the required data
  4. Interceptors based approach to intercept all operations, collect the data and log it through Audit service. Here interceptors can be of DAO layer interceptors like Hibernate Interceptors or Service level interceptor using AOP.

All of these approaches have their own pros and cons. As obvious, one approach can not be fit for all. Application state, project requirements and scope can define the right set of implementation. So lets discuss the pros and cons of each of these approaches to understand it more.

Database triggers

Database triggers can do really well and nothing can escape from the triggers. Once these are set carefully on all levels, all changes are bound to pass through these and hence will be captured in audit tables.

Pros:

  • Whether it is simple user operation, or any change is being done by DB admin; all kind of changes will be captured by triggers.
  • A comparatively simple approach, in aspect, that no code change is required and it can be implemented directly at database level without disturbing the code.

Spring RoutingDataSource to Work with Multiple DataSources

Finally back to blogging. It was a long journey to get ready, pick the pen (i.e. computer) and start writing again. Writing is a matter of habit.

Today we are going to discuss about using multiple data sources with Spring Transaction Management. Scenario is,

  • Application is having lot of legacy code
  • Application needs to work with more than one databases
  • There are some legacy methods in application which are supposed to work with any one of the database depending upon use case. Same method could be invoked with different data source context for other transaction.
  • Application is using Spring Transaction Management
  • Requirement of Spring Transaction Management is to declare data sources and associated transaction manager with application context (1 to 1 relation)

What would be the initial design considerations. 
  • Define all required data sources in application context
  • Define corresponding transaction managers too
  • Use any of the Persistent Template to implement the DAOs.
  • Define desired transaction behavior on service methods

We are done with basic infrastructure code. In above steps, missing part is how to tell application code about which data source to be used from multiple data sources defined in context. It can be done by specifying the specific transaction manager (related to desired data source) with Service transactional attributes. Transaction manager can be defined either at class level or at method level. Or a good approach could be to use Transactional advice and define the transaction manager in context configuration with a pattern to identify the methods. 

A general workflow would be; whenever any service method is called using Spring Framework, Spring will see if there is any transaction proxy available for that method. If yes, transaction proxy will get invoked. It will work with defined transaction manager and will start a new or use existing transaction (based on transaction attributes). It will also try to attach the connection with the current transaction (thread local based implementation). Connection will be retrieved from the data source which is associated with the transaction manager (defined in context). This connection will be linked with current transaction as synchronized resource. Please note, that connection may be attached lazily in case of 'LazyConnectionDataSourceProxy'. In this way, Spring enables the scenario to use multiple data sources in application based on specified transaction manager.  All the methods invoked during the service call, or from nested methods will go to the database which is associated with current transaction manager (and the data source).

What is Functional Programming - II

In previous article, we have discussed about basic concept of Functional Programming in brief. Continuing with same, today we shall discuss more about it.

Although there are many concept in Functional Programming which are different than Imperative programming style. However, following four points are very important and differentiating factors. These are:

  • True Functions
  • First Class Functions
  • High Order Functions
  • Focus on result, rather than on structure and procedure to do it

True functions, we have already discussed in previous article. These are the functions without any side effect and is a main building block for functional programming. These makes the parallel and concurrent programming easier.

First Class functions are the functions which can be presented anywhere in a program, like a variable. These can be passed as argument to any function, can be returned as value from function, can be assigned to a variable or can be stored in a data structure. These functions are the basic building block in functional programming. Java like languages does not have this feature. One possible similarity can be an anonymous class only, which can be passed as argument to any function in Java, but that is also quite limited in scope.

High Order functions are the functions which can take First Class functions as parameter or can return these as return value.

Combining above two type of function, we can write very dynamic programs. Imagine, a variable is passed to a function with another logic definition and hence added all possible dynamic behavior in same method. We can do this in Java also, by passing some commands or executors etc. But it is not that flexible. In Java, anyhow, we need to write a class even when we only need an behavior. Functional programming allows to define the functions directly without thinking about class structure and allow to pass these to other methods. A much easier and quick implementation.  

Fourth and important point is that functional programming advocates the focus on result, rather than on procedure of implementation or structure. Following this concept, Functional Programming languages provides a lot of abstract implementations for various repetitive tasks, like for iterating over collection, for parsing and reading any element from XML etc. In a language like Java, our focus used to be on good Object structure and the implementation logic. While iterating over a list, we plan whether we should use index based iteration or should use iterator. For XML parsing, we plan which parser we should use and so on. However, functional programming languages hide these implementation details from the programmer and provides high level syntax for performing such functions. Now if implementation is hidden from programmer, and is being taken over by language itself, it means that any programmer can implement the program much faster in functional programming. However, it means we are banking upon language capability to make a good decision or logic to perform these actions.

Doesn't this feel like loosing control to the language. Like in Java, we have control over every piece of code. We can open the source code and can see how List.add is working. If we are not happy with it, let us extend the list and write a custom logic to add the items in List. Hence a complete control what we want to do. So is that OK to loose all control to language and just use the high level language syntax. A big doubtful point  from a programmer working with Java kind of language, hard to digest. What if language is not perfect, or having bugs.

However, let us see the positive side of this approach. If programming language is providing the abstraction for such repetitive tasks and implementation logic, it means lesser coding for a feature implementation. Less coding also means lesser issues in implementation and more outcome, more focus on business code and hence the result. Further, in most of the cases, implementation done by language can be much better than ours. We may not be expert in all logic implementation. And as and when language implementation will improve its implementation logic for functions, our program will be benefited automatically. Any improvement in code means improvement for our application also without making any change.   Eventually languages will try to have better and better implementation with almost zero bugs and better performance. Hence if language implementation is that good, do we really need to have control on these basic logic implementation. Shouldn't we focus our energy on writing something more meaningful for business i.e. the business application functionality. Lets put all our efforts for business features.

For a Java programmer, the program structure given by functional programming languages is hard to digest. It is a altogether new structure with much different organization of objects, and classes etc. But if we think, it is just another way of writing the program and it is good if we are getting more work done by writing lesser piece of code. For example, if we are interacting with computer or machines, we always want to get more work done by machine in smallest possible instructions. If we need to send an email, we always like a single command like 'Send Email to ABC with following contents', rather than to write a complete low level program to interact with mail server. Functional languages are only that kind of step for programming approach. These can make programming much easier task if used properly. And eventually we can reach to a point when one line of instruction will perform all required functions, for which we used to write a whole 2000 line class in Java. Actually Java is also evolving in that direction with many new utilities, AOP, lambda expressions etc. So this will be the requirement of future and is worth to embrace.

I hope it will help. We shall keep discussing more concept about Functional Programming. 

What is Functional Programming

Today we shall discuss about Functional Programming in brief. Functional Programming is a different paradigm than Imperative style programming. Imperative programming includes change in states with functions, however, Functional programming advocates functions without any side effect, i.e. no effect on any of the state. This is a big difference in programming approach with many other implementation level differences.

Let us understand bit in detail, what is Functional Programming and how is that different than Imperative Programming.

For development using Java like language, we mostly follow Imperative style programming. Where a Class like data structure contains some state or represents state. Functions are implemented to work on this state. Functions make changes in states based on current state or passed parameters. End result is, once functions are executed, the shared states may be changed.

Functional Programming supports the concept of Pure functions. It states that function implementation should not have any side effects. It means that functions will not modify any state. These will only act on the parameters and will return the result. No state will be changed anywhere else. This also means that does not matter, how many times, you call these functions; if parameters are same then result will always be same.  This is one of the biggest difference in approach.

Let us discuss, how does this difference matter. With above understanding for Imperative style programming, if we want to support concurrent execution, we can apply concurrent programming concepts using threads and locks to safeguard the simultaneous update of states by multiple threads. We use different kind of locks, synchronized blocks etc to support the concurrent programming. Although with mature API support like java.util.concurrent, concurrent programming is getting much simpler now; but still it needs lot of care and knowledge to implement a perfect program. Moreover, we understand many scenarios only when program actually runs on multiple processors and scenarios changed with number of concurrent streams. So testing the concurrent programs is hard.

However, what if there is no shared state to modify through functions like in 'Functional Programming'. Then there is nothing to safeguard in concurrent or parallel processing. There is no overhead of locks and hence the concurrent scenarios testing. Results will always be same from a function irrespective of whether it is being executed by one or multiple threads by multiple processors. Functions just act on the passed parameters and return the result. Isn't that a big relief. Certainly, it can make parallel programming a lot more easier. Programmers can focus on business logic implementation instead of managing the concurrent programming scenarios. Further, it is entirely feasible and easy to process different functions in parallel on parallel processing units. Different implementation functions can be submitted to different processors. As there is no shared state to access or modify, so there is nothing for the processors to compete for. These can work parallel in harmony. So with proper designing, results can be utilized later from different processing units to form the final result.

From above discussion, it would be becoming clearer that Functional Programming is having edge when it comes to parallel processing and make it comparatively very easy to manage. This is one of the major difference in programming style and the benefits. That is why Functional Programming languages like Scala are getting popular. Why not, demand is for parallel processing after all.

There are many other differences also. Like, Functional Programming supports the concept of 'First Class' and 'Higher Order functions'. 'First Class' functions are, which can be presented in a program anywhere like any other first class member can present, for example anywhere like a Number type member, or as parameter or return value of a function. High order functions are, which can take other functions as parameter or can return these as return value.

We shall discuss  more for these implementation level differences and other concepts with coming articles. 

Design for Server Side Pagination

In previous article, we have discussed about various type of pagination and that how these work. We have seen that in most of the scenarios, server side pagination is better than client side pagination. Client side pagination can be used only if data, i.e. the number of records, are limited. In that case, we can consider to load all data on client side and may divide the data in pages while showing on screen. However, if data is large, we would prefer the server side pagination.

In this article, we shall discuss how we can design the server side pagination component. At first, let us summarize the requirements for server side pagination.

Requirements
  • Data is large enough to support the needs of server side pagination implementation, as discussed in previous article.
  • Only current page of data (or may be 1-2 more pages) should be loaded from data repository (DB), so we want to reduce the need to load large amount of data from data repository. The same or lesser amount of data should be loaded on client side.
  • User can navigate  through the pages using next, previous, first or last page kind of actions. 
  • User can also perform 'sort' and 'search' kind of operation on the data.  
With above requirements, let us design the Pagination Component now. 

Analysis and HLD

After analysis of above requirements, following are the main design requirements:
  1. Client - Any software program which needs to retrieve the large amount of data, but want to present this to end user (or application) in pages. Client can be a UI which is showing listing of data to end user, or may be a command line tool to show the data. 
  2. We need a component which 
    1. Can maintain the state for each client. Various states needs to be maintained are: 
      1. Current Page for which data is returned last time to client
      2. Number of records to be returned for one page
      3. Various data retrieval attributes required for fetching the page data from Data Repository, using data access component. These can be 
        1. Criteria to select the desired data 
        2. Sort criteria
        3. Search criteria
        4. etc
    1. Can work as a channel to retrieve the data from repository using data access components
    2. Can provide utility methods to client for accessing the data pages based on user requests like, next | previous | first | last | specific page number
    3. Can provide methods to client using which client can change various data retrieval attributes. This is to support the scenario, when end user change the search or sort criteria at UI.
  1. We need an abstract data access layer (can call it pagination data provider), which can understand the  language of pages and can return the filtered, and sorted data for specified page. 
  2. This component can be named as 'Pagination Manager' 

Create your own Hybrid Project Life Cycle

There are various project life cycle approaches in use for projects. All of these have their own pros and cons. So process should be picked after analyzing these pros and cons from project perspective. But it might be possible that none of the existing approaches are actually catering to all of your project or Organization requirements. Hence, it is also very much possible to mix more than one approaches, may be in different phases of project or in different activities. Many of the projects are executed with hybrid approaches. To understand this, let us first understand about most popular approaches in brief.

Waterfall Approach
It is one of the most used approaches for projects till now. It is in use since long. The approach suggests to plan for the whole project requirements in one go i.e.

  • Collect all requirements
  • Analyze and freeze the requirements
  • Do analysis and design for complete functions
  • Plan and Schedule the tasks for whole project
  • Complete the construction
  • Execute the testing of all functions
  • Fix the issues
  • Make the project live
  • Perform Maintenance activities
So you would see, it is a sequential approach to perform and complete all activities for a project going through conception, Initiation, Analysis, Design, Construction, Testing, Deployment to production and then Maintenance. Waterfall model comes from manufacturing and construction industries initially. Then it later adopted for software development also. And it actually worked well initially. It performs well for projects with comparatively stable requirements. 

Points in favor of this approach are that it give emphasis to complete the work for each phase with utmost perfection. It asks to design the system perfectly in design phase itself to avoid any restructuring later which can cost lot of money due to changes at large scale. It advocates to close the requirements in first phase itself, to avoid the changes later in project life. Due to these reasons, it results into a very stable project life cycle, easy to predict - plan - and budget. So it is good for budgeting also. It emphasize of documentation for each phase of project, and hence helps in creating the rich knowledge base. This remove the risk of loss of knowledge if any key member or members leave the project.

What is Pagination?

In many use cases, there is a generic requirement to show the list of data to user. User should be able to see the list of data, to perform search and sorting operations on this data. User should also be able to navigate to any data record anytime. This requirement demands to fetch the large amount of data from database and list it on UI for the user. Then this data can be filtered using various search criteria and can be sorted also depending upon user input. Approach to fetch the data can be different depending upon architecture and implementation of application, like data can be fetched directly from database in case of embedded applications, or 2 tier architecture or through some services in 3 tier architecture. The process flow used to be like:
  • Take inputs from user what kind of data she wants to see
  • Interact with database directly or through service (depending upon architecture) to get this data 
  • Display this data to user
  • Filter or sort the data depending upon user action on UI
For example, open google.com. Search for any word. You will get search results in list form, and various page number given at the bottom of the page to navigate to different pages. 

Now if there are thousands of data records in database for given inputs, all of this data can not be shown to user in one go. Showing this on same screen will be having problems like: 
  • It will not be a good experience for user, as she will need to scroll up and down a lot and information will be unreadable practically.
  • It will not be good for performance of application, as application may get out of memory or may face slow response due to large amount of data in memory, or data transfer from database.
To solve first problem mentioned above, we need to divide the data in small parts to show the user one part at a time. For example, we can divide data in parts having 50 records each. Then each of the parts can be shown to user one by one. Once user see first part, she can request for next or previous part and hence corresponding 50 records can again be shown on screen to user. These parts are called pages, and this process is called pagination - which divides the large data in pages (having limited records) and show these to user.

How to Manage Inter-Project Dependencies using Jenkins


We have explained about Use of Jenkins and its Configuration in one of the previous blog. Here we shall discuss, how Jenkins can be used to work with inter-dependent projects. Managing the CI environment with multiple inter-dependent projects is quite important, as it is general scenario with projects.

If there are multiple projects having dependencies, then requirements would be:
  1. If Project A is dependent on Project B, then a successful build of Project B should trigger the build for Project A also. In generic words, the build of current project should trigger the build for other dependent projects also. It is required to ensure the integrity of whole project dependency chain after any change.
  2. The dependent projects should be able to pick the latest jars from Projects on which these are dependent. Different mechanism can be used for this. One of these could be to modify the build system of every dependent project to pick the required jars from downstream project
  3. This way, finally whole project chain will be built again on change in any of the project (from down to up)

Now, how we can achieve these requirements in Jenkins. Here we are describing this with an example.
  • Suppose there are three projects, Project 1, Project 2 and Project 3. 
  • Project 1 is dependent on Project 2. Project 2 is dependent on Project 3.
  • Assumption is that build of every project produce the distribute-able jar etc in a specific folder
  • Now update the 'build' for Project 3 in a way, so that before compiling its own code base, it picks the output of Project 2 build from its output folder and synchronize it in its own library folders. Of course, assumptions are to have a fixed project structure (preferably relative directory structure).
  • Similarly update the 'build' for Project 2 in a way, that before compiling its own code base, it picks the output of Project 1 'build' from its output folder and synchronize it in own library folders.
  • Create a Job in Jenkins for Project1, as described with previous article
  • Add post build actions to this job to trigger the build of Project2
  • Create a Job for Project2
  • Add post build actions to this job to trigger the build of Project 3
  • Create job for Project3
  • Using this setup, whenever Project1 will be build, it will trigger the job for Project2
  • Project 2 will pick the depdencies from Project1 output folder and will build its own code base. Build will place the output files in some specific folder.
  • Similarly Project3 build will be triggered and it will pick the dependencies from Project2 output folders

Using this approach, we shall be able to have a perfectly integrated build system and will be able to track if any of the project in whole dependency chain breaks due to any commit. On change in any project, it will trigger the build of all dependent projects. Inter-project dependencies will be synchronized automatically.

How to Configure and Use Jenkins - A Continuous Integration System

Jenkins (http://jenkins-ci.org/) is a Continuous Integration system, facilitates continuous build and test setup for projects. It is an open source tool is similar to 'CruiseControl'. Jenkins is quite stable tool and is used by many Organizations. In this article, we shall discuss about Jenkins, its usage, and configuration.

When we call it 'Continuous Integration System', what is this?

When we work in a team environment using some Source Control / versioning tool, we checkout the work code from repository and starts working on it. After this, every developer used to commit her code to repository whenever she is finished with her work. When application is highly integrated, every commit may change the application integration scenarios, break the integration and probably can induce bugs also, or can break the code compilation etc. Now we need some tool to ensure that we check this inter-dependencies of integration and the stability of latest committed code, as soon as any body commits the code. So we need some tool, which can perform following kind of tasks:
  1. As soon as, any code is committed to source code repository (or at any given schedule), tool takes the update from repository for the project and run its build
  2. Frequency to check any new commit in source code repository should be configurable
  3. Build system is designed by team and can be based on any building mechanism like ant or maven. Tool should recognize and support the famous build tools like ant or maven etc
  4. Tool builds the project and hence all tasks configured with build system will be performed
  5. If build fails, tool should capture the 'build logs'/'console output' and should be able to send email with all logs to more than one configured email id
  6. It should have some User Interface where user can be able to see the status of various projects, their last build time, failure, logs etc
  7. If build passes, it means everything is good with new commit
  8. Then tool should be able to check if any other project or module is dependent on current project. If yes, it should trigger the build for that project also
  9. Again controls goes to step 5 for new dependent project
  10. .....
For more information about 'Continuous Integration', please refer to
  • http://en.wikipedia.org/wiki/Continuous_integration
  • http://martinfowler.com/articles/continuousIntegration.html

Jenkins support all of above features and even more with different extensions.

Earlier 'Jenkins' was known as 'Hudson'. It was started by its founder (as Hudson) developer while working with Sun Microsystem. Later, it was separated out under a separate name as 'Jenkins' due to some IP (or similar) rights conflicts. Hudson is moved to Eclipse Foundation now. You can find it at http://hudson-ci.org/

After knowing this, one question come to mind is, which tool we should use? Well, this is something everyone need to find herself. However, we have decided to go for 'Jenkins' because it is where most of the original developers and community is working. It is having quite active development releases and is going well as of now. You can find more discussions at http://stackoverflow.com/questions/4973981/how-to-choose-between-hudson-and-jenkins

High Level Design Considerations for Reporting Solution

Reporting is an important part of most business enterprise solutions. Even for end business users, value of software is directly  proportional to quality of reporting system it provides. In this article, we shall discuss about very high level design considerations for reporting system. We shall not go in depth of technology, but will  talk about the thought process and various considerations which helps in design and in choosing the right tool.

When we talk about reporting, it means we are providing the information stored by Enterprise Application in a form which can provide valuable business and operational information to various stakeholders. Data stored by Application might be in different format, like most of the operations are related to CRUD activities and processing of various business document. However, reporting requirements can be very different. These can be very simple like to show all order processed with summary of their values, and also can be bit complex where one want to see the summary of all operations held, trend of specific business operations, future forecasting of business depending upon current sale trend and market data and so on. That means that we need to maintain data considering reporting requirements of solution, otherwise, it will be a good level of processing at the time of generating the reports if database structure is not compatible.

Next to discuss is, how database structure required for reporting can be different than application general data structure. Here are some of the possible differences:-

  • Operation database used to be highly normalized to ensure the data integrity and consistency. However, to generate the reports which may need bulky data processing, we may need to maintain data in de-normalized form so that related data can be found in same table/s without applying multiple joins.  
  • Reporting database may need many indexes to speed up the searching operations while generating the reports. However same level of indexes can slow down the create/update/delete operations in Operational Database.
  • We may need to do various calculations on Operational Data to generate the reports. If reporting data is different and is ported from Operational Data, these calculations can be done during porting and can be stored in database for fast access while generating the reports.     


What is Software Release Process


As software systems, development processes, and resources become more distributed, they invariably become more complex. Further, software products used to be in an ongoing cycle of development, testing, and releases. Moreover different platforms add more complexity to this. Hence it is quite understandable that there are many different dynamic pieces that must fit together seamlessly to ensure the success and long-term value of a product or project.

Release Process means a set of well defined steps which MUST be followed before giving any new project version to end users for use. These steps involves various components like:

  • Planning of features/enhancements/support/bugs we are covering in this release 
  • Versioning of releases
  • Time line for release - release date for testing and for users
  • Repository structure like branching in repository maintain the changes
  • Trace-ability matrix to track the quality
  • A good build system to ensure the quality deployments
  • Test cases and procedures
  • UAT management
  • Release to production environment
  • Procedures to revert the deployment in case of any failure
  • Information to client and training wherever required

Release process is the core of a stable system. If engineering team is heart of the project, release process is like heart beat of the project. Stability of every release is directly proportional to the strength and quality of release process and how good are we adhering to it. Ideally Release process is so important that it is being kept at first step even before building the software. Because it is the prorces which will ensure a smooth and quality delivery to the end users. Software team responsibility is not only to build a great software, but also to deliver it to users on time as expected and with desired level of quality.

Role and Characteristics of Software Architect

Software Architect is a vague term, and is having varied responsibilities in different Organizations and Environments. However if we talk about well accepted concept, a Software Architect is responsible to architect the system and lead all technical initiatives in the system. Software Architect is actually a senior technical person and often an ex-developer who has acquired a good level of skills across the products and platforms and having good experience of life cycle of applications. So Software Architect lead the project (or projects) for all technology related activities. She is a technical lead, and hence should have good technical skills as well as should be a good leader also. She leads the whole team around architectural decisions and implementation, and around technology related quality aspects. Here is an abstract list of responsibilities from which an architect own some or all as per the environment: 
  • Keep an eye on new technologies coming in market and pick which can add value to the system
  • Prototyping for new tool or technology
  • Submit proposals for the development of Project with a long term vision of System requirements and architecture both while keeping in mind the priorities of business
  • Technical Documents
  • Converting business requirements to technical level requirements, so that team can understand these
  • Define over all architecture and interaction of various layers and components. A durable architectures, which is abstract enough to be independent of any third party API, and even abstract within different layers of system
  • Bridge between developers, project managers, and business experts
  • Good skills of communication to make every stake holder understand the technical decisions in their language
  • Ensure the technical directions of system and choices among various available options
  • Often have experience of mixed technology set or at least understand these 
  • Mostly initiate the in-house framework development and define the roadmap for the framework development
  • Suggest solution for complex problems in System
  • Review the implementation process and design for performance and quality
  • Set quality parameters
  • Release various guidelines for implementation
  • Mentor the team for technical knowledge
  • Knowledge builing exercises and work as mentor for team
  • Exploration of new technologies and tools, and propose right one to team
  • Proposal for process and execution considering technlogical changes, requirements and project requirements

Exception Handling in Web Applications

Error Handling is an important part of any implementation. An application without Error Handling is like a patient with all door closed for diagnosis. It is a perfect time killer for developers to debug the application issues without proper error handling. Hence it is an important topic to discuss. However here we are concentrating more on error handling in web applications (using JSP, Servlets).

Motive of error handling is to capture any error generated in the application, log it to any logging system and propagate it to right point so that it can be directed to the user with all useful information. So the basic flow of error handling should be
  • Apply try-catch block with right exception type in catch around the code which may generate the error
  • Log the error using any logging mechanism. One of the popular logging system is log4j using commons logging. Ensure to use right logging level i.e. debug, info, warn, error etc
  • Apply business logic whatever is required to handle the erroneous case as per application requirement
  • If error is not manageable and condition should be propagated to user, throw the appropriate error further after wrapping the original error. Make sure that new exception should carry all user centric details which can help them to understand the cause of error, and developer centric information which can help them to debug the issue. 
  • As a general mechanism, error codes can be set to exception which can describes the reason of problem at Application and UI level. These error codes can also be used to show the localized messages on UI
  • Application Framework should provide the facility to handle any exception originated from the application and redirect it to a designated UI which can show the error details to user with all the details
  • The UI can also have the mechanism which can facilitate the user to log the issue directly in Issue Tracking system or to send email to the support staff with all the details

Implementation of Login and Logout in Web Applications

Login/Logout seems like a simple operation in web application. However small information left behind can give a chance of security breach to hackers. Here is a simple and minimal workflow which we should ensure while implementing login/logout functionality in web applications.

  • Have a Security Manager on the Gateway which can authenticate and possibly authorize every new request to server. For example, it could be a ServletFilter. 
    • It should authenticate every new request to check whether user is logged in or not. 
    • If yes, does current request URL exists?
    • If yes, does user have rights on current requested URL?
  • If request is passed through Security Manager, the login  manager should do following: 
    • Clean the existing session for all application specific information.
    • Invalidate the session using session.invalidate.
    • If request is for login
      • Check if user exist for given user name and password. 
      • If not, return to right page with message
      • If yes, go ahead
      • Create a new session, for example, request.getSession (true)
      • Fill the session with all application specific information for current user like all UI structure for which current user is authorized.
      • Forward the request to home page of request application or module
    • If request is for logout
      • Forward the request to logout message page  
This is the minimal workflow to ensure the basic principles, however a lot can be added to implement the application specific security checks and to support the application structure. Like as an extension, the Security Filter which is sitting at gateway can interact with a security service to validate the current request for authentication and authorization. Similarly Login/Logout implementation can interact with Security Service to authenticate the login information and later to retrieve the user specific application settings, for example, the menu structure and UI look etc. 

This brief information may help in concept building and in basic architecture design.

Key Principles for Software Architecture and Design

Defining the Architecture is a challenging job. However by focusing on few Key Design Principles, we can make it easy and even interesting. Here are few Key Principles for Architecture and Design:
  • Separation of concerns: Each component in the system should be assigned a specific responsibility. It means that features should not be overlapped among the components and the users should be very clear about where to go for a certain feature. It avoids interdependency of system components, and make the system easy to maintain. Suppose in future, you find scope of improvement for this feature, then you need not to make the changes at multiple places. But you will make the changes in the specific component, owner of the feature, and all other components will get the benefits as they must already be using this for that specific feature. This approach also makes the application easier to understand for a user.
  • Principle of Single Responsibility: Every component should own one specific and distinguished feature. It helps in defining the responsibilities clearly, helps the user to understand the system easily and also help in integration of component with other components. 
  • Don't Repeat Yourself: This principle states that one functionality and hence the piece of code should be implemented in one component only. It should not be repeated across the components. Uses are that the code will be very maintainable. If you find any error, or you want to optimize the code, there is always one place where you can do it. Otherwise there will be a search in whole code to find out the places where similar code has been done for a feature.

Application Architecture and Design

Application Architecture is the structure of the whole system which describes the important component/objects of a system, various interfaces and that how these interact with each other. It also defines how system will be accessible to external world and how it will integrate with other third party services. So it is a high level structuring of the system, which might not have the detailing at object level; but will describes various layers, what kind of components/objects these layers will have and how these different layers will interact with each other.

Now if we need detailing at next level i.e. objects and their relations then we should proceed for designing of the system. To understand the difference between architecture and design, consider the Architecture may define a layer where all request processor/handlers should resides. Further design can describes various kind of actual request processors based on system and business need.

Singleton Design Pattern

It is a special class, for which we can not have more than one instance in system at a time. It provides a single global point of access to that instance. Hence it ensures that only one instance can be created for this class and every user is forced to use only that single instance for any operation.


Example

  • Any Utility Class: Generally utility classes do not have states with these and so a single instance of that class can serve the whole system.
  • Memory Manager: An object which is responsible to manage the memory in system. Obviously only there should be only one instance of this object so that it can update the objects with the current memory availability and other objects can update its state for expected memory requirement. 

Factory Design Pattern

It is responsible for creating the objects. As name depicts, it is a factory for creating any specific kind of objects. It abstracts the user from the details of creation mechanism, and also abstracts the actual implementation class of instantiated object. The only requirement is that the ‘object to create’ should be of some already defined type. The actual implementation may differ based on the current scenario.


Example

  • Maruti Car Factory Object: We can ask this object to return us a Maruti car based on any runtime parameter which defines its model like Wagon R, or Esteem. It is the responsibility of this factory object to return us required car implementation based on specific parameters.
  • Row Renderer Factory Object: We can ask it to return the renderer like structured row renderer, or a designable row renderer.

Builder Design Pattern

It separates the construction of complex object from its representation, so that number of different representations can be build based on the requirement. It is similar to factory pattern, but it does not return simple descendant of base class. The factory is concerned with what is made and the builder with how it is made. Factory simply returns an instance of related class of base type, but builder returns a composition of various classes depending on the specified state. 


Example

  • Editor Builder: Suppose you are creating a UI for workflow where a number of different types of nodes can exist. We need different editors to edit these nodes, which can be very complex in structure. Here we can use builder which can build the desired editor.  Even editors can vary in structure based on current state of system.

Prototype Design Pattern

It suggests, instead of creating a new instance of any object, make a copy of existing object and modify its properties as required. Generally cloning is used to create the copy of an existing object. 

Example

  • Drag ‘n Drop: While implementing drag and drop functionality in a UI, we need to show the shadow of items under dragging operation so that user can decide the place to drop the dragged item. Here instead of creating a new instance of item and setting the required properties, best way is to create a prototype of existing object and modify the required properties.
  • Filtered data set using same result set – We retrieved a large data as result set from database. Now we want to show different views on UI based on specified filter criteria. One way is to fetch the same data for every filter criteria, another way is to make the prototype of result set and apply filter to it. It will be less costly than repetitive database access.