« New Basement Shelves | Main| Notes 4 Screen Saver »

NotesSystem and DocumentExtended

Bookmark : del.icio.us  Technorati  Digg This  Add To Furl  Add To YahooMyWeb  Add To Reddit  Add To NewsVine 

Updated version of Domino Extended is now available.

Things are building. Simulating an abstract class in LotusScript started some discussion with Tim Triponcy, who combined the abstract classes with Julian's singleton concept. The result was a System class that would not have to be initialized but could be used by anything that included the script library. I like Tim's concept so much that I had to take it and run, with some minor changes and improvements (at lest from my perspective). I also wanted to take this same NotesSystem (new name) and port it to Java, since I have been doing most of my development in Java for Domino, using Domiclipse (awesome tool). Because Java can access the backend of Domino some of the UI methods have been commented out.  There is one other class that I created called NotesDocumentExtended (DocumentExtended in Java) to make my life easier and so I can be more lazy.

Enough said here are the class overviews

NotesSystem oveview

Private Class NotesSystem
        Public Sub New()
        Public Function hasWorkspace() As Boolean
        Public Function ThisWorkspace() As NotesUIWorkspace
        Public Function ThisDatabase() As NotesDatabase
        Public Function hasDocument() As Boolean
        Public Function ThisDocument() As NotesDocument
        Public Function hasUIDocument() As Boolean
        Public Function ThisUIDocument() As NotesUIDocument
        Public Function ThisSession() As NotesSession
        Public Function CurrentUser() As NotesName
        Public Function CurrentUserCommon() As String
        Public Function CurrentUserAbbreviated() As String
End Class

NotesDocumentExtended oveview

Public Class NotesDocumentExtended
        Public Function getFieldValues ( fieldName As String ) As Variant
        Public Function getFieldItem ( fieldName As String ) As NotesItem
        Public Sub replaceField ( fieldName As String , Var As Variant )
        Public Function getFieldText ( fieldName As String ) As String
        Public Function hasField ( fieldName As String ) As Boolean
        Public Function hasFieldText ( fieldName As String ) As Boolean
        Public Function hasDoc ( ) As Boolean
        Public Function hasDocument ( ) As Boolean
        Public Sub setDoc ( Doc As NotesDocument )
        Public Function Doc() As NotesDocument
        Public Sub setDocument ( Document As NotesDocument )
        Public Function Document As NotesDocument
End Class


Here is the code:

Comments

1 - @9 These are some of the same thoughts that went through my mind when I was creating these classes. The question why Lotus did not add some of these methods is a good question. I can not answer why they did not, and I am not saying that they should, but they would be a 'nice to have'.

I would agree with you and from a web agent perspective I would typically access the document directly. On a scheduled agent running over all or some of the documents in a database a DocumentExtended and/or a ViewExtended could make the code cleaner and simpler. The only reason I say that is because they typically access more fields and more documents.

I have not ventured out into the buisness object yet but I can see where you are going with them.

2 - I'd be very careful about what it was I was trying to achieve. I've certainly wanted to extend the NotesDocument class, and it's sometimes a real pain that you can't, but I can't think of a good way to do it without writing a whole new wrapper to the entire API. If in an agent I was using a generic DocumentExtended object, I would still have to get the Document object and pass it in. What I'd want is a view extended that would give me DocumentExtended back, etc, etc. That's a pretty big overhead. And you also need to ask yourself, why didn't Lotus just make the java api that way. There must be something about what they've exposed that fits with Domino. Be careful of covering that up or you may find you need it at some point.

What I have wanted to do in the past is extend the document so that it also has business methods, representing a particular type of document in my application, say UserProfile, Article, etc. So since I can't extend the domino document I have to be able to pass in the document, either in the constructor or at some other point. I could then make all of my business objects extend that. In this way my DocumentExtended class would take a Document in the constructor, probably storing it in a final variable, just for good measure, and then implement lotus.domino.Document and pass all the calls through to the stored doc. My business classes would then extend the wrapper class and override and overload the methods as appropriate. Obviously I could organise this into farther hierarchies of business object.

What I tend to do now is one of the following:

Create the business objects and have them take a document in the constructor and have the business object know how to deal with the doc.

or

Have the business objects know nothing about domino and have data access objects that load and save them.

