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 timtripcony.com.

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

Search

03/26/2014

"Do I Need to Learn Java?": a brief conversation with a composite character

Category java
Do I need to learn Java?

To sustain life, one must rather frequently breathe, eat, drink, sleep, and excrete. Everything else is optional.

No need to get sarcastic.

I'm not. That's the truth. Almost everything we do is superficial, designed to make life comfortable, convenient, entertaining, and fulfilling. But everything we do beyond attending to raw survival is optional; it serves only to further our pursuit of what we assume will be more pleasant than a lack thereof.

So... um... I don't need to learn Java? I though you said I did.

Then I apologize for miscommunicating.

It's okay, maybe I just misunderstood. Should I learn Java?

It depends.

On what?

First and foremost — really, beyond any other consideration — it depends on the size of your team. If you are the team, then yes. You should learn a little bit of Java, a little bit of JavaScript, a little bit of CSS, and a lot about the many frameworks out there that allow you to write as little of each as possible while delivering something visually and functionally elegant to your customers. If you're writing tens of thousands of lines of code — in any language — it's quite possible that you're reinventing a wheel in there somewhere... duplicating the efforts of some very smart people you've never met.

If your team typically contains at least one other person, examine your strengths and preferences. It's very liberating to have at least one person who can focus only on what the app looks like and at least one person who can focus only on how it works behind the scenes. When each person can be doing the work that feels most instinctive — and, yes, even fun — to them, end users' needs can be met in a fashion that delights them without those responsible for delivery devaluing each other for not necessarily being quite as passionate about one specific facet of the end-to-end solution as another might.

But, again, if it's all up to you, then strike a balance. The "right" code is rarely the "ideal" code: it's the code that meets the needs given whatever constraints are in play. And being the only one responsible for delivering the entire solution is a rather significant constraint, because it's up to you to make sure that you're not devaluing any aspect of that solution — security, reliability, performance, scalability, accessibilty, or the overall experience your users ultimately have using the app. Each of those elements is crucial, and the more languages — and frameworks — you have obtained a comfort level with, the more easily you can ensure you're placing sufficient emphasis on each.

Sounds like I still have a lot to learn. That seems kind of daunting.

I know, right? Isn't that awesome? I've been doing this stuff for just over 16 years, and rarely a day goes by that I don't encounter something that makes me feel like a novice again. I'm constantly reminded how lucky I am to have found a career that's always fresh and new, constantly changing, constantly evolving. Some of the alternatives I'd considered when I was younger are comparatively static: once you learn how to do it, you're done learning. You just do the same thing over and over again, day after day, year after year. How boring. Isn't it awesome that the moment we're tempted to think we're experts at what we do, something new comes along and we get to discover that too? And people actually pay us to keep learning?

When you put it that way, it does sound more exciting than scary.

Good. That's how it should be. Or rather, how it really is. It's sort of instinctive, even for those of us who love learning new things, to assume that learning something new is a scary thing. For me right now, it's Scala. I'm honestly a little freaked out about wrapping my head around that language. I remember going cliff-diving with some friends a long time ago in Colorado. I stood on the edge looking down at the water, my heart pounding. Then I jumped, and the fear turned to exhilaration. I climbed out of the water and ran back to the top. And immediately the fear came back... but this time it was mixed with the memory of the exhilaration. I know it's a bit corny to be comparing cliff-diving or skydiving — or anything else that seems scarier than it is until you actually do it — to learning a new programming language, but it's not entirely dissimilar.

I guess I just have one remaining obstacle: my job is so demanding, it feels like I don't have time to learn all of these technologies at once. They want everything done yesterday, so it's hard to learn on the job, and they never approve any training requests, so anything I learn, I have to teach myself... and my employer doesn't really provide any incentives for me to even bother.

All the more reason to be able to list competency in these technologies on your resume without lying. Software development is an enormous industry. It's unlikely to shrink in the foreseeable future. While the prevalence of various programming languages differs based on who you ask, nearly every recently published analysis places both Java and JavaScript fairly close to the top of the list. The more solid your comfort level with either — but preferably both — the more likely it is that you can find a better job where you're rewarded financially and otherwise for your skills and passion. You may have to occasionally forgo watching your favorite crime drama or sporting event in favor of online tutorials in order to spend a few evening or weekend hours each week gaining confidence in these languages, but imagine how much more relaxed all your evenings and weekends will be by comparison once you're no longer spending at least 23.8% of each week being systematically devalued by your employer.

If that sounds appealing to you, then I'd urge you to specifically examine mobile technologies. Domino may be around forever. It might not. Mobile isn't going anywhere. This technology has truly arrrived, and now that it has, the consumer market will not let it leave. The emergence of "wearables" is one of the latest indications of how the underlying technology might evolve and where else it might spread, but that underlying technology is not going to just disappear. While toolkits abound for writing mobile apps in JavaScript and then compiling them into platform-specific containers, end users can tell the difference, even if they aren't conscious of what they're sensing. The "experts" agree: the best mobile apps target each platform separately, and are written in the native language of each platform. For iOS, that's Objective C. For Android it's (melodramatic drum roll) Java.

