Latency is a powerfully factor with all user applications. Users always want more responsive systems, and quickly become annoyed with seemingly small delays as they occur upon every request. This can often mean the difference between converting a new visitor to them leaving after only accessing a few pages that have loaded at a sub-optimal speed. “Man, if it takes 3 seconds just to open a product page, it is going to take me all night to try and customize this product!”

We can all understand the requirement of low latency systems, particularly in customer facing systems, but what is an acceptable range and how do we not drop the ball when the golden age arrives? How do we ensure what works today to give us an acceptable latency measures for that fantasized point in time when we have more customers than we know what to do with? Now, maybe that time is far far in the future as a typical scale up solution works marvelously for 90% of companies, but if there is even a remote possibility of out growing traditional normalized database systems it is irresponsible to try and cope with them as architectural decisions.

Even more importantly, what happens to a user when a system becomes unavailable? Well, if that user was a fresh lead, good luck seeing them again. High Availability (HA) is a vastly important concept in any consumer facing application, even more important than latency if that is even conceivable. Our customers are narcissistic, impatient, and more importantly spoiled. Why? Because companies want their business and can afford to train them to be this way. Examples like Amazon over sell the problem, but even at more modest e-commerce shops cannot ignore the problem and potential profit losses. If your company is based on repeat business or continued engagement like Facebook or Digg you better care just as much as a company that can directly attribute this down-time to dollars (and they do).

What does all this have to do with noSQL databases like Casandra, MongoDB, and Redis? You cannot plan your system architectures on traditional boxed solutions without considering your user’s needs now and far far into the future. Perhaps you’ll be fine with a traditional database system that offers consistency and availability that you maybe able to scale in a traditional master slave paradigm. What if your transactions really have no reason to be transactions, and perhaps writes don’t need to be consistency verified? Why would you require your systems team to purchase monstrous systems so your database system can do a few thousand JOINs per second when you could architect your product catalog to push to a Casandra (Dynamo backed) no SQL database system that provides instant support for highly scalable systems or a denormalized document based MongoDB?

I’m not saying these new flavor of the month database systems should replace all of your old RDBMS, but many of them do make a lot of sense for many applications designed for the Internet of tomorrow. Knowing these systems is vital to making quality architectural decisions around your companies customer driven applications, and surveying the landscape is the bare minimum to being a responsible web architect.

After spending some time using aspects to do various cross cutting application tasks like live profiling and logging mechanisms in one of my Spring MVC web applications, I found myself wanting to use Spring’s IoC mechanism without it’s AOP implementation. Spring provides a dynamic runtime pure Java implementation of Aspects that they promote as a complement to AspectJ. It works great with all of the injected components you use as spring already uses a proxy layer to manipulate them. If you want to be able to place join points on code that isn’t managed by spring you will find yourself looking for an AspectJ weaver/compiler.

If you use Maven2 much like I do, you’ll find it quite simple to setup an AspectJ compiler/weaver. I’m using the aspectj-maven-plugin configured to attach to the compile and test-compile life cycle goals. Here is the configuration I used:


        org.codehaus.mojo
        aspectj-maven-plugin
        1.3
        
            
                
                    compile       
                    test-compile  
                
            
        
        
          src/main/aspect
          true
true
          1.6
        
      

Getting the Application Context…

Enough with this fluffy preamble, what I wanted to do was get the application context so I could access my Hibernate managed data access object and services tier. Initially, I wanted to autowire my service and declare the class as a component that would be injected with Spring’s IoC mechanism. Unfortunately, I could not discover a method of doing so without using Spring’s proxy based runtime AOP solution. One obvious solution would be to use the XML class path context loader and specify the context file via filename and location, but this was a very brittle method that would just introduce multiple points of context file configuration (not a very good solution.).

I realized my join points where on controller actions; therefore, I always had access to the incoming HttpServletRequest object supplied by our Apache Tomcat container. With the request object I was able to get the servlet context which gave me access to both the servlet configuration parameters and a method of retrieving the Spring application context that the servlet was configured with. We used the web.xml to define spring as the dispatch servlet (following the common MVC pattern) and had our context definition split into several XML documents. By using Spring’s WebApplicationContextUtils.getRequiredWebApplicationContext() helper one can get the entire application context that the servlet is configured with.

Here is an example of retrieving a dynamic setting from a database inside of an advice annotated method that wraps around a controller action:

  public String getWebSetting(String settingName, Object[] joinPointArgs) {
        for(Object arg: joinPointArgs) {
            if(arg instanceof HttpServletRequest) {
                return ((WebSettingService)WebApplicationContextUtils.
                    getRequiredWebApplicationContext(
                            ((HttpServletRequest) arg).getSession(false).getServletContext()
                    ).getBean("webSettingService"))
                        .getNameValuePairedWebSettings().get(settingName);
            }
        }
        return null;
    }

    @Around("xxx.yyy.profiling.ControllerRequestActionProfilerAspect.inControllers()")
    public Object profileControllers(ProceedingJoinPoint pjp) throws Throwable {
        String setting = getWebSetting("enable_performance_logging", pjp.getArgs());
         [...]
    }

    @Pointcut("execution(@org.springframework.web.bind.annotation.RequestMapping * (@org.springframework.stereotype.Controller *).*(..))")
private void inControllers() {}
© 2011 Technical Solutions Suffusion theme by Sayontan Sinha