Monday, August 05, 2013

How we build our web applications based on Domino

Intro

I've been working with Domino for many years (however very possible less than many of you :-), I started to work with version 5 at the beginning and in few months we migrated to 6.X). I worked in few companies with absolutely different projects and processes of development. There were lot of 'hell projects' (without any structure inside, just mess) and few really 'cool projects' where I could learn something. I always tried to bring the best of the old projects into new. Now I'd like to describe how we develop applications in Domino today. No revolution in our approach, however I believe that is quite good one. The only required thing in that process - you must have time and desire to change process.
Time to improve

Team and projects

We are small and quite typical team: few back-end and front-end developers, manager and no QA as we do not do mistakes :). Roll out each 2 weeks with new features. We are developing CMS that manage external websites of our company.

Few very important points about websites we are doing here:
  • website's pages have to load extremely fast (means 200-400 ms to load page);
  • clean HTML, all (!) tags, attributes, javascripts should be controlled;
  • easy roll out from development environment to production environment without any interrupt for users.

Process of development

Now let's look on most important points of development process. I'll describe each point more deeply in upcoming posts this week. Possibly I will add more points during that time, lets see.
  1. Split back-end and front-end areas, they should not block each other and be independent as much as it is possible.
  2. Front-end guys should not have any knowledge about Domino, they don't need IBM Designer installed at all.
  3. Back-end guys must have knowledge about Domino, however they don't need to use IBM Designer, only in very rare cases. Backend should be done using only Java (no LS/SSJS/@Formula etc)
  4. Using Git+Jira is must and Jenkins server as builder server
  5. Auto-tests.
We've done almost all the list, some areas require some improvements however concept works and now it's only question of time. All front-end developers do not use IBM Designer in their daily job, back-end developers still use it (rarely), everything goes to GitHub, and then Jenkins take care about rest. That image illustrate what we have.
Domino development process overview
You are welcome to give your comments, idea, suggestions or something negative about that, everything can help and improve or process and wait for new posts soon :)

Other articles in this series

  1. How we build our web applications based on Domino
  2. Split back-end and front-end areas, they should not block each other and be independent as much as it is possible.
  3. Front-end guys should not have any knowledge about Domino, they don't need IBM Designer installed at all.
  4. Back-end guys must have knowledge about Domino, however they don't need to use IBM Designer, only in very rare cases. Backend should be done using only Java (no LS/SSJS/@Formula etc)
  5. Using Git+Jira is must and Jenkins server as builder server
  6. Auto-tests.

Friday, July 12, 2013

Replacement for DSAPI in Java/XPages

I've written few articles about how DSAPI could help you to control classic web application built on Domino. That solution worked perfect for us and difficulties I encountered were:
  • slower development process due to my skill in C;
  • poor documentations about how things work in DSAPI (probably most weak side for me);
  • deployment process (you need to create new DLL each time and upload it to Domno Server, then restart HTTP);
  • you have to be 'very-very' careful with everything, one mistake (i.e. memory leak somewhere) can crash the server at some point;

Last months we worked on new Web CMS based on Java/Velocity in Domino and result I must say was really great. I will make post about most interesting things later: the topic will be about java, html/templates, velocity, git, jenkins, jira and how it works together. I would call it pure Java approach to do development in Domino. The beauty using java as engine allow us to get rid of DSAPI. So everything what have been done with DSAPI (and in total I spend maybe 2-3 weeks) we replaced in 2-3 hours with Java.

case #1: Re-write URL from http://domain/page/subpage/ to http://domain/page/subpage with 301 status. We simply set new location in header and new status
  getResponse().setStatus(MOVED_PERMANENTLY_STATUS);
  getResponse().setHeader(LOCATION_HEADER, uri);
case #2: 404/500 etc error pages we only set correct status for response + throw out required content
  getResponse().setStatus(DEFAULT_ERROR_STATUS);

So my feeling about DSAPI is actually quite good, however be sure you know how to cook it, otherwise - don't go with that solution. Remember my example: I've spent weeks doing DSAPI via C and now we did exactly same in few hours. That feeling when I compared what I spent with DSAPI (via C) compare to new solution with Java. 100 hours agains 3.


Related topics
DSAPI for Domino
Rewriting URL in Domino using DSAPI
Solution for Lotus Domino to the trailing slash problem

Wednesday, April 24, 2013

Deferred Loading

On my job we are trying to decrease time for loading pages as much as it is possible, we simply want 'fast pages'. We don't want our users waited for 2 seconds each time they load page. We are focusing to keep not more then 0.5-1 second per page and we are doing really a lot in that area. Nowadays It's quite common for most of websites to include javascripts just in head area (or at bottom area) as static html so each time we load pages they will be not responsive till all resources will be loaded. I want to share how to load of javascript files (or any another resouces) just after page loads. It could increase speed dramatically. This solution loads all javascrip files deferred after page load on onload event. That snippet should be minimized and be present on every page where you want to use deferred loading.