So here's just one of many possible ways you could get a job that rocks: watch this awesome video tutorial on Android development. It consists of 41 separate segments totalling 13 hours, but the last 9 (roughly 2.5 hours) are specific to the Samsung SDKs, so by all means, feel free to watch those too... but at a minimum spend 10 hours watching everything up to that point. If you can set aside one hour each weeknight for this, you're finished in two weeks. You won't be an expert on Android development by the end of those two weeks, obviously. But if native mobile development has ever seemed scary to you (like it did to me this time last year), it won't any more. And maybe you'll be really excited about it... maybe enough to spend a few hours a week building experimental apps. And maybe after 6 months of that, you'll feel confident enough in your grasp of the platform to tell your current employer to go......... easy on whoever they hire to replace you because you're leaving to join the Android development team at some exciting new startup. And maybe you'll create the next MySpace / Twitter / Facebook — MyTwitFace, perhaps — and can spend the rest of your life hiking the Alps or drinking cocktails with umbrellas somewhere in the Caribbean.

Or maybe the comfort level you acquired with Java while experimenting in your free time with native mobile development makes it easier to identify ways to occasionally apply a few of the same principles in your XPages, and maybe over time that simplifies your process enough to where your job feels just a little bit less demanding than it used to. And maybe that's enough.

Either way, that's probably worth committing yourself to an initial 10 hour investment... right?

02/21/2014

I finally know what a component's "binding" property is for

Category xpages
If I ever tell you, face to face, that I know everything there is to know about XPages, I beseech you, please take my keys and call me a cab, because I'm clearly not thinking rationally.

Case in point: from time to time, as I'm setting properties on a component via the "All Properties" panel, I accidentally hover over that mysterious property named "binding", and this hover help appears:



I read the explanation and remember that I've been intending for years (yes, years...) to find out what that property is actually used for, but I'm busy right now. I'll research it later. And then I promptly forget again. I'm not sure how many times that exact sequence has occurred. Many.

Well, mad props to Cameron Gregor, who told me precisely what it means. And it's simple, but has some interesting potential benefits.

We XPage developers are fond of talking about binding components to stuff — documents, beans, and so on. But that's not actually what we're doing. We're not binding components to those things. We're binding their values. Consider the following representative markup:

<xp:inputText value="#{currentDocument.subject}" />

This indicates an edit box that is "bound" to an item on a Domino document, right?

Wrong.

A better description of the above markup is an edit box whose value is bound to an item on a Domino document.

02/04/2014

workaround for severe screen sharing bug in Mavericks

Category skype
I love my MacBook Pro... once you go Mac, you never go back. Unfortunately, there's a massive problem with screen sharing once you've upgraded to Mavericks: models that have both an "integrated" (low-power) and a "discrete" (high-power) video card started using a feature that Apple calls "Dynamic Switching". This feature attempts to maximize battery life and other aspects of OSX performance by toggling between the display modes depending upon what you're trying to do at the time. As a rule, you don't notice when this is happening... "it just works".

...until you try to share your screen via Skype, GoToMeeting, join.me, etc. Within a few minutes (although the actual duration is unpredictable), you'll either be logged out of OSX without warning, or your entire screen will lock up; in the latter scenario, you can still talk to other meeting participants — you can hear them, they can hear you — but suddenly your mouse isn't moving anymore, and the only way to get back to normal operation is to hold the power button until the machine shuts down.

In my current job, I spend a significant amount of time sharing my screen with coworkers and customers. As you can imagine, this bug was extremely frustrating for me... until I found gfxCardStatus.

This simple utility adds an icon menu to the OSX menu bar, allowing me to change from "Dynamic Switching" to "Integrated Only". Now I can share my screen without incident, and I'm back to loving my Mac.

02/02/2014

the more essential it is, the less passionate we are

Category musings
As I am wont to do, I will be resorting in this post to analogies that make it easier for me to wrap my head around complex abstract ideas but ultimately distract from what I'm attempting to convey, trusting to your capacity to peer through the haze of metaphor and gauge whether anything of substance lies beyond.

Nearly all of us know at least one individual who is passionate about food. Most of us also know at least one person who is passionate about some form of drinking. Do you know anyone who is passionate about breathing? If so, are you ever tempted to write them off as "a bit odd"?



At least once a month, you must eat. At least once a week, you must drink. But go more than a couple minutes without breathing, and — unless you're David Blaine — the most likely result will be brain death. These are just cold, hard, facts. And yet, if you give me an enjoyable dining experience, it's likely that I'll remember it, and possibly even tell a few friends that "oh my goodness, you have to try this restaurant"... but improve my air quality by 20%, and I probably won't even notice.

