Java Beans and funny stuff

I have such a backlog of posts that I have written and have neglected to post, it is not even funny.  I have a few videos that still need to be edited or redone and it is nuts. So first off, I am sorry for the long breaks in posts, but life tends to get in the way.

Today I was working with an apprentice and getting him involved with XPages.  He seems to enjoy it so far, and it is a help for me because I give some of the more mundane things to him.  He has zero Notes/Domino experience and has focused primarily on .NET development.  If you go to derultimativeligatipp.de, you can see a bit of his handy work.  Of course he worked with another apprentice of ours to build that site, and I must say together they built one awesome application.  But I digress.  Of course I think our apprentices are amazing, but we want to quickly discuss our adventures of the day with Beans and XPages.

As readers may or may not be aware, I have spent a great deal of time developing a standard java library that I use in all of my XPage applications for use both internally and for customers.  It includes custom controls, standard beans, and now a configuration.  But a simple configuration was not good enough for me.  Let me quickly get into my use case.

Up until now, I have been using a file saved under the Resources/Files tab of the project.  I wanted to get around needing profiles which can be a cached pain in the rear, I originally did not want to have a view to look up a specific document, and I did not want to touch the xsp.config xml file. Of course there are some wonderful snippets available from Paul Withers in case you would prefer that approach.  I wanted to save values that differ from database instance to database instance, as well as from dev version to QA version to productive version.  As far as I am aware, performing a design refresh also rewrites the config.xml file.  Really the best way to get the functionality I wanted was a good old fashioned NotesDocument, a good old fashioned view, and the wonderful ODA view method “getFirstDocumentByKey()”. #ODAOnceMoreForTheWin .

This brought on interesting points that I could discuss with the apprentice: abstract classes, Beans, and expression language.   I wanted to build the following structure:

AbstractConfig
-contains the view alias for lookups which will be used for all XPage configurations
-abstract init() method
-abstract getLookupKey() method
-a few other methods that are sensible for our use case but may not be needed for all.

AbstractDashboardConfiguration => AbstractConfig (just an example)
-implements init() to fetch the needed data
-protected final Strings for each field in the NotesDocument
-private members for each field value and the appropriate getter/setters

DashboardConfigurationDocument => AbstractDashboardConfiguration (just an example)
-save() implementation
-specific XPage rendering helper functions
-is set up as a viewScope variable

DashboardConfiguration => AbstractDashboardConfiguration (just an example)
-Specific methods to use a re-init interface that I built so that all of my applicationScoped beans can be reinitialized with a click of a button by an admin
-obviously applicationScoped

As you can see, the build up is pretty complex, and this is the easiest of examples.  There are probably a few “WTF?” questions that I should touch upon, so let me get to them first.

First off, I am sure the reason for an AbstractConfig class is clear.  When all configuration documents are already being saved in the same view, then why not.  Certain fields need to be set in order to guarantee that they are displayed in the correct view. Also, why should the name of the view be set in each configuration class?  It just makes sense to have a single abstractconfig java class.  But, the question that probably comes to mind is, why is there a need for another abstract class before the real implementation?

The answer is pretty simple: I hate StackOverflowExceptions.  I started to create two classes to handle configuration information.  One bean would be responsible for saving and editing the information (DashboardConfigurationDocument), and the other would be responsible for caching the information in the applicationScope (DashboardConfiguration).  Without the abstract class I am left with the following conundrum…..

It is clear that DashboardConfigurationDocument should get it’s information from the document… I mean….  it is sort of implied in the name.  It should also save itself. It then needs to inform the applicationScoped DashboardConfiguration bean that it should refresh its data. This data could be read from DashboardConfigurationDocument to get around needing to write the int() function twice.  Right there we have a problem because we have two classes that call each other.  It just makes the most sense that both of these classes have the same key functions and members in the abstract version, and the rest of the key implementation in the concrete classes.  It makes for a much cleaner implementation at the cost of hereditary chaos.  🙂   Truth be told I find it awesome.

