In response to: XPages... the Biggest Barrier Unless you're nothing whatsoever like me, once you start actually developing XPages, you'll never want to write LotusScript again. I know that must sound crazy coming from me... until October I was a LotusScript fanatic. But trust me, SSJS is every bit as easy to write as LS (in my opinion, even easier, for several reasons), but WAY more powerful.
I admit, thus far I've had the luxury of developing XPages for audiences primarily interested in a web interface. Additionally, nearly all of the XPage-based apps I've been building have been brand new applications. But on one recent project the client was rewriting an entire public-facing website from a LS-heavy version to an XPage version; much of the LS code that was still needed could be rewritten at a pace of 5-10 minutes per agent because the method syntax is so similar... but the majority of the code wasn't even needed anymore because it was reams of script just for rendering interface components that are now bundled controls in XPages.
There are ways to save yourself time now:
1. Use lower-camel-case. For example:
Set docSomething = vwSomething.getDocumentByKey("key", True)
When it comes time to rewrite that line of code in SSJS, all you have to do is delete "Set" and change "True" to "true" (and - optionally, but recommended - tack a ; onto the end of the line). LS won't let you change the case of a Boolean constant, but it doesn't care about case in method calls. So make your code more portable by using lower-camel.
2. Avoid extended class syntax for accessing item values. For example:
subject = docSomething.subject(0) 'original LotusScript
...becomes:
subject = docSomething.getItemValueString( "Subject" ); // SSJS equivalent
If your code is already:
subject = docSomething.getItemValue( "Subject" )(0)
...your code is more portable, because (like the previous example) there's simply less changes required.
In short, when there's something optional in one language that's required in another, it's generally a good idea to adopt that as a convention, because sooner or later you'll have a reason for using the other language... at which point either you're completely rewriting your code in a syntax that seems utterly foreign... or you're just tweaking code in a new but already familiar context.
|
Re: XPages... the Biggest Barrier
|
This post isn't specifically about my impressions of Lotusphere as much as it is about version 8.5 of Domino. Imagine you're at a movie with a friend. It's well-written, well-acted, perhaps a little slow at the start, but intelligent, innovative, and just... well, different from all the crappy movies Hollywood is fond of making these days. The plot advances steadily, and as it builds to a thrilling climax... your friend gets up to leave.
"What? You're leaving now?" "Yeah, the Jonas Brothers movie is about to start. I think I'll go see if it's any good."
Seriously, if you know anyone who uses Notes/Domino and they're even thinking of migrating to another platform, your response should be, "you're leaving now, are you crazy?" The 8.5 client has all the pretty of 8.0 with noticeably less overhead - and is solid on Mac and Linux (heck, they even ship both .RPM and .DEB installers... they're really getting the hang of this Linux thing lately) - Domino Designer is FINALLY based on a proper IDE framework, and XPages... oh my goodness, XPages. When I first heard about them, my reaction was, "hm, sounds interesting". When I actually started developing with them, my reaction rapidly changed to, "holy crap, this changes everything". I've spent a ridiculous amount of time on them since, and my excitement about them continues to grow.
Is DDE a bit buggy out of the gate? Of course it is. My biggest pet peeve at the moment is that on Vista (yes, I know, I should be using the version of Windows that came out around the same time as Notes/Domino 5, but the Thinkpad tablet I use at work has no optical drive, and I'm not sure I feel comfortable reimaging my work PC via a thumb drive like I routinely do with my personal laptops), drag-select is broken almost everywhere... I guess Cinderella was right: you don't know what you got 'till it's gone. But honestly, compared to the myriad of functionality they could have completely hosed while porting this beast, if that's the most glaring bug I've found so far, in my opinion they executed brilliantly. There's plenty more that can be done with it - OOB SVN support, for example - but that's the whole point: now that Designer uses Eclipse for its core engine, the extent to which it can be further extended is downright silly. I expect we'll be seeing some amazing changes to it in subsequent releases. The hard part's done... now the real fun begins.
Call me a fanboy if you like, but far more than any preceding release, 8.5 doesn't merely give me hope that the product will survive, it's reminded me of the thrill I felt when I first encountered it 11 years (and 14 days, but who's counting) ago. Abandoning this platform now would be an act of sheer madness.
|
you're leaving now?
|
A brand new addition to the BleedYellow portfolio is a "labs" version of a microblogging application for Domino called "Squawk". Although it has several integration points with Lotus Connections (for example, you do not need to register separately for this application - you can use your existing BleedYellow credentials - and your profile picture in Squawk is whatever picture, if any, you've uploaded to your BleedYellow profile), the application itself runs entirely on Domino.
Originally envisioned purely as a proof of concept demonstrating that Domino applications can scale massively if architected well, we've decided to host it on an ongoing basis as a BleedYellow service. And, when the time comes, if you'd like to purchase a copy to run in your own intra/extranet (with or without Connections integration)... I suspect we can arrange that.
Squawk is still in the alpha stages, but we wanted to share it with you in its infancy to make you a part of its development. Here's a brief summary of what currently works and what will at a later date:
- Post a Squawk: like most micro-blogging applications, each post is limited to 140 characters.
- Community Squawks: this is a global transcript of the last 20 Squawks from anyone in the BleedYellow community.
- My Flock: search for people in the community; each search result will include the individual's name and profile picture (the Connections default image
if they haven't uploaded one yet), and a subscribe/unsubscribe link based on whether or not they're already in your Flock. An icon for each member of your Flock will appear in a block on the right; hover over their icon to see their name, click their icon to view their latest Squawks. - Various links (Profile, Settings, Home, etc.) are either just placeholders or, for the time being, unnecessary: for example, the Home link is a bit superfluous, because at the moment, Squawk is a single-page Ajax application.
- My Replies: we haven't wired these in yet, but at the moment our thinking is that @shortname will denote a Squawk as a reply to the individual with the matching shortname. We'll also be adding a reply icon that will automatically insert the shortname for you. But we're also going to be adding nicknames, so if you want to type @trip, for example, to reply to me, you can tell Squawk to treat that as a nickname for me. If you've defined a nickname for a member of your Flock, clicking the reply icon will insert the nickname you use for them instead of the default.
- In a related feature, at some point we'll also be allowing you to create groups from your Flock and direct a Squawk just to a specific group or individual: for example, "hello world #test !dxl" would tag the Squawk as "test" and it would only display to members of my "dxl" group. We're also going to allow you to load a default set of groups based on which BleedYellow communities you're a member of and who else is a member of each.
- Speaking of tagging, tags aren't clickable yet but of course will be later... in the meantime (and going forward), if you tag a Squawk with #bug or #feature, we'll use that feedback to improve this application.
So head on over to squawk.bleedyellow.com and check it out.
P.S. Interesting bit of trivia: Squawk instantiates a single view handle when the Community Squawks transcript is requested; searching for people to add to your Flock naturally performs a full-text search... every other function in Squawk ignores indexes entirely.
|
BAKAAAWK! Announcing Squawk: Microblogging for Dom...
|
This entry is related, but varies slightly from, Bob Balfe's article on debugging Eclipse plugins in Notes 8. My current hobby project is written entirely in Java, but it's not an Eclipse plugin - at least, not yet... once the application's API is finalized, the code I'm writing now will find its way into a plugin, a web service, a server-side JavaScript library for use in one or more XPages, and so on. But before I get carried away with any of that, I first need to get the core functions working.
I'm still primarily a LotusScript developer, so I'm accustomed to relying heavily on the LotusScript debugger to tell me why my code isn't behaving precisely the way I'd imagined it in my dreams... just kidding, I don't dream in LotusScript. Okay, there was that one time, but trust me... you don't want me to tell that story. Anyway, I've long since adjusted to adding semicolons at the end of each line, curly braces to open and close conditional blocks, and the like... JavaScript's optional preference for same has, over the course of several years, gradually prepared me for Java's non-negotiable stance on such things. But not having as informative of a debugger was really starting to bug me (rimshot). Besides, my testing process had grown rather cumbersome:
- Write the code in Eclipse (so I can actually get typeahead on both imported and custom classes, and easily integrate with SVN - not only so I can roll back to a previous version if I completely mangle something, but also to take advantage of Nathan's frequent midnight mindstorms).
- Export to a JAR.
- Open the test agent in Designer.
- Delete the JAR from the project and save it (since there's no "refresh" option to force the design element to notice that the local file has changed... I was going to write a separate agent to recreate the test agent using DXL by Base64-encoding the JAR and... yeah, ew.), wait for Designer to squawk at me that it could no longer compile, click Yes to save it anyway, add the JAR back in, save again.
- Run the agent.
- Check the three databases that should have new / modified documents if the code worked, and verify that all items were written correctly.
- Open / switch to the Java Debug Console to sift through ridiculously verbose logging and stack traces for some hint of why one item value had been set incorrectly.
- Return to step 1, hopefully now aware of which precise line of code needs to be updated - and how - in order to fix the bug. Repeat as long as necessary.
As my friend Sean Kelly would put it, "pain... you know it isn't easy". Here's my new process:
- Write the code in Eclipse.
- Open the class file that defines the unit test I want to run.
- Click the cute little bug icon in the Eclipse toolbar to launch debugger, then step into and over until it crashes or completes.
- Generally speaking, at this point I don't even need to switch back to Notes, because if it didn't work, I saw it go wrong during the debug run, so I know exactly where to look, even if I wasn't logging a durned thing. Return to step 1, repeat as long as necessary.
What changed? Surprisingly little:
- I had to add the Notes program file ( on this laptop, that's just "C:\Notes" ) to the PATH system environment variable. And, though I didn't realize this until later, I had to reboot for that to take effect.
- While normally I'd just include a standard JRE in my project build path, I changed this project's build path to point to an "alternate JRE": namely, the one included in Notes 8. To specify the Notes JRE as an alternate in Eclipse, select Window > Preferences, then navigate to Java > Installed JREs. Click Add, choose "Standard VM" as the type ( and click Next ), then give it a name ( like "Notes 8" ), and set the JRE home to "[Notes Program Folder]\framework\rcp\eclipse\plugins\[OS-specific folder]\jre", then click Finish. In my case, the [OS-specific folder] is "com.ibm.rcp.j2se.win32.x86_1.6.0.20080709-200808010926".
- Here's the crucial part: the class has to be runnable, so it needs to be treated like a command-line Java class - namely, it needs a static void "main" method - and it needs to start and stop a Notes thread ( I'd also recommend syncing your Notes and OS passwords so that you can skip being prompted for your password when the thread is started ).
For example:
public static void main(String[] args) {
NotesThread.sinitThread();
NotesThread.stermThread();
} That's all it takes. I now have a class for each of my unit tests. So I have one that creates a document, another that formats a summary of a document collection as JSON, and so on. Whenever I make any code changes, I run the unit tests for verifying any functionality that is impacted by the change I just made... so, without ever leaving Eclipse, I know right away whether or not I've just mangled something... and if so, what needs to change.
|
Debugging Notes and Domino Java code in Eclipse
|
I was contacted last week about a comment I had left on Bruce's site stating that I had code for assigning a database a new replica ID. The comment in question was an allusion to some code I'd originally found on the Breaking Par site that uses some Notes API calls to overwrite a database's replica ID. Last night I threw together a utility that makes use of this technique to provide two quick operations:
- Link Replicas: select a source (the database whose replica ID you want to retain) and a target (the database that you want to change to be a replica of the source) and click "Establish Link". The target database will be made a replica of the source database (and any additional replicas of the source).
- Unlink Replica: select a target database that you no longer want to be a replica and click "Unlink Replica". The target database will be assigned a new replica ID, effectively making it a copy of any databases it was previously a replica of.
Since the theme to all of this is replication, I called this utility Nexus, and you can download it here. You might notice the interface has a hint of an LCARS feel to it... the Sci Fi channel was running a TNG marathon yesterday, so Laura and I chose to relax (I got home at 3 AM Saturday morning from a business trip, we went to a family reunion in Gumlog, GA Saturday night, and spent part of Sunday and Monday at various state parks, so we were both a bit wiped) by sitting on the couch for six hours straight watching Star Trek. And then I wrote some code. So yeah, I'm a pretty content little geek.
|
Nexus: replica ID management utility
|
As I mentioned the other day, I've now updated my certification to version 7. As time permits, I'll take the update exam to bump that up to version 8 and be set until whenever 9 comes out... assuming they stay with the sequential numbering convention. Who knows, they might switch to Microsoft numbering, in which case we might get Lotus Notes 2010: The Year We Make Contact.
Though I'll most likely just take that update exam at Lotusphere, I decided last night to take a gander at Designer Help to see if there was anything that was added in 8 that I hadn't previously noticed (as it turns out, there was). I started at the top entry ("What's New in Domino Designer 8?") and just drilled deeper and deeper, but with no breadcrumbs to keep track of where I'd been, I rapidly lost track of which entries I'd already read. And then it struck me: whenever they add something in a new version, the help entry for that new property, method, etc., typically contains the phrase "new with Release {x}", where {x} is the version in which it was added... so it should be easy to create a basic wrapper for the web interface of Designer Help that allows me to isolate only what changed in each release... so I did: presenting Release Diff for Domino Designer Help.
|
Community offering: what's new in each version of ...
|
A couple of disturbing observations: First, in a 2006 post from Julian about animated favicons, the little animated banana dances at the exact same tempo as the song "Your Star" by the All-American Rejects. Try it... it's mesmerizing.
But secondly, to explain the title of this post, I noticed an odd behavior related to image resources in the Notes client: GIF support is incomplete. ICO files are actually stored in the same format as GIF, just with a different extension. So another approach to creating animated favicons is to simply rename an animated GIF to .ICO. That's how Dean Edwards created a favicon that periodically blinks. Theoretically, then, we should be able to download any site's favicon, rename it to .GIF, import it as a file resource, and then display it in the Notes client. No such luck.
Since real browsers (read: Firefox, Safari, and Opera... of course, as always, IE fails) don't distinguish between the two formats and simply trust the server-supplied MIME type, navigate to the same image resource via a URL and the image displays as expected. But try to reference the same image resource anywhere in the Notes client (or even just preview it in the image resource list), and you get nothin' but gray.
Sorry, Bruce, I tried...
|
PNG support in the Notes client? Maybe they should...
|
For as long as I can remember (possibly 2001) I've always maintained some variation on a SmartIcon toolbar button that a former coworker called the "magic button": it allows new fields to be added to a document and existing fields to be overridden or deleted from the document, either while editing the document or while it's selected in a view. I've seen various approaches to this basic concept over the years, and each time I install Notes on another computer, I either consult the Google to find one I've used before or just reconstruct it from memory. It finally occurred to me that if I just posted the one I'm currently using here, not only would it be easier for me to find later, but some of you might find it useful as well. So here's the current incarnation of said magic button:
targetField := @Prompt([OkCancelEditCombo]; "Select Field"; "Select a field to override:"; ""; @DocFields );
updateTypes := "Text":"Number":"Time":"Delete Field";
updateType := @Prompt([OkCancelList]; "Select Type"; "Choose a type or action:"; "Text"; updateTypes );
@If(updateType = "Delete Field"; @Return(@SetField(targetField;@DeleteField)); "" );
newValue := @Prompt([OkCancelEdit];"New Value";"Enter the new value:"; @Text(@GetField(targetField )));
newTypeValue := @Select(@TextToNumber(@Replace(updateType; @Subset(updateTypes;3);"1":"2":"3" )); newValue; @TextToNumber(newValue); @TextToTime(newValue));
@SetField(targetField; newTypeValue)
I'm sure you can decipher the above, but here's what it does:
- Asks you which field you want to override. Type in a new one if you're adding a field. I've seen other versions where something like "---NEW---" is included in the field list prompt, and if you select that, it asks for the new field name... figured I might as well skip that extra step by just using [OkCancelEditCombo].
- Asks what data type the new value will be (text, number or time), with an option to delete the field instead - in which case the formula just deletes the field and exits.
- Asks what the new value will be, defaulting to the current value (if any).
- If the new value's data type is not text, converts the value to the selected type.
- Writes the new field value to the document.
This little button has saved me oodles of time over the years...
|
Magic Button
|
|
I just had an epiphany... or maybe just an apostrophe. I'm in the middle of some code that does some date matching (determines which document to process based on date information posted from a web application). I don't have control over the date format posted to the agent, and currently the format is [Month abbreviation][unpadded day number][day number suffix] - i.e., Apr15th. I already knew that passing "April 15th" to the constructor of a NotesDateTime object would create an instance representing [04/15/2008 12:00:00]. But did you know that "Apr15th" will too? As it turns out, it actually ignores the suffix: "Apr15bogus", for example, creates a date with the same properties. Always good to find these things out before I resort to string parsing...
|
Cheap date
|
Yesterday (April 1... I know it's technically April 3 now, but for me it's still Wednesday) was mildly momentous. Although the following graph hasn't quite caught up yet (UPDATE: now it has), the server that hosts TimTripcony.com broke its uptime record:

As the graph indicates, the red X's (which hover, on average, closer to 0) are from the server's stint as a Windows box; the blue represent its shiny new Linux identity. Since the conversion in early December, it's only had one reboot... and that's only because we had a brief power outage (bad Timmy, no UPS). Other than replacing the hard drive (with one that was actually older than the Windows drive, just hadn't ever been used), the hardware is the same - same motherboard, processor, NIC, RAM, etc.... it just stays up now. No babysitting: no weekly defrag, no chkdsk to try to keep it from tanking, no weird behavior if I ignore a security update on a server that's only externally accessible on ports that I'm securing via Domino anyway... it just stays up. Is Linux administration "harder" than Windows administration? Sure... if, like me, you don't originally come from a UNIX background, there's a lot that may seem counter-intuitive about it. You may spend a bit more time on "the Google" looking for the exact syntax of various commands. But I'd personally rather support something I rarely have to touch - even if that occasional interaction isn't quite as intuitive as its Windows equivalent - than have to constantly babysit a system just to keep it operational.
|
Uptime
|
I haven't seen much discussion about how easy it really is to consume web services in Notes/Domino 8 (perhaps precisely because it is so easy), so I thought I'd outline exactly how one goes about providing and consuming services now. Let's use a very basic example. Create a script library and toss this in the Declarations:
Public Class House
Private currentColor As String
Private currentValue As Long
Public Sub buy (price As Long)
Let Me.currentValue = price
End Sub
Public Function color() As String
Let Me.color = Me.currentColor
End Function
Public Function value() As Long
Let Me.value = Me.currentValue
End Function
Public Sub sell (price As Long)
Let Me.currentValue = price
End Sub
Public Sub paint (newColor As String)
Let Me.currentColor = newColor
End Sub
End Class
Save that library, and create a web service. Include the library you just created via a Use statement in the Options, then in the properties of the service, specify House as the PortType class. The service doesn't need any code of its own, because it's aware of the House class via the Use statement and knows that's the class that defines the service methods.
Now it's time to consume the service. From within the service, click "Export WSDL", and save the file anywhere you can get to it later. In any Domino database (including, but not limited to, the database containing the web service), create a new script library (can be Java if you prefer, but in this example, we'll use LotusScript). At the bottom of the window you'll see a WSDL drop-down button. Click that and select "Import WSDL". It'll warn you that this will overwrite your script library (which is fine, since that's precisely what we want); click OK and select the file you just exported. Here's what you'll see:
%INCLUDE "lsxsd.lss"
Class House As PortTypeBase
Sub NEW
Call Service.Initialize ("UrnDefaultNamespaceHouseService", _
"HouseService.Domino", "http://localhost", _
"House")
End Sub
Sub BUY(PRICE As Long)
Call Service.Invoke("BUY", PRICE)
End Sub
Function COLOR() As String
Let COLOR = Service.Invoke("COLOR")
End Function
Function VALUE() As Long
Let VALUE = Service.Invoke("VALUE")
End Function
Sub SELL(PRICE As Long)
Call Service.Invoke("SELL", PRICE)
End Sub
Sub PAINT(NEWCOLOR As String)
Call Service.Invoke("PAINT", NEWCOLOR)
End Sub
End Class
Any of this seem familiar?
Only one change to the library is needed: replace the reference to "http://localhost" (in the Service.Initialize call) with "http://server/path/db.nsf/servicename?OpenWebService" (where server is the IP or DNS address of your Domino server, path/db.nsf is the full filepath of the database containing the service, and servicename is the name of the web service design element).
At this point, you can save the new library and include it anywhere you need to consume the service. And actually consuming it is this easy:
Dim myHouse As New House()
Call myHouse.buy(200000)
Call myHouse.paint("Purple")
Call myHouse.sell(5000000)
But the real beauty of web services is that it allows you to execute functions against an application you know nothing about, whether it's inside your network or not. For example, if you download this file and import it into a script library in any of your applications, you can pull a random quote from my site as easy as this:
Dim Quotes As New Quotes()
Dim Quote As Quote
Set Quote = Quotes.getRandomQuote()
Msgbox Quote.Content & Chr(13) & "- " & Quote.Source
|
Consuming web services in Notes and Domino 8
|
import lotus.domino.*;
public class JavaAgent extends AgentBase {
public void NotesMain() {
try {
Session session = getSession();
AgentContext agentContext = session.getAgentContext();
DxlFactory.createAgent("James Bond", DxlAgent.LOTUSSCRIPT).addCodeEvent("Initialize", "Sub Initialize\n'Shaken, not stirred.\nEnd Sub").toDesignElement(agentContext.getCurrentDatabase());
} catch(Exception e) {
e.printStackTrace();
}
}
}
|
Tee hee
|
Last month, Greyhawk expressed frustration with a pattern he'd detected in the whitepaper emails they'd been sending, and unsubscribed from their distribution lists (as did many of us). Ed later took them to task on the same issue. I'm keeping them in my RSS strictly because I've also noticed a decline in the quality of tips submitted, and I would like to occasionally serve as some small bulwark against the dissemination of bad advice to noobs. Messiah complex? Yeah, maybe a little. Earlier this week, I spotted a real winner.
In a remarkable display of over-engineering (sorry, Christian), the tip linked to above demonstrates one approach to downloading the contents of a server's INI file. It uses approximately 220 lines of code (including comments and whitespace) to issue a remote console command and store the response in a text file... using Notes API calls to issue the command and Windows API calls to write the response to the file using Notepad. Assuming you're using one of the last three major releases of Notes/Domino, the same exact operation can be accomplished with 8 lines of code. And (gasp) it'll work on all supported platforms.
Sub downloadServerINI (Byval server As String, destination As String)
Dim session As New NotesSession
Dim stream As NotesStream
Set stream = session.CreateStream()
Call stream.Open(destination)
Call stream.WriteText(session.SendConsoleCommand(server, "Show Config *"))
Call stream.Close()
End Sub
I used their comment link (a mailto:... they haven't quite gotten around to implementing the comment feature you'll now find on almost any blog) to send Gervais a comment summarizing the above. He responded less than an hour later, thanking me for the feedback and indicating that he'd update the tip as soon as he got a chance. I just checked, and although it's been over two days since then, there's been no change... except that it now shows that, thus far, it's been rated a 5.00 out of 5.00. So anyone reading this tip that doesn't know any better might think this is the most elegant approach available. I rated it a 1, but apparently the average isn't real-time.
|
Disappointed in SearchDomino
|
By now, we all know (hopefully) not to use GetNthDocument to loop through document collections, but here's something that often gets overlooked: don't use NULL in formula to determine if a field is blank. NULL doesn't exist. In LotusScript, the keyword Null basically means "unknown" or
"invalid". For example, ArrayGetIndex returns Null if the search value
does not exist in the source array. You can manually assign Null to a
variable - but only if it's a Variant - and then use IsNull to see if
it's still Null, but I'd advise against that, since the only way a
value can be Null is if you specifically tell it to be or assign it to
an expression that returns Null. IsNull( "" ), for example, returns False.
In formula, although @IsNull does exist, NULL simply has no meaning. It's not a reserved keyword, so much like extended syntax in LotusScript,
it doesn't know what it means, so it assumes you're referring to a
field. Since there is no field (again, hopefully) named NULL, NULL
returns "". So technically you get the same result, just more slowly.
This reminds me of trying to navigate one of those voice-activated
menus when I try to call the customer service department of an ISP,
utility company, insurance agent, etc. After trying unsuccessfully to
determine how to contact an actual human, I'll just say "human". More
often than not, the response is: "I'm sorry, I didn't understand you.
I'll transfer you to a representative." The result was precisely what I
wanted, it just took longer than it would have if I'd known to just
push 0 at the start of the call.

In other words, the following formulae all return the same Boolean value:
Subject = NULL Subject = "" @IsNull(Subject) @Length(Subject) = 0
The last is the most efficient, but arguably the least readable. I'd still recommend it, though, for use in column formulae for potentially large views and view selection for any view in a potentially large database. For performance purposes, hide-whens on forms/subforms should be kept to a minimum anyway, but the more you have the more noticeable it becomes if you're asking if some field value = NULL in each: Notes has to check each time whether a field named NULL exists, find out that it doesn't, evaluate NULL to "", and then do a string comparison between "" and the field you've specified. With @Length(FieldName) = 0, it's just checking the length of the field value, then comparing one number to another. Again, slightly less readable, but faster every time.
|
NULL and void
|
A friend of mine recently set up a Domino server at home running on Fedora, and is currently replicating a few databases with my personal server. He's locked out of the rest of the databases on my server, of course, so the connection document is set to only synch the ones he has access to. But in order to trigger a manual replication (outside of the schedule defined in the connection), he had to issue a separate Replicate command for each database to avoid getting errors about all the databases with shared replica IDs that his server can't access. He wanted a single command that would allow him to just type "go go gadget replication" and have it do everything he wanted, but only what he wanted. As it turns out, IBM posted instructions for this just last Friday.
If you issue a console command with the following syntax: < "filename" ...Domino looks for the specified filename relative to the data directory, and treats each line in the specified file as a separate console command. So, for example, a file named "go go gadget replication" (no extension necessary) in the data directory containing:
Replicate Coyote/ACME names.nsf Replicate Coyote/ACME mail/coyote.nsf Replicate Roadrunner/ACME stuff.nsf Broadcast "(!)Selective replication manually initiated." "Wile E Coyote/ACME"
Wile E can now issue the following console command (the < indicates the rest of the command is a filename):
< "go go gadget replication"
The server will kick off three replications, then pop up a message confirming the comands.
NOTE: on Linux, the file must be owned by notes:notes (or whatever user:group Domino is running under) in order for this to work.
|
Go Go Gadget Replication
|