I was recently in Orlando for a few days. I wasn't attending the IBM Connect conference (and no, this wasn't an act of rebellion on my part, just an attempt to balance some personal and professional priorities), but most of the people I was there to visit were. And quite a few of them were tweeting on Monday morning about something being referred to as "Mail Next". The reaction was very mixed. One sentiment I saw expressed by many was relief that IBM was acknowledging that email isn't dead.

Of course it isn't. Email is essential.

Some have learned to go without it entirely, and, frankly, I applaud them. But almost any time I hear any discussion of an individual or organization who has completely eliminated email, it's framed as though that is an act of rebellion. It's very counter-culture — hipster, if you will — to be at "Inbox Zero" indefinitely.

Admittedly, I'm fairly close to that. In an average day, I get maybe two to three work-related emails. In an average week, I get maybe two to three personal emails. I haven't explicitly instructed people not to email me. Perhaps I've sent non-verbal signals that somehow discourage others from contacting me via email. Whatever the reason, email remains absolutely necessary for me, but how could I possibly be passionate about anything that makes email "better"?

Conversely, the bulk of my professional communication is siloed not to my email account, but rather to applications.

Tangentially professional is my participation on stackoverflow. As one way of giving back to the platform, and community, that pays my bills, I try to answer at least one to two questions a week. But I also comment on questions that I don't officially "answer". All of that communication is, therefore, contextual. And, months, or even years, later, people I never directly interact with can view that communication without hacking into my email account.

Arguably the largest persistent store of communication between me and those with whom I currently interact professionally takes the form of commit logs within source code management systems (e.g. git, Mercurial, etc.). At the end of most weeks, in fact, this is how I know what to put on my timesheet: I open up SourceTree and, in addition to the long-term value of being able to see how a given piece of software took shape, it also reminds me of what I was doing the past few days... and, in full candor, if I weren't tracking that somewhere, I couldn't possibly remember.

Additionally, some of my customers use project management systems. While I do receive email notifications from some of those systems, I don't include those messages in the approximated statistic I previously mentioned... because the only purpose of these messages is to alert me to new communication that resides in that context, so I typically delete those messages within a few minutes of having received them. A push notification on my phone, which disappears the instant I acknowledge having seen it, would have achieved the same goal: I know there's something somewhere else that I should look at, so I do. Once I have, the notification itself has served its purpose and does not need to persist.

Admittedly, if my email account (or software) evolved to somehow pull all of this into a single place, a single window into the process-contextual applications wherein I truly collaborate with others... okay, yeah, I might get a bit excited about that. And, if I'm correctly interpreting what I've read and heard (absent the full context of the conference, which may have shed additional light on the intended direction), this might be precisely what "Mail Next" will attempt to become.

If it does, it's no longer mail.

I recently made a statement that seemed to resonate with a few people:

"In the real world, an excess of email is always evidence of an immature app ecosystem."


Here's what I meant by that: if you're receiving (or sending) hundreds of email messages a day, or even just dozens, that's because there's no other mechanism in place that feels easier, more instinctive, and more effective for facilitating that communication. Conversely, if you have the "right" apps in place — apps that each target a specific business process and / or community — the only value that email can possibly provide is to further facilitate interaction with those apps. Ergo, the more valuable your email is, the less mature your app ecosystem must be.

Why am I droning on and on about this? Because I am simultaneously dismayed and encouraged. For far too long, I've felt that IBM doesn't grasp the significance of an app ecosystem to a well-functioning organization. I've often attributed this to their sheer size: like Grawp in corporate form, they mean well but simply can't comprehend how to interact normally with any creature that isn't also enormous. But more recently I've also attributed this to the comparative difficulty of selling potential vs. the ease of selling actual. Imagine yourself as the salesperson in the following exchange (pun intended):

"You should buy our email platform."
"I know what email is. We already have email."
"Ours is better."
"Oh, okay. Here's a large stack of cash."

Now try selling apps:

"You should buy our custom app development platform."
"What does it do?"
"It lets you build apps."
"Like what?"
"Um... well, anything you want."
"Okay... like what?"
"Well, imagine any app you might want to create, and our platform will let you make that happen."
"I don't have an imagination."
"Oh... crap. I don't either. You should buy our email platform."

I'm not saying that's what actually happens when IBM tries to sell Domino... but I assume that it's more difficult to convey the value of something that lets you do anything you can imagine than it would be to convey the value of something that only takes the shape of something all of us already recognize — and, therefore, we don't need to imagine because we can, instead, simply remember. Even if you were to provide some examples of truly valuable apps that your platform enables customers to deploy, you risk giving the impression that this is all the platform can do.