The second major question that I should directly address is, why do I just not save the DashBoardConfigurationDocument bean in the application scope? Basically I am a control freak wanting to do crazy things.  No….  I assure you that I have a reason.  Let’s look at lazy admin A and multi-tasker admin B.  Admin A makes a single change, directly in the appScoped bean before going for coffee, and admin B gets a phone call after doing the same.  Neither are finished with their changes, neither of them had to save the changes explicitly, yet both of the have a change that is already potentially putting the application in an unstable state.  Baaaaaaaddddd  vooodooo….  baaaaaaaadddddd.  For this reason, I also like to separate my editing logic from my global configuration logic. Additionally, I can have XPage UI specific logic in the viewScoped class without feeling guilty about caching stupid spam members in the appScope bean.

I can use this pattern as often as I want, and I can be sure that I do not forget anything.  All of my field names are saved as final strings and I can use them in other sub-classes if I need to.  I can even decide later that I want to override my save function in another bean to get SQL support or whatever. It is just clean, and I like clean.

After taking some time to explain a lot of this to the apprentice, we dove into Expression Language and getting some good old binding done.  It worked like a charm…. almost.

This goes into another crazy use case.  I only wanted one configuration XPage.  I have an enum where I have specific configuration keys saved.  These values are then presented to the user in a combobox where a specific configuration key can be selected, and the document is opened, and the information is displayed.  We did this with Expression Language.  The ComboBox held string values representing each of the values in the enum, and the bean had the necessary getter and setter to take the string and set the enum value for that document.  This setter also triggered a process whereby the configuration was fetched and the values were refreshed.  It was a thing of beauty until we realized that the values were not being refreshed on the XPage although the values in the bean were being refreshed with the contents of the NotesDocument.  It took us two hours to figure this issue out.  The correct getters/setters were being called, the init() function was being called, the correct document was being retrieved, and the values were correct in the bean.  Why were they not refreshed on the XPage?

First off, I thought it was a simple refresh problem.  The errorMessages control displayed no errors, and I thought that it was just a simple case of needing to either perform a full refresh, a refresh directly on the component, or some other crazy thing.  We messed around without any success.  In the end, this was one instance where a simple EL expression just was not enough.  We saw that the EL expression was calling the correct methods;  the onChange partial refresh on the page was working correctly.  My suspicion is that the partial refresh was being performed faster than the methods called by the EL expression.  We took out the EL data binding and instead implemented a SSJS function calling the setter method for the configuration key.  When we did this, everything worked as planned.  We also now have one page that can be used for multiple similar configuration documents that can easily be extended without changes in the design.

Lesson learned:  Java is awesome, EL is cool, but ssjs still has to be used for certain things.

About reederProgramming

I already have an about me page, so I will just put a quick bit of info here. I am a Notes/Domino developer at holistic-net GmbH located in Hannover, Germany. I use Java primarily at home and as often as I can at work. I have dabbled in C# and a few other languages and platforms. This website started out as a place for me to quickly store and access some of my most important how-tos and has started to become a place where I can really help others too!
Tagged , , , , , , , , , , . Bookmark the permalink.

2 Responses to Java Beans and funny stuff

  1. David Leedy says:

    Interesting that SSJS got you the refreshed data while EL did not. I’ll have to try that next time it happens to me. I have seen things like that myself. Typically I’ll do a refresh in the onComplete event and that takes care of it. hmmm

    Regarding your config document issues. This is where the hash UNID thing comes in handy. I’ve not used it myself but I definitely would here. You can compute your own unid for a document. They you can use the very fast getDocumentByUnid() method to get it back whenever you want. This would eliminate your need for views to access the config document. And since it’s a document it can be different for your different levels of DB’s.. test vs production…

    Might be something you want to consider checking into.

    Great post!

    • reederProgramming says:

      My idea was to perform the the refresh manually… manually being that I would get the components and set the values with the data I would manually fetch from the bean with the getters. Before I wrote all that out though, I wanted to see what using the setter for the enum value directly would do. That “magically” took care of the entire problem. I didnt think about using the onComplete event, but that more than likely would have fixed the problem as well.

      As far as using that hash unid thing is concerned, I really need to look into that. It sounds like an awesome idea. I still like the idea of going through a view (it is only a get once and forget thing anyway so I am not concerned with a performance hit), because I then have a guaranteed place to easily find the documents in order to look at the document properties. Otherwise, I would need a custom control that creates an HTML table displaying all the fields and values in the document for debugging purposes. Actually, truth be told, the apprentice already has that task on his list. 😉

Leave a Reply

Your email address will not be published. Required fields are marked *