Sunday, December 22, 2013

Asynchronous Calls with Servlet 3.0

Background

With the advent of Rich Internet Application (RIA) and data-hungry HTML5, asynchronous calls are becoming more and more inevitable at every level of web application, including servlet layer. In typical “thread-per-request” model, web container assigns one thread, from pool, for each http request and runs the doXXX method of the servlet. But in cases where the doXXX methods need long time to complete, the thread is engaged with the underlying request. This creates bottleneck and limits the number of requests which can be served by web container. Although there were proprietary implementation to achieve asynchronization (Comet apps as an example), none of them provide true sense of it. I’ve seen many implementations where developers trigger a new thread inside doXXX to accomplish the time-taking tasks, but the biggest fault of such implementations is that the response is committed back to client as soon as the doXXX method ends and then you need to poll the server to get the result of the original request.
One of the important features of Servlet 3.0 is the provision for Asynchronous calls. The center of this is the AsyncContext class, which encapsulates the request and response objects and provides methods to commit/dispatch the response at later point of time. The noticeable difference here is that, on the completion of doXXX method, the thread is simply returned to pool but the response is not committed. The request and response can be retrieved from AsyncContext object later on and then response be committed from there or dispatched to another resource (servlet or jsp). Let’s consider an exemplary code snippet to understand it better:

@WebServlet(value = "/sample", asyncSupported = true)
public class SampleAsyncServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

        AsyncContext asyncContext = req.startAsync(req, res);
        asyncContext.getResponse().getWriter().println("Starting new asynchronous request…");
        asyncContext.start(new LongRunner(asyncContext));
    }//This doesn’t commit response.


    private class LongRunner implements Runnable {

        AsyncContext asyncContext; 
        public LongRunner(AsyncContext asyncContext) {
            this.asyncContext = asyncContext;
        }
 
        @Override
        public void run() {
            //Do some long process here……
            try {
                asyncContext.getResponse().getWriter().printf("Output of long process……”);
            } catch (IOException e) {
                //Handle exception
            } finally {
                asyncContext.complete(); //This commits the response back to client
            }
        }
    }
}

In the above code, inside doGet method, a new AsyncContext object is created and a new thread is started using its start method. This start the execution in a new thread while the original thread associated with doGet method is returned back to the pool. The response is not yes committed to client. In the new thread, once the task is done, the response is sent back to client using complete method of AsyncContext.  

So, theoretically, the steps are as follows:
1.       Client sends the request to web container
2.       Web container gets a thread from the pool and runs the doXXX method of the servlet
3.       With request.startAsync() method, a new AsynContext object is created which encapsulates the req/resp.
4.       You can either start a new thread and pass it to start() method of AsyncContext object to start long & time consuming process or store AsyncContext object at appropriate level and retrieve later at valid trigger.
5.       The completion of method doXXX, simply releases the thread back to pool, but response is not sent back to client.
6.       Req/Resp objects are retrieved from AsyncContext object and worked on.
Finally response is committed by calling complete() or dispatch() method to dispatch to other resource (servlet/jsp).

How to Enable Asynchronous?

By default it’s turned off. It can be enabled either using annotations or in web.xml
 