So I can sympathize with the temptation to cling to an obsession with email and focus on improving its value in an attempt to make what must already be an easier sale than selling a custom app platform even easier. But the way in which they seem to be pursuing that improvement risks revealing the truth about email: it no longer matters — or, at least in the context of professional collaboration, it shouldn't. If it does, you're missing some apps. If "Mail Next" is awesome, therefore, it's because those apps do exist, and instead of a traditional inbox, you now have something that makes it easier to use those apps.

In short, without the apps, it's still just email. If customers have nothing to pull in to that central context, the improvement is incremental at best. There's nothing here to get passionate about.

So what's the good news? While many were so impressed with what they did see that they just assumed it would no longer be on Domino (running, presumably, on some flavor of Websphere instead), that's apparently not the case. In a sense, this would become the new iNotes. But a rumor I've heard is that Domino as it exists today can't even do everything it would need to do for Mail Next as currently proposed to even function within Domino. This implies that Domino is about to get better again. It's been getting better at a far faster rate than it used to, and that's awesome. And if Mail Next is the sales catalyst that gives the programmability folks the leverage to implement some awesome features that can, in turn, be used by app developers to create even more powerful functionality than we already can, huzzah.

But what I'm even more excited about is the likelihood that IBM actually does realize all of this, that they've learned the lesson that, by all appearances, is still lost on BlackBerry: superior messaging is insuffcient to maintain market share. You need passionate customers. And passionate customers have a thriving app ecosystem. This is what IBM will be most heavilly focused on as Domino, SameTime, Mail Next, and what we already know of as Connections, all just become Connections. It will become easier than ever for custom app developers to give IBM's customers an app ecosystem that fosters the passion that ensures that the IBM collaboration software stack plays an integral role in those customers' long-term success, because this is IBM's number one priority for the future of that software stack. This needs to be true, so I choose to believe that it is.

02/02/2014

imagine

Category passion

12/18/2013

Beyond Documents, part 2: a futuristic example

Category design
The aim of this series is to explore why it's instinctive for those of us in the Domino world to conceptualize everything in terms of "documents", as well as to ask what potential benefits might be open to us if we were to move beyond using the notion of a document as our fundamental unit of abstract thought.

In part 1 of this series, I asked why our first instinct as Domino developers is to base our entire conception of our applications on the notion of a collection of documents, and presented my theory on why that's currently the case. I also hinted that there's an alternative to maintaining that conception.

Why would we ever bind XPage components to anything other than a "document"? Let's examine a notion that (currently) is so futuristic as to be a bit ridiculous in the hopes that it will elucidate a few implications. In subsequent posts, we can take a look at how the same principle can be applied even today to make our applications easier and more pleasant to design, use, and support.

Imagine a world in which advances in gene therapy allow a person's eye or hair color to be changed without, respectively, contact lenses or dye. Rather, technology is developed -- and later commercialized -- that actually changes the color at a genetic level. Customers can decide, for example, that they want green hair and purple eyes.

You have been hired to develop an app that will allow customers to schedule the surgery in which these genetic changes will be applied. Should be easy, right? It's just a "form" with a few "fields". One can even envision what the UI might look like: you'd probably want a date picker for them to specify their preference for the day of their appointment, a checkbox group to indicate whether they want to change their eye color, hair color or both, and then radio buttons or combo boxes to allow them to choose from a constrained list of available color names for each of the modifiable characteristics. Simple. Each of these components is bound to an item on a document: specifically, the record that represents their request for an appointment for surgery.

But the document is not your customer's goal. Your customer's goal is to have green hair and purple eyes. Your customer doesn't ultimately care whether a document is created. They want to change something about their own appearance. So, while our instinct for such a simple "form" is to make the entire user interface look like a paper form, wouldn't it be much more engaging for the customer if part of the UI was a picture of them?

Imagine your app integrates with the camera on the customer's device: they take a picture of how they currently look, and photo analysis determines where their hair and eyes are, allowing you to define click targets. Clicking on the specific portion of themselves that they want to alter pops up a tooltip dialog or interface equivalent that includes a color palette. As the customer hovers over any color swatch in the palette, their photo is immediately updated to provide a preview of how they would actually look if they chose that particular color for that particular attribute. Clicking their favorite updates the component's value.

Is it within reason to assume that customers would be more excited by this type of UI -- and, as a result, more likely to go through with purchasing their desired modifications -- than they might be if the UI were just a grid of fields? I admit, I would find it a bit disturbing if this technology ever emerged, but I'm assuming this analogy makes a vivid point about why thinking beyond documents to the reason documents exist can alter our conception of an ideal user interface.

Next let's extend this theoretical technology even further. Inspired by the programmable tattoo technology that already exists, your employer invents a way for your customers to genetically alter themselves at will. Now that customers no longer have to schedule a surgery -- they simply choose a new eye color and their eye color immediately changes -- what changes do you need to make to your app?