What is the best way to do it? It all depends on how complex the application needs to be. For most little agents you can just access the doc. When you start having to create business objects, you will start to abstract the doc automatically, and in a way that is suitable for the app in question.

A DocumentExtended class I used automatically on every agent? No.

3 - Nice, but why are you using Let in your code?

4 - I am glad you like it. The doc and document classes were purposely done just to accommodate everyone.

5 - @3 The let is the formal way of writting it. Most of the time you will not see it.

@4 Thanks Kerr, The suggestions make sense, and I will make the changes. With regards to #2, Here is what Domino Designer Help says

Java has no knowlege of the heavyweight back-end Domino Objects, only the lightweight Java objects representing them. Garbage collection has no effect on Domino Objects unless you first explicitly recycle them.
If you appear to have memory problems, try recycle but adhere to the following guidelines:
- Recycle an object only if it is no longer needed.
- Recycle an object in the same thread in which it is created.
- Recycling a parent recycles all the children.
- In Session, call recycle() only after all other threads exit.
- Where NotesThread.sinitThread() and NotesThread.stermThread() are used, call recycle() before stermThread.

6 - You did exactly what I'd been planning to do next: put in a dependency hierarchy to ensure that only the objects that are needed get initialized, based on which object is being accessed. Keeps the abstract class absolutely as lean as possible. I also agree that the properties are better as functions. Good work!

I also like the idea of the NotesDocumentExtended class... there seems to be some duplication in the functions, though, i.e. setDoc() looks identical to setDocument(), same for hasDoc() and hasDocument(), Doc() and Document(), etc.

7 - Let provides additional readability: you can see at a glance that a statement is an assignment, not an evaluation, and that the assignment impacts a variable that is not an object reference (as opposed to Set). It takes less than a second to include each time, has no impact on performance, and saves time later when troubleshooting or modifying code. In other words, the benefits are the same as those gained by using intelligent naming for variables instead of one or two characters.

8 - @7 I fixed the recycle method, no I did not understand what you meant. I understand your point about the usage of NotesSystem in Java, because Session is available through the agent and if I would write something outside of Notes then the current database would not be applicable. So the NotesSystem needs a little more work

Are you saying that you would never write an NotesDocumentExtended type class? Let's just say that you would, could you post what it would look like or send me an e-mail. I would like see your implementation.

Please keep the comments coming, that is why I take the time to have a blog is to learn from other people.

9 - On the java stuff; some constructive criticism, honest

1: You should only override finalize() when you really need to. see:
http://www-128.ibm.com/developerworks/java/library/j-jtctips/j-jtc0319a.html

If you use it for every doc you access then you are going to cause your GC to have to do a lot mroe work.

2. If you want to have a recyle() method, you should drop your ref to the doc. You can't do anything with it anyway. Just explicity set it to null.

3. Urgh, methods with leading uppercase letters.

Personaly I'd refactor the lazy init into the accessors and just call them. But that's probably a style thang.

10 - @6
You missed the point I was making. After you have recycled the doc by calling doc.recycle() there is no reason to hold onto reference to the doc object. Once it's been recycled you can't use it for anything. therefore you may as well set you're reference to null and allow the java object to availible for garbage collection.

I was having a think about these classes and I'm not sure where I'd see using them would be that helpfull. Are you just trying to avoid writing the classic start to an agent's NotesMain method? What are your real drivers? What would a simple agent look like with these classes and what would it look like without?

You just eat the NotesExceptions, don't even spit them out to a log, System.out or System.err. So how do you know what went wrong when something does go wrong?

The accessor methods can return null so when you use them you can't blindly assume that the value is not null, requiring you to check (before hand using the hasFoo() methods if you want).

You really don't need to worry about recycling docs unless you are dealing with a large number of them, say looping through a view where you get a handle to each doc. I'd be more conserned about accidentaly loosing reference to the DocumetnExtended object, having it gc'd and then finding the doc I have still got a handle to doesn't work cause it's been recycled. Remember session will recycle all its child objects when it's recycled, which happens automaticaly in an agent.

I really don't want to come across as being negative, hopefully you will take these comments in the constructive manor in which they are meant. Again this is just my person opinion, so I'll be checking back to see the counter comments

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)