@WebServlet (urlPatterns = {"/sample"}, asyncSupported=true)
   public class SampleServlet extends HttpServlet {

OR

    <servlet>
        <servlet-name>sample</servlet-name>
        <servlet-class>com.sample.servlet.SampleServlet</servlet-class>
        <async-supported>true</async-supported>
</servlet>
Further Reading

Conclusion
Servlet 3.0 added the provision for asynchronous calls, which provides great flexibility and avoids the need for proprietary implementation to achieve the same in web applications.

Saturday, May 25, 2013

Software Architecture - A Summary Sheet

What are the key activities of a Software Architecture?
Philosophically, Architecture is an art. An architect thinks of something which doesn’t exist.
As a practice, a Software Architect is responsible for converting the business requirements into system blueprint, which can then acts as reference for design, implementation and other phases. Some of the key activities of an Architect, to list, are:
  • What is it - Describe & Define the system from a broader perspective, based on essential functional and non-functional requirements. Draw the blue print of the system.
  • Where it fits - Detailing on how the new solution would fit into and interface/communicate with other parts/systems of the whole eco-system.
  • What it contains - Visualize system as combination of sub-systems, parts/modules/functions and how these sub-systems will communicate/interface with each other. Define the system boundary, interface points/protocols and sub-system interactions.
  • How it is Structured – Choose appropriate Architectural pattern or combination of one or more and outline, how different sub-systems, modules, layers would be structured and interface with each other. For e.g. if chosen n-tier + SOA, then define different tiers and services exposed by them each and the way these tiers are connected.
  • How to build it - Define Technology Stake. Identify suitable frameworks/tools etc. Do a technical feasibility and evaluation exercise, if required.
  • What are Non-Functional Requirements – One of the important tasks of an Architect is to consider non-functional requirements applicable at Architecture phase for e.g. Scalability, Performance, Availability, Security etc.
  • How it is deployed - Consider Hardware architecture and infrastructure support required for this solution.


What are the key considerations while architecture an IT solution?

Apart from implicit consideration that system should do what it is supposed to do, these are the important considerations from architecture perspective:
  •  Money matters: The far most consideration is the overall cost involved in the solution. The solution should be cost effective, but still maintaining its value proposition.
  • Know Your Users (KYU): The solution should be easy to adopt and use. Many well architectured solutions have failed just because they are difficult to use and not adopted by user community. Know your users and make something which they can use.
  • Hear the unsaid: Along with key business functional requirements (which are mostly documented), the architect should consider the critical non-functional requirement to be addressed (which are, ironically, not always well documented and mentioned).
  • Anticipate Changes: The solution should be extensible and ready to accept (realistic) changes with minimal cost and efforts.
  • KISS: Solution should be less complex and maintainable.
  • Make it Testable: Keep the testability in your mind. Something which can’t be tested, can’t be used.


What are key principles of software architecture?
  1. Separation of Concerns – Ensure that the system is divided into logical units, each performing its designated task(s) and there is no or least overlapping between these units. Don’t cross concerns. This helps in achieving loose coupling and logical partitioning of the system.
  2. Single Responsibility Principal – It is highly recommended to divide the system into units so that each has a single (logical) responsibility to handle and avoid multiple unrelated tasks.
  3. Principal of Least Knowledge (Low of Demeter) – This means each unit, component or object should know only about itself and has no knowledge about the internal details of others.
  4. Avoid Replication – Another key principle is to avoid repetition and maximize reusability of component, logic, code etc.


What are key non-functional requirements?
Non-functional requirements are one of the critical aspects of an IT solution. Ironically, those are not always well documented or candidly mentioned, but those are inevitable. Some of the important NFRs are
  • Runtime – Security, Performance, Scalability, Availability, Data Integrity
  • Implementation-time – Configurability, Auditing, logging, i18n, localization, extensibility, maintainability, adoptability, testability.


What are key points to be considered for scalability of an IT solution?
Scalability is becoming an inevitable aspect for any IT solution, especially those involved customers interactions. Here are key points to be considered to address scalability:

  1. Functional Partitioning: It’s a very valid statement –you can’t scale if you can’t split. In other words, to achieve scalability you have to slice your application into logical modules or functions. This could be combination of functional or non-functional modules. With this, the modules or functions should be loose coupled, independent and, possibly, distributed. This allows these modules to scale independently. 
  2. 3 Key Attributes of interaction/Communication
    1. State-less: One of the key needs of a scalable architecture is the provision of stateless interaction between different layers, components and modules. With no overhead of state management, 2 components or layers can scale independently with optimum utilization of each.
    2. Asynchronous: Another inevitable aspect is the asynchronous communication, using queues, messaging, batch processing etc. This would allow one layer to communicate with other, without holding the call. For e.g. if A wants to call B, A needn’t to wait till B finishes the job and vice versa. This also helps to ensure that A doesn’t stop even if B goes down or not available. Asynchronous is also the key for ‘Availability’ aspect of the solution.
    3. Service Oriented: One more important aspect is to have logical, atomic and granular level of communication, instead of multiple- fine grained calls. For e.g. if A wants to call B, B should expose services which are logical and granular enough to perform an operations. This would avoid A calling multiple times to B for the same functionality.
  3. For Database, 6 Key points
    1. Vertical Partitioning: Logically and physically divide the DB. Have relevant tables at one place and more disconnected in distributed manner.
    2. Horizontal Partitioning: Horizontally divide the DB (Shrad or Table partitioning).
    3. No referential integrities: Avoid maintaining referential integrities in distributed environment. It’s a killer for scalable system.
    4. No Data integrity: (Read about CAP theory) Forget about data integrity in fast, distributed and scalable environment.
    5. No cross-domain joins – Avoid cross-domain joins. Those are expensive and time consuming.
    6. No distributed transactions

And in the last, What are the key recommendations for a software Architect?
  • Visualize the System – If you can’t visualize or imagine the system while taking shower, go back and clarify your doubts. An artist has to have the image in mind.
  • Always Keep 3 things in your mind – Business value, cost and time. Missing anyone will nullify all your efforts.
  • Make NFRs SMART – NFRs are critical, but unless those are Specific, Measurable, Attainable, Realizable and Traceable, those can’t be achieved. 
  • Don’t Sketch Your Own Lines. Choose architecture patterns and practices which are established and accepted by Industry. 
  • You may refer from your previous assignments and implement learning, but don’t biased from it. Technology is dynamic and improving everyday. Don’t hesitate exploring new paths.
  • It is important to document all Key decisions and learning.
  • Architecture is not just an inception phase. Lead your team till the end. Don’t just define architecture, deliver it as well…

Monday, January 21, 2013

Non-Functional Requirements – Did you get the unsaid?

One of the biggest learning I had over the years, while architecture multiple IT solutions, is the criticality and importance of non-functional requirement. This article is a snippet of my learning on these unarticulated but badly needed aspects of any IT solution.
 
As an architect & designer, like most, I also spend lot of time and efforts in understanding the business pains, needs and areas where the proposed or existing solution works. We call those functional or business requirements. There is no way to disagree on the importance of these requirements, as this is the sole purpose for the existence of the solution. But there is another set of requirements, which, most of the time, are unarticulated, undocumented…un***, but has major impact on the acceptability, usability, profitability and overall success of the solution. These set of requirements, called non-functional requirements, if not considered, can badly affect all phases of solution development including architecture, design and implementation.
 
In simple words, if functional requirements say what system should do, non-functional say how well system should do those functional things.
 
So, what are those typical non-functional set of requirements. Unfortunately there is no defined list, and interesting, not all are applicable and desired in all solutions. But still, as systematic approach, let’s categorize those into 2 sub-sets.
 
Run-time Requirements – Which affects the system during execution.  Few of the most common, and vital, runtime non-functional requirements are
  • Performance – Your response time, throughput, latency etc.
  • Security – Do you check who can enter into?
  • Availability – Is your system available 24X7 
  • Scalability – How do you react if tomorrow another set of 10K users added or new clients with huge data added to application?
Static (Development- time) Requirements – The set of requirements which are not related with run-time environment, for e.g. 
  • Extendibility – Is your solution functionally flexible and extendible within affordable cost?
  • Maintainability – Is your solution simple and maintainable over the period?
  • Auditing & logging – This is with reference to the audit and logging capabilities of the system.
  • Failover – Can your solution auto or manually recover from failure?
  • Interoperability – Can your solution operate in multiple environments?
  • Legal & regulatory requirements – Have you satisfied legal and regulatory norms?
  • Internationalization & Localization – Specific for solutions to be used in multi-lingual environment.
  • Configurability – Is your system configurable?
Problems with non-Functional Requirements
More than implementation, non-functional requirements are characterized by their fuzziness. Some of the typical problems associated with non-functional requirements are:
  1. They are not clearly defined and subjective in nature – Statements like “System should perform well”, “User shouldn’t wait long to get the response”, “System should be easy to maintain and update”, are examples of subjective nature of these requirements.
  2. They are not documents, articulated and noted – Most of the requirement docs have section for NFRs, but those are short and contain bullet points of NFRs.
  3. They are not measurable
  4. In many situations, they are not achievable (technically feasible), attainable (with given skill set or time) and relevant (for e.g. imposed based on prior experience)
  5. They are not clearly classified as in-scope or out-of-scope
Then what is the solution?
I remember, I read one of the best statements regarding non-functional requirements that those have to be SMART. i.e. Specific, Measurable, Attainable (do-able), Realizable (with given skill set, time etc) and Traceable.
In more words:
  1. NFRs have to be well defined, documented and elaborated (like functional requirements)
  2. Very important, NFRs should be measurable. (for e.g. With 100K transaction per day, the EFT would take 1 second to be verified by transaction monitoring module)
  3. A technical study (PoC) must be done to verify the attainability of NFRs
  4. NFRs must be considered and addressed in each phase including architecture. They must not be thought of as “do it when you face it”
  5. Comparatively, non-runtime (or static) NFRs are more vague. The *abilities are very subjective and must be clearly defined. For e.g. “system should be extendible” is a vague statement which can’t help an architect or designer to address it. Also, these abilities have major impact on the time and cost of the project. Hence a clear understanding (with examples) of extendibility (and other abilities) is a must.
Conclusion
Non-Functional Requirements majorly affect the time, quality and cost of any project. By nature, they are vague and ambiguous, but have major impact on the architecture, design and overall acceptability & usability of the solution. They must be considered, specified, measured and tracked at all stages of development.