Despite your fancy UI in the initial version, maybe your components were still bound directly to "fields" on a "document". Assuming this is an XPage app, and your document data source is named customer, you might have EL expressions in your source that look something akin to the following:

#{customer.leftEyeColor}
#{customer.rightEyeColor}


The customer isn't thinking of their interaction with the app as a document, they're thinking explicitly in terms of their own physical appearance... but your data model is still thinking of your customer -- a human being, with certain named attributes whose properties can now be programmatically altered -- as a document. But what if it didn't?

What if, instead, your entire data model was focused on your customer? What might that "look" like?

Assuming, again, that this is an XPage app, you would probably define a Java class. Ideally, it would be a bean; it doesn't necessarily have to be a managed bean, but it should adhere to bean conventions. If this class has properties like leftEyeColor and rightEyeColor, and the class instance -- whether defined as a managed bean, a data context, an object data source, or exposed by other means -- is accessible via a variable named customer, your EL expressions should instead be:

#{customer.leftEyeColor}
#{customer.rightEyeColor}


Oh wait... they already are. Okay, never mind.

So what needs to change in your Java class? In the original version of your app, the class presumably has methods like load() and save(), which (respectively) retrieve and store information about the customer. That information is stored on documents in a Domino database. In the new version, the information is stored on a microchip implanted in the customer. The team who designed that chip -- specifically, the portion that communicates with your company's servers over 4G (or whatever is the newest wireless communication protocol at the time) to download firmware updates and such -- has provided you with documentation for the REST API that allows you to send a signal directly to the chip to tell it to immediately change the customer's eye color. So what needs to change? load() and save(). Instead of reading and writing Domino documents, those methods are now parsing and sending JSON, which is trivial in Java. Everything else in the class can stay exactly as it is.

And what needs to change in your XPage? Not a darn thing... well, okay, with one exception: you can remove the date picker for scheduling the change, 'cause this is real-time, baby.

As your customer, I can pull out my phone, tap on a picture of my face, tap on a color, and then look in the mirror and giggle as my left eye turns bright purple. Then, just to really freak people out, repeat the process and turn my right eye orange.

When you originally designed this app, the requirements didn't say anything about supporting this new feature because it hadn't been invented yet, but the moment it had, you made fairly minor changes to two methods of one Java class, and deleted one now-deprecated visual component from an XPage.

This was the most extreme example I could even think of to illustrate how changing your entire conception of applications from documents to the reasons documents exist isn't simply "better" in some nebulous philosophical sense; rather, it allows your application to evolve to do things you never anticipated when you first wrote the app... without having to rewrite the entire app.

12/04/2013

an easy way to give Domino Designer a ridiculous performance boost

Category domino designer performance
  1. From the top-level menu, select "File > Preferences"
  2. Choose "General > Appearance"
  3. Change the option labeled "Current presentation:" from "Styled Presentation Factory" to "Classic Presentation"
  4. Click "OK"
  5. When prompted, allow the "workbench" to be automatically restarted
I do feel obliged to warn you that the behavior of Designer after following the above instructions can be extremely disorienting. For instance, removing an app from the Applications navigator no longer causes that entire viewpart to freak out, repainting itself over and over again... the app just instantly disappears. Adding apps to Designer is also lightning fast. So is switching between working sets, changing which apps belong to which working set, and... well, okay, pretty much everything is significantly faster. Most disturbingly of all, unless for some weird reason you're developing directly against a server (instead of developing locally and replicating when you want to test your changes), and the network latency between you and that server is sufficiently high, you'll no longer see a progress bar when you compile your changes. The build process is just instantaneous. That kind of freaked me out the first time it happened. Thankfully, this is still Designer, so occasionally you'll still have to do a Project > Clean to give it the digital kick to the groin required to assure it that you do, in fact, want it to run the new code. And if you find you miss the progress bar (and hourglass or other OS equivalent), just find a slow enough server to code against, since it's not Designer's UI that's the bottleneck in that scenario. Otherwise, you'll probably need to adjust your routine to specifically schedule breaks (restroom, coffee, cigarette, et. al.) instead of letting Designer decide for you when you should get up and do something else for a few minutes.

10/26/2013

they told me I could be anything

Category
The technology with which I am currently most associated is IBM XPages, but, as I’ve mentioned before, I consider myself a Java developer. That’s a fairly recent mindset shift for me, and has been very liberating.

My first Notes job started nearly 16 years ago (January of 1998). I was warned upon my arrival not to get too comfortable, because Notes was already dead at that point, and the company would soon be transitioning to something else. I was fine with that, because the whole point of taking this job was to do something temporary until I could decide “what I want to be when I grow up”. My plan was to sit there and just create and delete email accounts for a few months, maybe a whole year, and then go do something else. I didn’t know what, but I knew I’d find something that was a good fit for my personality and aptitude.

