Showing posts with label bestpractices. Show all posts
Showing posts with label bestpractices. Show all posts

Tuesday, June 5, 2007

HTTP Content Optimization

You have your business engine all setup. Your processing algorithms have been optimized to the hilt. Your data model is as scalable as any. Any now you are publishing your data to the WWW. Well, the good news is you can still do more - all with plain old HTTP.

Herein I list 3 simple ways you can leverage HTTP to help you better serve your content:

  1. Cache-Control headers
  2. ETag + If-None-Match
  3. gzip
1. Cache-Control headers

Cache-Control is byfar is the most widely used of all http headers and for good reason. You generate your response and you set a Cache-Control response header with a validity period. The clients, the intermediaries and the web infrastructure at large all work overtime for you caching your content until the time that you have tagged it valid.

This of course works best for static resources or for such dynamic resources whose validity you can reasonably predict before hand.

2. ETag + If-None-Match

This is one of the most powerful but unfortunately, a not-frequently used technique. So your content is such that you can't reasonably predict its validity period. Which means #1 doesn't work for you. Your next best buddy is ETags.

This is how it works: You generate your content and you set the http header ETag (entity tag). The ETag represents the state of your resource. Even if one bit of the resource content changes, so does its ETag. You can think of ETag as a simple hash of your content. Ok so you have set the ETag and sent the response. Now the next time the client tries to access the same URL, it will send an If-None-Match request header and it will be set to the same value as that of your ETag. Now you can either regenerate the content or you may have it cached on your server, if the ETag of your content matches the If-None-Match it implies that the content has not changed. The client has indicated to you thru the If-None-Match that it already has this content. So what do you do - send nothing! Yes - simply set the response status to HTTP 304 (Not Modified) and the size of the content that you send this time is exactly 0. At a minimum, you gain in saved bandwidth (read performance) but if you have cached the content on your server, you also gain from saved computation.

3. gzip

With #1 and #2 you benefit by not having to resend your content in certain situations. But even when you can't get away from having to send content, you can still gain in bandwidth by simply compressing it. But of course you want to compress content only for clients that you know can decompress it and even then you need to tell the client that the content you sent is compressed and it needs to decompress it.

No hassle - http makes it fairly straightforward. If the client understands gzip, it sends an Accept-Encoding request header with the string gzip in it. If you (the server) read this header and find the string gzip, you gzip your content and set a response header Content-Encoding to gzip. This tells the client that the content is gzipped and it must decompress it before providing it to the user.

It's normal for gzip to compress text content in upwards of 70% and given how easy it is to compress content you should be compressing your content right about now.

Note that #2 + #3 put together have problems in IE 6 and you might have to take that into account.

But all in all optimizing the delivery of your content with http is simple yet powerful and your web application can only benefit from it.

Friday, May 18, 2007

More Resources == Scalable

Link: Sam Ruby on Google Maps

Of course, the rest of the iceberg was that Google had simply tiled the Earth. In so doing, they converted a single web service (call me with a bunch of information, and I will provide you with a custom result) into a large number of individually addressable, cacheable, and scalable web resources.
That's it. More the resources more is the opportunity to use Cache-Control headers, to use ETags, to distribute and load-balance the system.

In the same article, Sam also talks about how the web is not a service but a space. And in today's world adding more "space" will scale your system manifold than implementing a state-of-the-art service with the most optimal algorithm. Processor speeds have flattened. Today it's about dual-cores, quad-cores, (your-budget)-cores. The more cores your program can use to get the job done, the more scalable will your system be.

As Brian Goetz puts it: "Tasks must be amenable to parallelization". Parallelization comes for free with every resource you add. So add more resources and see your system scale.

Sunday, May 13, 2007

JavaOne Days 3-4: Mashups and garbage collection

If you are surprised that I am talking about mashups and garbage collection in the same post, well, so was I. But if one can talk about implementing servers in JavaScript, I most definitely can talk about mashups and garbage collection in the same breath.

Day 1 was primarily scripting, day 2 hardcore java. Days 3 and 4 saw sessions on the entire gamut of Java technologies - from garbage collection to mashups. I discuss some of them here.

Blueprints for Mashups

