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

Wednesday, February 27, 2013

Fighting for control of URL in Domino

We have really annoying problem for years with our URLs on all websites based on Domino. We use classic approach because we want control all tags + we like jQuery more etc. Our problem is about mandatory action [?open | ?opendocument] for pages with parameters, so if you want to add parameters to your page (i.e. param1=123) you have to add [?open | ?opendocument] just after your URL and only then you are allowed to add parameters.

Not really a huge problem, however we want to use new tracking code from google. That tracking has problems with [?open | ?opendocument]: it does not work correctly in case if first parameter is ?open. So now its blocker for us and we want to fix it for all another cases as well. We want to have possibility get rid off ?open | ?opendocument

Question in few words: "is it possible to get this URL working?"
http://www.e-conomic.com/accountingsoftware?parameter=123
instead of this
http://www.e-conomic.com/accountingsoftware?open&parameter=123

We've tried redirect, substitutions - no success ofc :(.

Next in my queue is DSAPI and I'm sure it can solve that problem (at least from documentation) however I'm not able to do that due to my experience with DSAPI and very very low information in the web.

I've played with different events in DSAPI: kFilterStartRequest, kFilterRawRequest and kFilterRewriteURL and tried to change incoming URL from request but did not success with it. Does any of you guys can give me tips :) what I do wrong or maybe there is another solution how to achieve that quest?

Tuesday, February 05, 2013

Nodejs and compression of HTML, JS, CSS

To decrease loading time for pages, it is always nice to minify your HTML, CSS and JS. Also to decrease number of requests we inject our minified CSS/JS directly on our pages (ofc we will do that unless our CSS/JS have small size), so minus 2 requests to all pages.

Now time to write couple lines of real code

1. UglifyJS - compress JS

var uglifyJS = require("uglify-js");

var result = uglifyJS.minify("filename.js");
console.log(result.code);

2. Sqwish - compress CSS

var sqwish = require('sqwish');
var filename=app.get('filename.css');
fs.readFile(filename, 'utf8', function(err, data) {
    if (err) throw err;
    var minifiedCss = sqwish.minify(data)
    console.log(minifiedCss);
})

3. HTMLMinifier - compress HTML

var htmlminifier = require('html-minifier');
var minifiedHTML = htmlminifier.minify(data, {
 removeComments: true,
 removeCommentsFromCDATA: true,
 collapseWhitespace: true,
 collapseBooleanAttributes: true,
 removeAttributeQuotes: true,
 removeEmptyAttributes: true
});
So at the result we decreased size of our pages a lot and also decreased number of requests which is also nice, we all love "fast pages".

Wednesday, January 30, 2013

Node.js first experience and first simple project

From 2013 I've started to learn (as much as I've free time) Node.js. 'Domino/Notes' still my main, however it is always nice to learn something new.

Node.js is a platform built on Chrome's JavaScript runtime for easily building fast,
scalable network applications. Node.js uses an event-driven, non-blocking I/O model 
that makes it lightweight and efficient, perfect for data-intensive real-time 
applications that run across distributed devices.

Together with Andrew Kuba (who guide me how to 'node') we are doing simple website for one game which is very popular right now, we are aiming to have hundreds users/month :) at some points + it is always nice to do something that is real and online
We are using only couple modules for our first application:
  • Express - minimal and flexible node.js web application framework, providing a robust set of features for building single and multi-page, and hybrid web applications.
  • Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects
  • mustache is a logic-less templates.
  • yuicompressor compressor to minify our JS/CSS (we do compress all our CSS/JS and put it directly on page to avoid additional lookups)
  • html-minifier compressor to minify our HTML
We do not use database right now, however we are planning to use mongodb with mongoose in near future.

Pick LoL is our website (first version) we are working on to get some experience with Node.js

During next couple months I will write more posts about node.js which I'm going to like hopefully :).

Monday, December 17, 2012

First couple days with IBM Domino Designer 9.0 Social Edition

Worked 2 days already with Domino Designer 9 (I do not really care about changes in Notes 9, as I believe in 'web' direction). I did not find something really new/impressive for developers, however worked only 2 days and also I do not forget that it is just a beta. My impression:
  • It is fast enough, however I do not feel difference compare to my 8.5.3, perhaps my laptop just too good.
  • Ext Library is included by default.
  • I've also read that now we have an API (Java, LS, C API) for C&S, would be great to have it few years ago, now its too late :), but still thanks!
  • Special places for JAR, I guess it is only for xPages, but not for Java libraries/Agents, need to verify.
  • Server-side JavaScript debugger for use with xPages (need to verify how it works, but options are present, I saw that :))
  • $DesignerVersion still says: "8.5.3" when you save elements. I think that would be changed with Release candidate.
  • There are some new options to "Manage working sets drop-down" I really like, waited for those changes for a long time.
  • Application Properties got 'Xsp Properties'.
  • There are also changes to xPages, but I had no time to look on them.
  • All 'old staff': old window to work with @formula, properties dialog still looks same (and that is sad).
Some words about API for C&S.
I've been working on synchronization Lotus Notes 6.5-8.5 Calendar & Scheduling with huge CRM on my previous job (synchronization in 2 side, from LN to CRM and back) and we spent months to manage that correctly, oh dat recurrent events :), it would help us really a lot if we get such API earlier.

I've read also on some blogs that Domino 9 may have dojo 1.8. which would be nice to have and use.

That's all for now.