And I did. As it turned out, I already had. Here I am, 16 years older, a published author and patented inventor, working almost entirely from home writing code for a “dead” platform in collaboration with people I respect and admire in nearly every time zone on the planet. My job is fun, challenging, and rewarding. Thank the goddess I didn’t allow myself to be scared away by those who told me that attaching myself professionally to Lotus Notes was a mistake the very day I started my first “real” job… or the next year… or every year after that. All of what I’ve experienced thus far in my career would, theoretically, still have been possible had I, instead, chosen to pursue some other technology or profession. But here I am, 16 years older, with some amazing memories that are inextricably linked to a pursuit I’ve been advised almost continuously throughout to abandon.

It’s not as though that feedback hasn’t had an impact. I recently realized that, despite being a champion (though, not always a Champion) for the Domino platform throughout my career, there has always been more reluctance than I’ve wanted to admit — even to myself — in my embrace thereof. Every year, I’ve seen and heard the claims that my beloved platform is already dead, that there’s no more work to be found for those of us choosing to focus on it, that it’s time to jump ship and do something else. And every year, I’ve felt more secure in my career than the year before — perhaps not always in the specific job I held at the time, but simply the overall sense that I don’t need to go master some other technology to avoid imminent starvation. And yet, knowing that everybody needs to do what they feel they must, both for themselves and for anyone in their life that might be depending upon them, and continually seeing this “trend” that everyone else seems to be abandoning Domino, some small part of me has always, at least somewhere in the back of my mind, been looking over a conceptual shoulder wondering when this trend will finally touch me. When will my reckless foolishness in continuing to duct tape my entire professional existence to a dead platform finally catch up with me?

For the past five years, my message to others in similar circumstances — namely, others developing for this long-dead platform — has been to embrace XPages. The most public form of this message has been that XPages can drastically improve the capacity of Domino customers to empower their end users in ways that were never before possible (or, at least, easy) within the Lotus Notes client. And that’s all true. But little by little, this shifted to become a self-defense strategy for developers. If you learn XPages — and I mean really learn the technology — you’re learning what so many other developers already know. You’re obtaining a comfort level with XML, Java, JavaScript, CSS, and HTML. These are technologies you can talk about with developers that have never even heard of Domino, much less written Domino apps, and they’ll still know what you’re talking about. You can learn from them, and they can learn from you. You can ask the Google (and stackoverflow)  how to do something you’re attempting to accomplish, and you’ll get solid answers from people who don’t know Domino exists. But purely in the interest of self-preservation, when Domino does inevitably die, you’re qualified to get a job that has nothing to do with Domino. You don’t have to learn a completely foreign technology overnight to avoid starving to death.

Until recently, however, this message has been theoretical. It sounded true, it felt intuitively correct, but I didn’t have any firsthand evidence of this. Now I do.

Over the course of this calendar year, I’ve gained on-the-job experience with several technologies (most notably, in my opinion, native Android development) that are not new, but were new to me. While each has had its own unique learning curve, I attribute the ease with which I was able to comprehend each directly to the comfort level I’ve acquired with the technologies that, as previously mentioned, are fundamental to the nature of XPages. One of these technologies, about which I’ll likely be blogging at some point, is the Play framework. A couple months ago I encountered a professional need to learn it. I can’t claim to have mastered it, but I was instantly comfortable with it. I was able to produce valuable results using this framework the same day I was asked to start learning it. How is this possible? It’s MVC, and it’s Java. It’s template-driven, not component-driven, but for an XPage developer, this is easy to learn. I feel confident in asserting that this would not be nearly as instinctive a transition for a Lotus Notes client developer.

Am I now announcing a plan to abandon Domino and become a Play developer? By no means. Rather, my exposure to these other technologies has produced a surprising, but exciting development: I am now embracing Domino with no reluctance or hesitation. The reason is that I now have proof that I don’t need advance warning of Domino’s demise. Every hour I spend developing XPage apps can serve as practice for doing something else. Given that mobile has truly arrived, and is here to stay, the percentage of my time that is spent on mobile development is practically guaranteed to continue to increase over time, just as it has over the past year. Much of this development will involve Domino in some middleware capacity, and some of it will not. But as long as our customers continue to ask us to provide them Domino solutions, I see no reason to walk away from that demand. When Domino eventually does die — for real — I’ve already learned what I need to know to do anything else, because I’ve embraced XPages. If I were still writing procedural LotusScript full time, it’s likely that I could survive a direct transition to SharePoint development. But because I’ve immersed myself in the technologies fundamental to XPages, if I realize someday that I want — or need — to do something else, I can do anything.

10/10/2013

the reason panel data sources can't be accessed outside the panel

