Disclaimer and License

Opinions expressed here by Tim Tripcony are his own and not representative of his employer.

Creative Commons License
Tip of the Iceberg is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at xmage.gbs.com.

Unless otherwise explicitly specified, all code samples and downloads are copyright Tim Tripcony and licensed under Apache License 2.0.

Search

What the Quote?

"I am angry at digital jump rope."

Ryan Wagner

"There are two major products that come out of Berkeley: LSD and UNIX. We don’t believe this to be a coincidence."

Jeremy S. Anderson

"No means no, Ra."

Tim Tripcony

« reflections on IamLUG and MWLUG | Main| well, it's about friggin' time »

Installing XPage Extension controls in a specific NSF

Category xpages
By now, many (if not all) of you have heard about, and, perhaps, even already installed and begun playing with, the recently released XPages Extension Library. There are a plethora of reasons to be excited about this project, but most can be folded into two categories of awesome:
  1. New controls for you to use and love

    Let's face it: the majority of XPage developers will never write their own controls. Their employer subscribes to the "do more with less" philosophy, so they're behind schedule on ten different projects because they're the only Domino developer at their company who hasn't already been laid off. They want components that already work that they can just drag onto a page, set a couple properties, and have the page do what the component descriptions imply they'll do. If this description fits your situation, but you're excited by the notion of the Extensibility API, it's likely that your excitement is based in the knowledge that, like ASP developers have been able to do for years, you'll now be able to take advantage of functionality that doesn't ship with the product because somebody else wrote extension components, not because you plan to write any yourself. That's what this library provides... and it's free.

    The Extension Library bundles together a sizable collection of immediately useful controls that you can use in any XPage application the same way you would use controls that are already native to the platform: specifically, the icons show up in the palette regardless of what NSF you're in... you don't have to copy these to every application like you do with Custom Control design elements. To get an idea of just how much extension this library represents, consider that Domino ships with 38 pre-defined native controls - Panel, Repeat, Edit Box, and so forth. The version of the Extension Library currently installed on my machine (which, admittedly, is newer than the version that was released yesterday) adds 68 new controls. This library doesn't just add a couple of "Hello World" examples of how one might use the Extensibility API... this nearly triples the amount of controls available to you, and each of these controls is truly useful. Just to further illustrate the point, I'll call out two of my favorites as examples:

    • The "Remote Services" control allows you to easily define a JSON-RPC API for your page. If you read up about JSON-RPC, it sounds complicated, but the beauty of this control is that it makes it simple. You simply define one or more methods as properties of the service control, specify what arguments (if any) each method accepts, and what SSJS should run when the method is invoked. At runtime, the XPage automatically registers a global client-side JavaScript object named whatever you called the service... that object exposes the server-side methods, allowing you to call server-side code from client-side code far more easily than any other approach I've yet seen. And, because the only data being transported between the browser and the server is automatically-encoded JSON packets (you don't have to do that encoding yourself, that's just part of what this control does for you) representing the method call and its response, it's ridiculously performant. So, in short, it's kinda like Web Services with all the stupid removed. And, thanks to the Extension Library, it's now an icon that you can just drag from the palette to a page and define a couple methods. Easy.


    • The Application Layout control will be a favorite with anyone who likes the looks of OneUI, but hates having to remember what CSS classes to apply to all of the many elements that make up the layout specification. Just drag one control to your page, and everything that makes up the layout portions of OneUI are properties of this single control. So you can specify legal text, footer text, title bar tabs, bread crumbs, etc.... all as hierarchical properties of a single control. It's almost as simple as having a wizard for your layout: the property grid guides you through defining the layout of your page, so you can literally design the entire layout for your application in about 5 - 10 minutes.

  2. Real-world examples to inspire your own extensions

    As I mentioned, the controls aren't simply "Hello World" examples of using the Extensibility API, they are powerful examples of using the Extensibility API. So if you do get the urge to strap on your Java boots and try creating your own controls, you can start by analyzing how IBM writes controls - everything from the very simple "Keep Session Alive" control (which just allows you to specify an interval at which the page should ping the server to keep the viewScope active in case the user has left the page idle for hours but still expects to not lose their in-progress data when they return) to the REST services that will allow you to render a view as a Dojo grid that supports in-view editing (this wasn't included in the initial release, but it works on my machine, and will be included in a subsequent release). If you're like me, you'll find it's much easier to start diving into this by first looking at the way IBM approaches "real" use cases, and then model your own controls after their approach, than to stare blankly at a javadoc and try to guess how it all fits together.
