River – Customer Project 2
River is a workflow application where department heads can create new personnel requests and have these requests approved for human resources to later create positions for them. It is the starting point to a much larger group of workflow applications. It is used worldwide and is comprised of multiple databases and replicas on 15 different servers. The major push for an XPage implementation was that they would like to get rid of the replicas in order to prevent conflicts. Another major draw is that the notes client would no longer be needed and the future prospects of having a mobile version for the ease of workflow operations.
The implementation of River went very well. The problems seen during the Solar project were almost completely eliminated. I very quickly developed a few conventions that aided the development and that I will use from now on. It was not until half way through that I found my enemy, the NotesException and his buddy, “This Object has already been removed or recycled”.
Let’s get technical for a moment and quickly touch upon a few things that I had no idea of before these lovely issues bared their ugly faces. Let’s start with a story. Once upon a time, IBM built Lotus Notes. They used c++ and built an amazing system to store information in a document and notebook style application and people were (more often than not) happy. Eventually, IBM decided to give the developers another tool to create agents with and created a Java API. This API acts as a wrapper for the background C++ objects. I assume Lotusscript does the same. The programmer creates a Java object lotus.domino.Database and it points to a c++ object. One issue however is Garbage Collection. Using Lotusscript, the developer never has to think about clearing memory. In java, it is necessary. For someone who is well versed in java, this is a new concept. After all, the only time a programmer needs to do that is with NIO and IO objects, (Network) Input Output. Files, SQL database connections, and streams must always be closed at the end of a function. When XPages came about many years later, this unintuitive API was still being used. In my opinion, this was a bad call. Because XPages is built on Java Server Faces, Java was destined to be a powerful force in XPage development. Since a lot of developers who had worked with Lotusscript never had any reason to go into Java for most cases, it just became very frustrating. Many were not just learning a new programming language, but were also trying to get a handle on this terrible API.
If you doubt its horror, take a look at a few use cases. The user has a document open in an XPage. This XPage has a function that creates a new document in the background using configured templates located in another database with values located in the current. This background document is then saved to the user’s mail file and sent to the list of recipients as read from other documents in the same database. To make matters worse, the XPage application is a dashboard application and all information is saved in other databases. This is a complicated case, but is not by any stretch of the imagination unusual. In order to solve this, the programmer makes a managed bean stored in the applicationScope to retrieve the templates from the template database. It takes certain keywords or variables from the current document, searches for the fitting template, stores the UNID and key in a HashMap, and returns the template. Everything is recycled and it works well. The second part of the use case kicks in. A recipient list is returned in the exact same way as the template. A search with document keywords is made, the UNID and key are stored in a HashMap for future users, the values are returned, and cleanup is completed. The source database is also recycled, and right there the problems begin.
The first problem can be solved with a little bit of experience. In this example we have two different Java Objects: Mailer and RecipientTemplate. The Mailer has a reference to the source database which is creating the Memo document. RecipientTemplate also has a reference to the source database where these lists are configured. The Mailer has created the Memo, retrieved the body template, and, before it is sent, has called the function in another bean to get the recipients. The next line calls the send method of the memo document object and it fails. NotesException, object has been removed or recycled. After banging your head bloody on the desk, screaming so loud that the people in the basement call to ask if you are alright, and a coffee break later, you read this blog entry to figure out what happened.
The session as far as I can tell keeps a mapping of the c++ objects. This mapping works in a few different ways. In this example, the first mapping introduces the problem that the RecipientTemplate and the Mailer “Database” objects point to the same single c++ object. When the RecipentTemplate recycles its Database object, the C++ object is also ripped from the hands of the Mailer object. But, that explains the database, but we are talking about the memo document being gone. There is also a mapping of the objects stemming from the higher level objects. When the database is gone, the documents, and the objects belonging to the documents are also either recycled or are unusable. I am unsure which. Knowing this, the programmer can move the call to get the recipient list to the very beginning before the memo document is created. The call to the function is successful and you go home happy and feeling accomplished, albeit with a headache and blood stains on your shirt.
Alright, that is not a good solution, so what should be done to fix the issue without risking a server crash? This was a question that took many hours of research to answer. I was once again saying that XPages needed to be buried next to Jelly the hamster. As was with the Solar project, I was frustrated, angry, and just saw no future for XPage development. How can a framework exist that just introduces more and more problems? One issue is solved and another shows up. That is when I found the next little gem released on openNTF.