Category xpages
Marky Roden recently called attention to a lesson he learned: if you associate a data source with a specific panel, you can only refer to it by name via events (or attributes) attached to components inside that panel. There are two very specific reasons for this:

  1. Hierarchical component processing
  2. The role the requestScope plays in variable resolution

While there are no doubt some subtle exceptions to this premise, you can consider all runtime processing of XPages to be hierarchical. To conceptualize this visually, imagine the view root (basically, the page itself) as the trunk of a tree. Think of each of the components that are placed directly on the page, rather than inside other components, as branches attached directly to the trunk of the tree. Each of those branches might, in turn, split off into several smaller branches.

Let's consider a simple real-world example:

Imagine an XPage that contains two 2x2 tables. In both tables, each row consists of two cells: one containing a label, and the second containing an editable field.

The server-side structure of an XPage at runtime is sometimes referred to as its "component tree": in this example, the XPage itself is the trunk of the tree. As we look up along the trunk, at some point the trunk splits into two branches: each branch is a table. This branch, in turn, splits into two separate branches, each of which is a table row. Each of these also splits into two branches, each of which is a table cell. The first of these two branches contains a single "leaf"; the leaf on the first branch is a label component. The leaf on the second branch is an input text.

So, if this were a real tree, and we wanted to reach any of those leaves (and, assuming these branches are too high for us to just reach up and touch a leaf), we would climb the trunk until we can reach the tables. We could then make our way along the branches - first one of the tables, then one of its rows, then one of its cells, until finally we're at a leaf. We've found our field. If we retreat back to the inner branches, and then repeat the process for all the rest, we would eventually touch each leaf.

To very briefly change the subject by introducing a less obvious analogy: imagine that some of these leaves (namely, those representing fields) are sentient, and your friend Steve can communicate telepathically them, so he constantly knows what they're thinking. But you can only communicate with them by touch. So… suppose that a leaf named Alan recently learned something you need to know. You decide to climb the tree and work your way along enough branches to eventually find Alan. This could take a while, because not only do most of these trees have a lot of branches, but you don't actually know what branch Alan is on. To find Alan, you have to follow each sub-hierarchy of branches, touching each leaf to ask it its name (technically, its ID).

Eventually, you'll ask a leaf, "are you Alan?", and it'll say yes. Now that you've found Alan, you can ask it everything it knows.

Meanwhile, Steve knew the whole time what Alan was thinking. He's standing safe on the ground, laughing at you scurrying from branch to branch and trying not to fall.

If any of my previous descriptions of why we should always call dataSource.getValue("propertyName") -- instead of getComponent("componentId").getValue() -- didn't make sense, perhaps this illustrates the premise a bit more clearly. getComponent() crawls along all the branches until it eventually finds Alan. dataSource is Steve. Just stay on the ground and ask Steve.

Okay, back to the topic at hand.

Part of why it's not a problem for the core processing of an XPage to traverse this hierarchical structure is that each of the various JSF lifecycle phases has to touch all the components anyway (with the exception, during some phases, of components that aren't rendered, and the descendants thereof), and each only needs to be touched once. So each phase starts at the view root (the <xp:view/> tag) and works its way inward until it's processed all of the components that it needs to a single time.

Some of the phases split the processing into "begin" and "end" operations for each component. For example, the bulk of the work of the RENDER_RESPONSE phase (the very last phase, which is what actually sends the HTML markup to the browser during a typical XPage request) consists of executing the following three methods on every rendered component in the tree:
  1. encodeBegin - For most components, the primary purpose of this method is to emit the opening HTML tag, along with all the currently applicable attributes.
  2. encodeChildren - Once the HTML tag for the current component has been sent, this method basically loops through all the components directly within the current component and passes control to them to "encode" themselves.
  3. encodeEnd - For many components, this just closes the HTML tag.
Because these methods execute in sequence, the result is hierarchical.

Let's consider an even simpler table than before: one row, one cell in that row, and one button in that cell:
  1. table runs encodeBegin, emitting an opening table tag with all pertinent attributes (client-side ID, CSS class, et cetera)
  2. encodeChildren passes control off to the table row
  3. encodeBegin of the row opens a tr tag
  4. encodeChildren passes control to the cell
  5. encodeBegin opens a td
  6. encodeChildren passes control to the button
  7. encodeBegin opens a button tag
  8. encodeChildren does nothing, because this button contains no child components
  9. encodeEnd of the button closes the button tag
  10. encodeEnd of the cell closes the td
  11. encodeEnd of the row closes the tr
  12. encodeEnd of the table closes the table
In reality, there's a bit more going on in there, like making sure there's a tbody surrounding any tr's, etc., but essentially the above is what occurs when this type of component hierarchy is rendered. When any components have multiple children, it gets more complex, except it's still really just these three methods making sure that a parent component gets to start sending its markup before any of its children are processed, that all children have been completely processed before it finishes sending its markup, and finally that it has an opportunity to finish processing itself before any sibling components are touched.