With that context established, I've been asked by several folks to share my approach to storing control definitions directly in an NSF, bypassing the plugin installation process. Since I'm so fond of lists, here are two reasons why this can be useful:
  1. Some admins adhere stubbornly to the principle of not allowing any modifications to a server, to the point of missing out on the spirit of that principle: maximizing the end user experience. Naturally, if a server has been mucked with in a way that negatively impacts reliability, that is A Bad Thing™. Conversely, however, if an admin refuses to put a JAR file on the server simply because it's not part of the standard Domino installation, and "that's against our policy", even though that particular JAR would allow a developer to provide users a better application in less time, this also is A Bad Thing™. Nevertheless, if you are at the mercy of such an admin, this will allow you to provide enhanced functionality to your users without the admin having to violate their sacred policy.
  2. While installation of a control library is fairly easy (step one, install it as an Eclipse plugin into Designer, just like you'd install any other Eclipse plugin; step two, add any JAR files contained in the plugin to the plugins folder on the Domino server), when you're writing your own controls, the testing process is horribly tedious... tweak your code, build the plugin, uninstall it from Designer, restart Designer, reinstall the plugin, restart Designer, test, repeat until it works. Fun. This is, of course, assuming that you're not one of the three people on the planet who have figured out how to correctly configure Lotus Expeditor in a standalone copy of Eclipse (NOTE: I am not one of those three people). Hence, this allows you to reduce that to a mere two steps (apparently this post was brought to you by the number 2... and the letter X): write some code, test it. Much, much simpler. When the control is working the way you want it, then you can move it out of the NSF and into a real control library, so you don't have to copy it to every NSF... just install the library. But in the meantime, you can test changes immediately after you make them without having to go through all the hassle of treating it as a real plugin.
To stretch the binary nature of this post just a bit further, there are really two types of files that comprise any component's definition: Java and XML. A Java class (and any other classes it might reference) defines the control's behavior, and XML files expose the existence of these controls to Designer (and the XPages runtime). The XML files can, again, be subdivided into two types: faces-config.xml and .xsp-config files.

If you've gone spelunking in the Package Explorer, you've likely already stumbled upon both of these types of XML files, because Designer automatically creates these for you as you're developing your application. The faces-config.xml file is created in WebContent/WEB-INF, and while I've never actually seen Designer contribute any content to it, it inserts a commented section where it would place its own contributions if needed. So if you're defining managed beans, for example, this is the file where you'd store that definition... so be sure to place that definition outside of that commented section. Any .xsp-config files automatically generated by Designer will be located in the CustomControls folder. Whenever you edit an XPage, you're really editing a .xsp XML file that tells Designer what Java to automatically generate for you. When you edit a Custom Control, however, you're really editing two XML files - the corresponding .xsp file, and a .xsp-config file that tells Designer that control exists. In fact, the existence of that .xsp-config file is really the reason that the icon for the Custom Control shows up in Designer; if the Java file that corresponds to the control didn't exist, it still wouldn't show up, of course, but even if it did and Designer hadn't created the .xsp-config file, the control would exist but Designer wouldn't know that.

Hence, the easiest way to include extension controls in an NSF without properly installing a control library is to simply create a linked source folder: right-click the application's folder in the Package Explorer, then select Build Path, Link Source. Browse to the top-level source folder (typically called "src") for the control library, set a folder name that will be unique in the NSF, and click Finish. In the case of the Extension Library described above, at a minimum you'll probably want to link the core plugin ("extlib"), "extlib.domino", and "extlib.oneui", but there's some other cool stuff in there as well (for instance, "extlib.dwa" includes the iNotes Calendar view as a control... let that one sink in for a moment...).

Because both the Java classes and the corresponding XML files are contained in subfolders of your linked source folder, as soon as your application finishes rebuilding (which will take a while, especially if you're linking to several of these plugin folders), you'll see the icons for the controls show up in your palette. Be warned, however: since a lot of these controls are fairly sophisticated, actually using them without properly installing the plugin is going to be hit or miss. There's a lot of other stuff going on behind the scenes that the OSGi framework allows which you can't really take advantage of unless it's treated as a true plugin. But here's something that might help: if you locate the faces-config and xsp-config files for each of the plugins you linked to (in each case, they'll be stored in a META-INF folder inside the src folder), drag them into WebContent/WEB-INF in the NSF. This ensures that they're actually stored inside the NSF and not just in the workspace folder in your Notes installation. I've found that, for some of the controls in the Extension Library, this is perfectly sufficient. But here's another word of warning: if you do take this linked source approach - at least with the Extension Library, which contains approximately 800 Java classes - every time you make any change to any XPage, the build process is going to be sloooooow, because you've introduced an additional layer of complexity into what Designer has to do in order to determine exactly what code the application contains. So you've circumvented the admins. Great. You've also just punched your productivity in the face if you don't have an SSD.

There is good news, however: on an individual control basis, there's a much better way. Add your own src folder to WEB-INF, designate it as a src folder, and create your control classes within that folder. Then add a .xsp-config file for the control to WEB-INF and, if needed, define its renderer in the faces-config.xml that's already there in the same folder. That works like a charm.

There are additional caveats, of course. The most obvious is that this is fine for a couple controls here and there, but gets unwieldy when you're maintaining large sets of controls, since you have to copy several categories of files to every NSF where you want to use them. In other words, I'd advise against taking this approach for the entire Extension Library. If there's a specific control you want to use, and you can isolate every Java source file it uses and know that it's not also relying on images, CSS, and JavaScript libraries that are bundled with the plugin (yes, you can do that... this is some of the "other stuff going on behind the scenes" to which I referred earlier), go for it. But if you're looking to pull in something as complex as the JSON-RPC control or dozens of simpler controls... just take the blue pill and walk away.

Much less obvious caveat: if you're configuring your control this way for testing purposes - for instance, you've already got a plugin library installed, and you're just developing a new control that you want to add to it - this works fine as long as the control is an extension to a native component (UIComponent, UIInput, or one of the core controls that ship with Domino). If, however, you're extending an extension (maybe you dig IBM's Dialog implementation but want to automate the addition of OK and Cancel buttons), the Java class for the base component must be directly in the application's build path - not in the plugin dependencies - even though at runtime the classloader would be able to find it. If Designer can't find it in the build path, the icon won't show up in the palette. Yes, I learned this the hard way.

Comments

Gravatar Image1 - Tim, great article. Just one comment regarding "tweak your code, build the plugin, uninstall it from Designer, restart Designer, reinstall the plugin, restart Designer, test".

You don't actually have to restart Designer twice and you don't have to uninstall the plugin. You can simply export the plugin(s) from your Eclipse IDE to C:\notes\framework\extlib\eclipse and then restart Designer via 'designer -RPARAMS -clean'.

In order for this to work you have to do some setup:

1. Create C:\notes\framework\rcp\eclipse\links\extlib.link with this line: path=C\:/notes/framework/extlib which is the dir to which you export your plugins.

2. And for security reasons, the Notes client does not accept plug-ins installed this way without modifying the file data/workspace/.config/org.eclipse.update/platform.xml.
See { Link } page 9 for what you have to change in that file.

Gravatar Image2 - Thanks, Niklas! I'll give that a try.

Gravatar Image3 - I am absolutely in the 1st group. It sounds like you were describing me. Only Notes/Domino dev left trying to do more with less describes things exactly.
Are you spying on me? Emoticon

The added controls this provides are going to save me some work and allow better apps.
I would love to learn more on how to create these myself, but I don't think I can find the time to do so.

Gravatar Image4 - Hi, I have a rather silly question..
If i embed the library within the nsf, would that allow me to run the app (with the new controls) on a 8.5.1 server?
I would really love to use the controls, and can't wait for the admins to upgrade this 3 months later...?

Gravatar Image5 - @Rakesh - it's highly unlikely. Prior to 8.5.2, you can define your own controls in this way (create a Java class that extends UIComponent and register it as a component in an xsp-config file)... in fact, that's how Medusa is currently packaged. However, many of the controls defined in the Extension Library use API methods introduced in 8.5.2, so they would not even compile correctly if added directly to an NSF using Designer 8.5.1; if added using Designer 8.5.2 but deployed on a Domino 8.5.1 server, they would compile but would not run.

It sounds like you're in a common situation: your admins are the primary obstacle between your users and the type of applications they could be using. If it takes them 3 months to deploy a maintenance release of Domino, your best option is to confront them with the truth: "you're doing it wrong".

Gravatar Image6 - Requiring a customer Admin to install an open source library on ther server for our applications to use will be a non starter.

Either the customer will be large and forbid it or they will be small and not have the skills ( I am being a bit simplistic but you get the idea ).

The extensions look brilliant but there adoption will be hindered by these issues.

Gravatar Image7 - Sean, I fully agree: there will be many organizations that will miss out on the enhancements to developer productivity and application functionality that this library offers (for free) due to the considerations you mentioned.

But I'm curious about your assertion that some admins might "not have the skills" to perform the installation. For the record, here is the entire process:

1. Place the JAR files in:

[data]/domino/workspace/applications/eclipse/plugins

(where [data] represents the root of the Domino data folder, i.e. C:\Domino\data)

There is no step 2... unless you count restarting the HTTP task.

There is no installation wizard. There is no command line kung fu. If the admin has ever dragged files from one folder in Windows Explorer to another, they have the skills. If not, they shouldn't be allowed anywhere near (physically or digitally) a Domino server, regardless of the organization's size.

I'm well aware that there are still many organizations who have a fundamental distrust of all things open source { Link } . I have seen (in person) a publicly traded company spend ridiculous amounts of money on a buggy proprietary software package instead of adopting a superior free solution solely because the latter was open source... one of their executives thought that meant that their public website would get hacked because a tool they'd be using internally to publish content to the site would be open source, and therefore "insecure", despite being informed that the actual content of the site would be the same regardless of the tool used to publish it. He wouldn't budge.

This same organization had a blanket ban on the use of instant messaging (even Sametime) because "it's a toy". So lots of employees would get up and walk all the way across the building to ask someone a quick question because "he's on the phone and he never answers email". Or, in some cases, they'd shout at each other over cubicle walls. It was ridiculous.

So I shouldn't have been surprised to find out, 6 months in, that the entire project I'd been brought in to help with was the result of a misunderstanding. One end user who had the IT VP's ear wanted a couple features added to a Domino application. The VP misunderstood what she was asking for and instead commissioned a complete rewrite of 24 related applications from the ground up. There were 7 of us writing pretty cool, fairly innovative... and ultimately pointless code. We were doing good work, but none of it had been necessary. Millions of dollars were spent producing something the users hadn't even asked for.

Assuming the same folks (or others of their ilk) are still in charge, it's a safe bet that their developers aren't allowed to use the Extension Library. This means that they have to choose between taking longer to develop a certain feature because they're having to develop functionality that IBM has already written for them (for Pete's sake, the mail template is open source, in the sense that the code isn't buried in DLL's... it just doesn't have an Apache license attached to it, and it ships with the product) and not bothering to implement that feature at all. In either case, end users suffer and money is wasted. Which is particularly wasteful there for two reasons.

The first is that they have talented developers. At least two of the guys I worked with at the time are still there, and they're good at what they do. Sure, it's wasteful to have an entry-level developer struggling to figure out how to code something that, were they using the Extension Library, would just be drag-and-drop, but in my opinion it's even more wasteful to have an experienced developer reinventing a wheel when they could be building really powerful stuff on top of an already fully-formed wheel.

The second is that this just so happens to be a health insurance company. Now, before anyone goes all midterm on me about the politics of health insurance, I'm well aware that what follows is the epitome of hyperbole.

But consider this: if health insurance companies are making wasteful decisions on principles that sound good but in practice don't really apply to the decision at hand (for example, HIPAA is a very real and very important consideration in many decisions a health insurance provider makes, but should have no bearing whatsoever on whether or not to leverage the Extension Library), and as a result they're losing millions from reduced developer and end user productivity, and even large scale development projects that serve no purpose whatsoever, then they can either accept a smaller profit margin, or they can jack up their customers' premiums. If the latter occurs, it's not entirely outside the realm of possibility that there's at least one person somewhere who could have afforded insurance at cheaper rates that instead went without; he later contracted some illness that, if diagnosed early on, would have been treatable, but because he had no insurance, he couldn't afford to go to the doctor, so he didn't even know he was sick. And now he's dead.

Please don't misunderstand me: I'm not implying that, unless every Domino shop uses the Extension Library, people will die. That's so morbid. My point is that if you dig into the reasons why a company will tell its developers they can't add a couple JAR files to a folder on their Domino server, in many cases, you'll find that the policy that decision is based on is either entirely arbitrary, or used to be a good idea but ceased to be sometime in the mid-90's. And, if you dig even deeper, you're likely to find that all manner of decisions are being made for similar reasons. Decisions that have consequences. There will absolutely be organizations that forbid the use of this free resource... and I can't help but feel a little bit sorry for their stockholders and customers.

Gravatar Image8 - Tim, I agree with what you have said but it doesn't change the reality on the ground.

I am running CENTOS and Ubuntu development servers on 852. I am getting a lot of crashes with memory problems. { Link }

The opensource platform may not be the problem ( personally I don't think that it is ) but my non standard configuration means that I cannot call on IBM support for these servers. If I were a large corporation that would be an unacceptable situation.

I can understand why enterprises want vanilla supported configurations.

In terms of the skills piece I have customers on iseries with no iseries skills and infrastructure contractors who charge a lot. The Notes admin is all done in-house via the client.

I agree that the placing of files is easy but if I were a jack of all trades administrator I would take a lot of convincing to add files to any server having had my fingers bitten from previous changes ( not necessarily Domino related ).

The other aspect is that ISVs will be reluctant to fork their code for some customers that have the extensions and some that don't.

Sean

Post A Comment

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