Snippet of deferred loader
(function(){
 function deferred(success){
    if (typeof window.onload != 'function') {
   window.onload = success;
  } else {
   var old = window.onload ;
   window.onload = function() {
    old();
    success();
   }
  }
 }

 function getScript(url,success){
  var script=document.createElement('script');
  script.src=url;
  var head=document.getElementsByTagName('head')[0],done=false;
  script.onload=script.onreadystatechange = function(){
    if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
   done=true;
   success();
   script.onload = script.onreadystatechange = null;
   head.removeChild(script);
    }
  };
  head.appendChild(script);
 }

 function getScripts(urls, success){
  var total = 0;
  function trySuccess(){
   total++;
   if(total == urls.length)success();
  }
  
  for (var i = 0; i < urls.length; i++) {
   getScript(urls[i],trySuccess);
  }
 }
 
 var DeferredLoader = window.DeferredLoader = {};
 DeferredLoader.getScript = getScript;
 DeferredLoader.getScripts = getScripts;
 DeferredLoader.deferred= deferred;
})();

How to use loading, in that example we load jQuery, then when it's loaded we load kissmetrics libraries and only then utils.
var urls = {
 jquery: "/javascript/jquery-1.9.1.min.js",
 dependent: ["/javascript/util-2013-04-10m.js"],
 kissmetrics:['//i.kissmetrics.com/i.js','//doug1izaerwt3.cloudfront.net/' + window._kmk + '.1.js' ]
};

DeferredLoader.deferred(function () {
 DeferredLoader.getScript(urls.jquery, function () {
  DeferredLoader.getScripts(urls.kissmetrics, function () {
   DeferredLoader.getScripts(urls.dependent, function(){})
  })
 })
})

Wednesday, March 06, 2013

Rewriting URL in Domino using DSAPI

I will briefly describe what we were aiming to achieve. In order to open page with parameters Domino requires to add ?open or ?opendocument action and only after that Domino allows to add parameters. It's quite annoying for us due to some integration with another systems, those systems expect they can simply add parameters just after our pages, i.e.: http://www.host/page?parameter=123 etc. Also important reason - we simply do not like this ?open or ?opendocument in URL.

we want to be able to that:
www.host/page?opendocument&parameter=123 ==> www.host/page?parameter=123

I got couple helpful comments in my previous article about URL control in Domino, that helped me to look on different solutions, thanks guys. However I decided that those solutions a bit complicated to setup and they could do some impact on page load time.

I've been working on DSAPI solution last days and finally with some help I've made it! Now we have full control with our URLs, at least I've such feeling :). Let me share my small success to all of you.

Here you can find main steps you need to do. Please keep in mind, I've updated my code a bit as our logic has many rules when exactly to add parameters.

1. Enable flag to catch Rewrite URL event.
filterInitData->eventFlags = kFilterRewriteURL;
2. Link 'rewrite URL' event with you function.
DLLEXPORT unsigned int HttpFilterProc(FilterContext* context, unsigned int eventType, void* eventData) {
 switch (eventType) {
  case kFilterRewriteURL:
   return RewriteURL(context, (FilterMapURL *) eventData);
  default:
   return kFilterNotHandled;
 }
}
3. Finally the main logic, that makes URL rewriting.
int RewriteURL(FilterContext* context, FilterMapURL* pEventData) {
 FilterParsedRequestLine pReqData;
 unsigned int errid=0;

 // if there are no parameters in URL - nothing to do.
 if (strstr(pEventData->url, "?")==NULL) return kFilterNotHandled;
 // read request as we are going to update query.
 context->ServerSupport(context, kGetParsedRequest, &pReqData, NULL, NULL, &errid);
 // if query starts from opendocument - nothing to do
 if (strncmp(pReqData.pQueryUri, "opendocument", strlen("opendocument"))==0) return kFilterNotHandled;
 // adding opendocument before query and put result in pEventData->pathBuffer
 sprintf(pEventData->pathBuffer, "%s?opendocument&%s", pReqData.pPathUri, pReqData.pQueryUri);

 return kFilterHandledEvent;
}
Solution we did works like a charm and what is very important it does not affect page load time (we measured of course)

Related topics
DSAPI for Domino
Solution for Lotus Domino to the trailing slash problem
Replacement for DSAPI in Java/XPages

Sunday, March 03, 2013

Mongodb - Enable Authentication

Basically it is very easy to do,
  • 1. open mongodb shell
  • 2. open admin db and add admin user (you need to have 1 user otherwise you can' lose access to your databases at all)
  • use admin
    db.addUser("admin","12345")
    
  • 3. Enable authentication auth=true (simply un-comment it) in config file 'sudo vi /etc/mongodb.conf', save changes and restart mongodb service
  • sudo service mongodb restart
    
For more information please read Security Practices and Management