And that last premise is what causes the behavior Marky experienced. Panels are one of a few components that are considered "data containers". As such, when the above process starts for a panel, it doesn't just open a div tag... it also checks to see if any data sources (and/or data contexts) are associated with just that panel. If so, it goes through the motions of ensuring the data source exists, which consists of something like the following:
  1. Based on the scope (r/v/s/a) and name, does this already exist?
  2. If not, create one and store it in the correct scope
  3. Add a pointer in the requestScope
It's that last step that's crucial: adding anything to the requestScope makes it a variable.

Within any EL expression (whether standard Expression Language, SSJS, or some custom language), any symbols determined during expression parsing to be variables end up asking what's known as the "variable resolver" for the object to which that variable refers. There are several places the standard variable resolver looks, and one of them is the requestScope. So any requestScope key is a valid variable for as long as that key exists within the requestScope… which is usually the entire request.

Panels, however, don't just add variables, they clean up after themselves.* Specifically, at the end of a panel's processing, it again checks to see if it has its own data. If so, it removes the requestScope pointer it created during its initial processing. If the data source has a higher scope (the default is viewScope), the data source itself still exists within that scope. But there's no longer a pointer to it in the requestScope, so there's no longer a variable by which it can be directly accessed. On any subsequent requests, when the same panel is processed again, it will find the existing data source instance in its correct scope, create a fresh requestScope pointer, and then remove that pointer again when it finishes its processing.

That might seem a little pointless, since it's typically milli- (or even micro-) seconds between the creation and obliteration of the variable. But because all processing is hierarchical, this means that during all processing of components anywhere inside that panel, the requestScope pointer does exist. Any components in that sub-structure can refer to that variable. But once the panel and everything within it have been processed, that variable is gone. The more complex an XPage, the more valuable this automatic cleanup, because it optimizes resolution of all variables. So it's a good practice to always be looking for ways to structure our user interfaces in ways that allow us to localize our data as much as possible. This not only maximizes app performance, but also makes the application source more logically coherent by compartmentalizing its visual structure according to the conceptual structure of its data.

* P.S. If you considered the above and immediately guessed that Custom Controls and repeats behave similarly, you get a gold star.

08/22/2013

quick tip: persistent query string parameters

Category xpages
Here's a handy bit of code to drop into the afterPageLoad event of your XPages:

viewScope.putAll(param);

Why?

One of the best characteristics of XPage applications, in contrast to their non-XPage Domino counterparts, is their statefulness. The capacity to maintain consistency of data, user behavior, and user preferences between interactions with the "current" page, across pages within an individual user session, and even across all (or select groups of) users of an application is simply baked into the platform. This type of consistency no longer requires complex and fragile hacks.

Now that I've been developing XPage apps for almost exactly five years, I've come to take this statefulness for granted so much that I occasionally assume some portion of the XPage runtime is even more stateful than it actually is. Consider, for example, the query string parameters of a URL: at first glance, it might seem reasonable to bind some component or data source attribute to a specific parameter; e.g.:

#{param.preferredExportFormat}

You load the page to test it, passing some representative value via the specified query string parameter, and everything looks like it worked, as you'd naturally expect... until, that is, you trigger any event against that same page. Suddenly the attribute you bound to the parameter is gone. Why? You can see the parameter right there in the address bar... you know it's there. Why did Domino forget the value just because you triggered an event?

The more astute among you already know. Several of you might even be chuckling, and with good reason. Domino "forgets" the value because every event has its own query string.

Caveat: this might not apply to Domino 9. In a few quick tests on a server running XWork 9.0, I noticed that partial refresh events do pass any parameters from the original page load to any event in addition to the standard parameters, like $$ajaxid. So even this hack might not be necessary to achieve the intended result, at least if you've already upgraded to 9. And you really should.


Anyway, the afterPageLoad event is only run when a component tree is initially constructed. If the user triggers events against the page (links, buttons, etc.), that initial event is not fired again. So this is basically the opposite of the afterRestoreView event, which does not fire when the page first loads, but does fire when any user event occurs. As a result, in the context of any afterPageLoad event, the query string parameters the server is aware of are the same parameters that the user sees in their address bar. Hence, the line of code at the beginning of this post takes all entries (in the Java Map.Entry sense) from param and copies them to the viewScope.

So, instead of the previous, potentially fragile, example:

#{param.preferredExportFormat}

I now have a safer alternative:

#{viewScope.preferredExportFormat}

If that property name wasn't in the original URL query string, the above expression will still return null. But... if it was in the query string, the above expression will remain valid no matter how many events are triggered against the page instance... as long as nothing else clobbers the duplicated pointer in the viewScope, of course.