Classic Notes: How to communicate with IBM Connections from LotusScript wrapping IBM SBT with LS2J - Part 2
This part 2 of 3 in the article series “Classic Notes: How to communicate with IBM Connections from LotusScript wrapping IBM SBT with LS2J”.
Read the others here:
I recommend you read that too to get the concepts here :-)
Ok, SBT installed on your machine, and jar files copied and configured on both client and server. Now what?
As mentioned in the start of the article, I now have two classes which must exist in any database wanting to use SBT. Personally I like to have template living on the server with all the design elements. By copying the design elements to the target database, I always answer yes to the question Designer asks about inheritance.
By doing this, you establish a design-relationship between the template design and the code living in the target database. Each time the template design changes, you can simply use File -> Application -> Refresh design to refresh the design in your target database.
At the time of writing the only two needed libraries are:
- classes:SBTJavaHelper100 - The back end Java script library communicating directly with the SBT jar files we have copied to either the client or server in the steps above. The LotusScript programmer won’t use this class directly, but it must be in place since the next class uses it.
- classes:SBTHelper100 - The main LotusScript class containing the class which the LotusScript programmers will use.
Below I discuss each library
A little disclaimer about coding style before we dive into code! I am not that super-fluent with Java, so I tried to copy the style of coding from what I see the SBT-developers do. This concept led me to use a separate package name no.tine.sbt for the code, but the sample would probably have been simpler without it :-)
Also, be sure to visit the Playground (and remember that the Domino database is actually a part in the SBT you just have downloaded, look in the C:\sbtk\redist\domino directory!). It has all kinds of samples, showing how you can code many features in SBT! Invaluable resource!
Below I have opened the java script library, and as you see, it contains 3 classes. The superclass is the SBTHelperBase100.java, which is the superclass for both subclasses SBTCommunityHelper100.java and SBTActivityStreamHelper100.java.
Remember I told you that it is possible to simply copy the files between Eclipse and Domino? This is where you do this. If you have started out your project in Eclipse, right click on the java files in Eclipse…
…and select Copy (this copies the selected files in Eclipse to the clipboard). Now switch to Domino Designer and open the java agent. Right click on the package name at the arrow;
… and select Paste. The selected Eclipse files will now be copied right into the java-agent in Domino. This can of course be done vise-versa too, if you have coded in the java files in Domino first!
Ok, let’s have a look at the superclass first.
It’s main purpose is to be the one and only connection point between the different services I want to expose to the LotusScript developers. Right now the set support the services Communities and Activity Streams. In the future I would probably add support for Profiles, Files and Libraries (the super cool Connections Content Manager/ECM support) too.
In other words, this class is the one and only point where we see the actual connection details, such as the user id and password of the superid mentioned earlier. Other subclasses like the SBTComminityHelper100 and SBTActivityStreamHelper100 then automatically inherit the properties and methods of the superclass.
At the very top, we see all the package and import statements.
The nice thing with Eclipse is that it aids you getting the import correctly. Pay some attention to the suggestions though, as you should end up with com.ibm.sbt-related stuff very often.
Next comes the class itself, starting with the class-properties;
At (1) you see the connection details such as user id, password and URL to Connections. Note the use of https in my case.
At (2) I define the variables for the so-called runtime context. This is one of the main tricks in this code! Why is that? Read more about that in a short while!
At (3) you see how I define support for the four basic Connections services, activity streams, communities, profiles and files.
At (4) I just have some control variables telling me whether I have enabled a service or not.
The main trick!
By just grabbing the code in the SBT and trying to make it work in Domino context, you quickly discover that that the samples contains some so-called managed beans that need to be defined in the src\META-INF\managed-beans.xml file. The managed beans is actually small datastores, that the java code use to grab connection details such as user id, password and connections URL (sounds familiar :-)). When you run the code, it typically crash when the code tries to establish a runtime context
Looking around on StackOverflow.com and other forums, I found similar references to the needed beans now living in the file \WEB-INF\faces-config.xml. To make a long, confusing and frustrated story short, I asked this question on StackOverflow.org and got an answer from Philippe Riand (one of the lead developers on XPages in IBM) where he explains that web-related jobs reads the faces-config.xml while other jobs reads the META-INF\managed-beans.xml. He also suggests several approaches such as creating an endpoint myself, or use an XAgent (a faceless XPage, acting much like an agent - which will read the faces-config.xml from WEB-INF, or use “DOTS”).
The main reason that Domino’s JVM couldn’t pick up the managed-beans.xml is that the Domino’s Java-agent implementation doesn’t have any notion of the folder META-INF. In other words, I can’t get the standard SBT code, which depend on certain folder- and file names being present, to load the file.
My complete constructor there looks like this;
At (1) I create the endpoint and set the variables I mean is necessary to get stuff to work. First and foremost I set the Connections URL with the endpoint method setUrl().
At (2) I attempt to login the superid with it’s password. In production code I would of course retrieve this information from some sort of configuration document or profile document.
At (3) I connect my object to each of the Connections services
The other parts of the SBTHelperBase100 class is just blueprint copies of what the classes in the SBT looks like, so stuff like setEndpoint(), getEndpoint() and initEnvironment() try to do the same stuff as the sample applications.
Right now I also have another helper method named getUserUUID() in the superclass.
This simple method accepts the user’s e-mail address and retrieve it’s unique identifier which must be used when we post stuff to user’s activity streams.
This is one of the subclasses extending the superclass SBTHelperBase100.java. Remember, it inherits all the superclass’ mehods and variables.
The only new things this class brings to the table are a constructor telling what connections-services we need;
At the present time, I enable all services but the files service. The next code snippet is a method that constructs valid JSON based on a set of parameters. I got that idea from this snippet on OpenNTF XSnippets;
The next method is important - it is the one method that is exposed to the LotusScript developer later on. Meet postEntry!
postEntry is the method you see in the first image in this article. It can post an Activity Stream entry to either a person- or community stream. Note that it accepts a set of parameters, such as short title, short content, long title and long content. I don’t have the full idea of where everything ends up in Connections yet, and the parameters may very well change in the future. One thing to note carefully, is that postEntry supports a sourceUser and a targetUser. This means that you can easily tell postEntry() to post something imposing as user A when posting entries to user B. This is only because your superid has it’s super-powers because of the trustedExternalApplication-role in Connections.
Also note that the source- and target users either are person’s e-mail addresses when posting to persons or community uuids if posting to a community. I wrap this much more up in the wrapper LotusScript code in classes:SBTHelper100. More on that later!
At (1) you see that I default the URN to person posting, this is later changed at (3) if the postEntry is posting to a community.
At (2) I resolve the source user based on the input user e-mail.
At (4) I set the targertUserUUID as the input parameter community UUID. I had this construct because I thought I could retrieve the UUID of any community in Connections. It turns out that I can either get all public communities, -OR- the communities that the current id is member of. My superid isn’t member of any communities. This means that a user id currently can’t get the uuid of a restricted community. I solve this by dumping all communities and their uuids directly from the back-end DB/2 database in another project. The community name is then resolved by the wrapper LotusScript code :-)
At (5) I get the user’s uuid based on the user’s email address
At (6) I construct the JSON with the json-helper method
At (7) I create a java HashMap to store the header - note that this isn’t in use anymore, as the real backend ActivityStreamService’s postEntry no longer support the extra header parameter!
At (8) I call the actual doer-method in the ActivityService object from SBT. Believe me, if this doesn’t work, you end up with a stack trace and a java error!
Continued in part 3