This was arguably the most informative session for me by far at this year's JavaOne. Kudos to Greg, Mark and Sean for putting together a to-the-point, practical and readily-usable session together. Personally, this session validated the REST and JSON concepts I had gathered over the past few months. I'll recommend this session to anybody interested in building mashups, REST services, AJAX and a whole lot more. (No, they haven't paid me to say this.)

Anybody building REST services should design their system with JavaScript in mind. In today's mashup world the browser (and hence JavaScript) is your first class client. XML and JSON are the typical content types returned by REST services. To get over the browser's cross-domain restrictions, there are 2 possible solutions:

  • Server-side proxy: Clients always send requests to the server that is hosting the page. The server in turn acts as a proxy, sends your request to the (remote) mashup service and returns the data it gets from the mashup service to you.
  • Dynamic script tags: Browsers allow script tags to communicate with cross domain servers. This opens up the opportunity for you to issue requests to any mashup service by generating dynamic script tags.
Consider the Atom format if you are serving XML. This opens up your service to the large number of feed readers and other Atom clients out there.

JSON has of course gained immense popularity of late. Although JSON is technically a serialized JavaScript object, the JSON format is highly portable and language independent. In addition to returning JSON, you can also support wrapping the JSON object in a JavaScript callback method (they called it jsonp - JSON with padding). This enables clients to specify a callback method which can readily work with the JSON that the server returns.

Various options are available for securing your REST services:
  • User tokens
  • Session based hash
  • URL based API key
  • Authentication headers
JavaScript best practices:
  • Use namespaces
  • Use CSS for applying styles
  • Don't add to the prototype of common JavaScript objects
  • Setting the innerHTML property is easier / better than DOM manipulation
Components of a ("good") Mashup API / library:
  • A server-side service
  • A client-side JavaScript API / library
  • A client-side CSS for applying styles
  • Document the API
  • Create simple examples enabling a simple cut-and-paste approach to learning your API
As you can see, they have, true to the name, provided blueprints for mashups, best practices, possible hurdles and workarounds, problems and solutions. Once again - highly recommended for anybody who has / will have / may have anything to do with mashups.

Phobos - A Server-side JavaScripting framework

While JS clients are ubiquitous and obviously here to stay, for the life of me, I have not yet come to terms to implementing my server in JS as well. The 2 reasons they cited - impedance mismatch and all-you-need-is-an-F5 to redeploy - didn't quite do it for me. May be in another life I'll grow up to JavaScript servers, but not for now. And if at all that day were to come, there should be a JavaScriptOne and no JavaOne.

Garbage collection

If there was one objective of this session, it was to clear the GC myths out there. Some of the finest Java minds were refuting the urban legends out there and when they talk you listen:
  • Object allocation is cheap. Reclaiming young objects is also cheap.
  • Small, short-lived immutable objects are good. Large, long-lived mutable objects are bad.
  • Nulling references rarely helps - except when it comes to arrays.
  • Avoid finalizers - in most cases there are better alternatives possible.
  • Avoid System.gc() - except between well-defined application phases and when the load on your system is low.
  • Object pooling is not required in today's VMs. It is a legacy of older VMs. Exceptions are objects that are expensive to allocate / initialize or objects that represent scarce resources.
  • Consider using reference-objects for limited interactivity with the garbage collector.

Certain memory-leak pitfalls:
  • Objects in wrong scope
  • Lapsed listeners
  • Metadata mismanagement

They strongly advocated FindBugs for finding such pitfalls as well as other potential bugs.

JavaOne Day 2: Hardcore Java and Java EE 5

While Day 1 saw an overdose of scripting, sanity made a return on Day 2. Although JavaScript technology (whoever came up with that) sessions continued, there was a good supply of deep-dive Java and Java EE sessions to keep me busy. And there was also some WADLing.

Generics and Collections

Generics have been around for a while and most Java programmers have some understanding of it. There have been many criticisms against the erasure based implementation of generics - since parameter types are not reified, constructs that require type information at runtime don't work well. However erasures allow 2 most important benefits - migration compatibility and piecewise generification of existing code. Just these benefits make erasures a necessary bane.

Huge additions have been made to the Collections framework in Java 5 and 6. So much so that many recommend programmers to never use arrays - Collections all the way!

Concurrency Practices

The concurrency classes introduced in Java 5 are a great new toolset for the Java programmer. New concurrency related annotations such as @ThreadSafe, @GuardedBy, etc. are being considered. One important aspect to keep in mind - imposing locking requirements on external code is asking for trouble. Ensure that you make your code threadsafe yourself. Performance penalties incurred by synchronized constructs are overblown.

Immutable objects are your friends - final is the new private! They are automatically threadsafe. Object creation is cheap. Aim for less and less mutable state.

Performance is now a function of parallelization - write code such that it can use more cores to get the job done faster. So to improve scalability find serialization in your code and break it up:

  • Hold locks for less time
  • Use AtomicInteger for counters
  • Use more than one lock
  • Consider using ConcurrentMap
  • Consider ThreadLocal for heavyweight mutable objects that don't need to be shared
Effective Java

Builder pattern allows you to construct objects cleanly in a valid state with both required and optional parameters. The basic premise can be expressed in code as such:
MyObject myobj = new MyObject.Builder(requiredParam1,requiredParam2).optionalParam1(opt1).optionalParam2(opt2).build();

Generics - avoid raw types in new code. Don't ignore compiler warnings. Annotate local variables with @SuppressWarnings rather than the entire method / class. Use bounded wildcards to increase applicability of APIs. 3 take home points for paramterized methods:
  • Parameterize using <? extends T> for reading from a Collection
  • Parameterize using <? super T> for writing to a Collection
  • Parameterize using <T> for methods that both read and write
If a type variable appears only once in a method signature then consider using a wildcard. Avoid using bounded wildcards in return types. Generics and arrays don't mix well - consider using generics wherever possible.

Java EE 5 Blueprints

Filter.doFilter() may run in a different thread than the Servlet.service() method. The Servlet API does not use NIO, however it is possible to implement it yourself. New annotations may make web.xml optional.

The JSP and JSF EL have been unified. # is now reserved in JSP 2.1. The javax.faces.ViewState hidden field (for client side state) will be standardized. Include this field in your AJAX postback. Application-wide configuration of JSF resource bundles will be possible in faces-config.xml. The <f:verbatim> tag is no longer needed to interleave HTML and JSF content. @PostConstruct and @PreDestroy annotations will be supported for JSF managed beans.

WADL

WADL - Web Application Description Language. As a colleague of mine put it - it's WSDL for REST! And IMO that's almost what it is. It's all in good intent to introduce WADL - a formal definition of your REST resources, allows you to automatically stub out code in your favorite language, aids testing. However WADL has many rough edges and I don't see myself using it anytime soon until those have been addressed - overloaded / loosely typed query parameters, security, non-standard content negotiation, et al.

Sunday, March 26, 2006

ArcGIS Server coding practices

The ESRI dev summit was a great experience. Meeting fellow developers is always good - you talk the same language, exchange ideas, receive feedback, discuss how things can be made better,... I could go on and on.

Ok, so I was asked quite a few server related questions at the summit: What should I keep in mind while coding against the server? Any do's and dont's? Any particular classes / methods I should read more about? etc... So here I'll talk about certain points you should keep in mind while working with the ArcGIS Server, particularly the MapServer:


  • Use the description objects: Sure the MapServer gives you access to the IMap but you don't have to go there. A lot can be accomplished by using the IMapDescription, ILayerDescription, et al.

  • Release the ServerContext: In a pooled environment you are sharing the server object with other users. So it's your responsibility to release the context once you have performed your set of operations. For web applications, this translates to releasing the context after every request. Of course, if you are using the ADF, the ADF does that for you so you need not worry. But even then it's good to keep this in mind.

  • Do not reference server objects after the context has been released: Do you continue to work with the Statement object once the JDBC Connection has been closed? NO. Why? Because a Statement can be executed only while the Connection is live. Similarly, you should not reference ANY server objects once you have released the IServerContext. If you want to persist the state of any server object, you should use the saveObject() method to get a serialized string representation of the object before releasing the context. You can once again rehydrate the object by using the loadObject() method once you have regained access to the context.

  • In case you had forgotten - use the description objects: Did you know you could add serializable custom graphics to the IMapDescription object?

  • Use methods exposed by the MapServer: Look at the javadoc for the MapServer and for all the interfaces that it implements. It can do a lot more than you might think - you can export maps, layouts, do queries, identifies, get feature info, handle SOAP requests, and a whole lot more.

  • Create server objects on the server: You don't create RMI objects on the client. You don't create EJBs on the client. Similarly, you don't create ArcGIS server objects on the client. ALWAYS use the IServerContext.createObject() method to create all and any ArcObject in a server application within your server context at the server.

  • BTW, use the description objects: Did you know you could change layer visibilities, select features, even set definition expressions with the ILayerDescription object?


This by no means is an exhaustive list but something which might help you when working with the server. Oh yeah, in parting, in case you had missed: use the description objects!

Wednesday, December 21, 2005

Exception handling in web frameworks

There are many good articles out there pertaining to good exception handling practices. Here I'll list some that I've learned over the course of working on web applications and as it pertains to web frameworks.


  1. Chain Exceptions:
    Sure one should never lose sight of the destination, but with exceptions one should never lose sight of the source - the all important root cause, the crux of the problem. While you can catch exceptions and throw custom exceptions, never lose the exception that you caught. When creating custom exception classes, always include a constructor that takes the cause as an argument:
    public CustomException(String message, Throwable cause) {
    super(message, cause);
    }

    Or if you are using an exception which does not have such a constructor, you can always use the initCause() method:
    catch(AnException e) {
    IllegalStateException ise = new IllegalStateException("Something went wrong.");
    ise.initCause(e);
    throw ise;
    }


  2. Throw framework specific exceptions:
    The root cause tells you what went wrong but you also want to know where it went wrong. This is especially critical in web frameworks where the framework makes callbacks, does dependency injection and other IoC stuff to call into app specific custom client code. When your client comes to you with a support call or posts the problem on the forums the first thing you want to know is where in your stack did it fail. Debugging and fixing the problem becomes a lot easier once you have narrowed it down to your courtyard. Framework exceptions are best implemented as a hierarchy of custom runtime exceptions. The root of this hierarchy could be a RuntimeException named MyFrameworkException and it could have any number of sub-classes such as MyFrameworkModelException, MyFrameworkControllerException, MyFrameworkViewException, etc. depending on how you have categorized different pieces of your framework.

  3. Log, log, log:
    Where exception messages don’t tell much, debug messages logged from important places will. What comments are to source code, log messages are to runtime. The standard JDK logging API allows you to log messages at multiple levels including INFO, CONFIG, FINE, FINER, et al. Logging messages at various levels will not only provide answers to the hows, whens and wheres of the problem but will also go a long way in helping your customers understand the underpinnings of your framework. And more often than not that is all they need to fix the problem themselves!


We are constantly trying to improve the exception handling and logging in the ArcGIS ADF and you can be assured that we are employing these principles as well.

Saturday, July 2, 2005

Annotation use cases

My first blog here but will cut straight to the point.

The most talked about feature at J1 this year was annotations. It was as if every new API / framework had to have support for annotations or must have something pertaining to it on their radar to gain acceptance or even be considered a contender.

I have not yet being able to make my mind if this profileration of @YeahIHaveAnAnnotationToo is a good thing or not. For the time being I am trying to come up with use cases of where annotations make sense. Here are some that I have assimilated from various blogs, J1 sessions and my own brain dumps:

1. Dependency injection.


  • The @Resource and the @EJB annotations introduced by EJB3 are obvious examples of dependency injections. Any custom framework will have some notion of a context or an environment or a manager and injecting such resources into users' classes would make a lot of sense.


2. Aspects (boiler plate stuff handled by the container / framework) and interceptors

  • The @TransactionAttribute annotation associates a transaction aspect to a method. @Query and @Update annotations introduced by JDBC 4.0 perform tasks which go beyond just boiler plate - they actually populate and manipulate objects which directly affect business logic. I've put interceptors alongwith aspects coz I consider interceptors as an implementation technique for aspects (Correct me if I am wrong). I think one needs to be really careful when designing annotations in this category because taking this route could be a slippery slope - you design a bunch of annotations which perform certain core tasks and your co-developer has his/her own set of tasks which s/he religiously believes are "core" and your manager feels that it's critical to design a third set to appease that billion $ client. IMO, for this category of annotations just design those which strictly do boiler plate stuff and don't necessarily alter the business state for the client.


3. Callback methods

  • The @PostActivate and @PrePassivate ones fall in this category. I am not sure if I am a fan of annotations in this category. Basically with this all you are trying to do is eliminate the need to implement certain interfaces. Which means all you gain is that you don't need to have empty implementations for methods that you don't need. But it becomes very difficult for somebody to understand what contracts your object fulfills or which methods are actually designated as callbacks. One might argue that objects are no longer POJOs if they have to adhere to some framework specific interfaces - if this argument is important for you then implement callback listeners (an alternative that EJB3 also provides) to achieve this objective.


4. Container contracts

  • Tagging an EJB as @Stateless and @Stateful makes it known to the container how it should treat that bean. Moreover, it also sets a programming pattern for the user how to access and use these objects. Most marker annotations could be included in this category. So if your framework needs to handle certain objects in specific ways, you could think about such annotations.


5. Programmatic access to metadata for classes, fields and methods.

  • This is an oft forgotten use case but one which I think makes sense for UI objects. While it's a given that it's important to publish information regarding a method or a field's behavior through detailed comments and Javadocs; for UI objects this information may also need to be presented to the user on desktop panels and HTML forms. So the next time you author a UserBean think about associating a runtime @Description annotation with the username and password fields so as to give consistent descriptions for these fields across different views of your app.


(I'll try to add more as I get my head around it more (or if you have any more points for me).)

While this push toward annotated POJOs for everything might be a good thing; the thing that I fear is that Java classes of the future would have less Java code and more of annotations. It may become increasingly difficult for the user to deterministically gauge what behavior any given method would exhibit because what the method does could change dramatically depending on which annotations were applied when the method was actually called.

Not trying to attach a pessimistic annotation to annotations (what can I say, I love meta-anything!) but just waving a flag of caution before we head heads first into the annotated unknown...