27 September 2011

Java JSONWriter Domino Agent Class

If you're like me, in the coarse of your web development years with Domino you've had to create plenty of agents that need to output little bits of JSON as output to the browser for some reason or another. Since these were just bits of JSON here and there, I created the code to do this from scratch every time I made a new agent -- not the best way to do things, but it worked. I eventually got tired of that and created a small helper class for Java that simplified this process.

Simply add it to your Java agent, and then initialize it with a "JSONWriter.start()", passing "getAgentOutput()" as the sole parameter. This can be done from anywhere in your code, as long as it's before whenever you try to start printing JSON output. Just pass the string name of your JSON parameter, followed by either a string, variable, or boolean value. Close up the stream with "JSONWriter.end()" whenever you're finished.

(I have a git repo of this code at https://github.com/mdmadph/mdmjava.)
package util;

import java.io.PrintWriter;
import lotus.domino.NotesException;

/**
 * @author mdm-adph
 *
 */
public class JSONWriter {

	/**
	 * 
	 */
	private static PrintWriter printOutput = null;
	
	/**
	 * 
	 */
	private static boolean firstParam = true;
	
	/**
	 * Default constrctor.
	 * @constructor
	 */
	private JSONWriter() throws NotesException {
	}
	
	/**
	 * Initializes the JSONWriter singleton with the desired PrintWriter
	 * @param pOutput {PrintWriter}
	 * The PrintWriter object to associate with JSONWriter,
	 * usually the result of getAgentOutput()
	 */
	public static synchronized void start(PrintWriter pOutput) {
		if (printOutput == null) {
			printOutput = pOutput;
			
			printOutput.println("Content-type: application/json");
			printOutput.println("{");
		}
	}
	
	/**
	 * Internal function that prints the actual JSON information
	 * @param param {String}
	 * The string value of the JSON parameter name.
	 * @param value {String}
	 * The value of the JSON parameter.
	 */
	private static synchronized void printLine(String param, String value) {
		if (firstParam) {
			firstParam = false;
		}
		else {
			printOutput.println(",");
		}
		
		printOutput.println("\"" + param + "\":" + value);
	}
	
	/**
	 * Public interface for printLine() for string params
	 * @param param {String}
	 * The string value of the JSON parameter name.
	 * @param value {String}
	 * The value of the JSON parameter.
	 */
	public static void print(String param, String value) {
		printLine(param, "\"" + value + "\"");
	}
	
	/**
	 * Public interface for printLine for integer params
	 * @param param {String}
	 * The string value of the JSON parameter name.
	 * @param value {int}
	 * The value of the JSON parameter.
	 */
	public static void print(String param, int value) {
		printLine(param, Integer.toString(value));
	}
	
	/**
	 * Public interface for printLine for Boolean params
	 * @param param {String}
	 * The string value of the JSON parameter name.
	 * @param value {Boolean}
	 * The value of the JSON parameter.
	 */
	public static void print(String param, Boolean value) {
		printLine(param, Boolean.toString(value));
	}
	
	/**
	 * Closes the JSON stream
	 */
	public static synchronized void end() {
		printOutput.println("}");
	}
	
	@Override
	public Object clone() throws CloneNotSupportedException { 
		throw new CloneNotSupportedException(); // that'll teach 'em 
	}
}

20 July 2011

JS/ExtJS Code to Determine Age

Just something I came up with for a form I'm building -- is there a quicker way to do this?

(_now.format('Y') - birthdate.format('Y')) 
     - (_now.format('z') < birthdate.format('z') ? 1 : 0)

13 July 2011

LDDMonkey -- Greasemonkey Script for the IBM LDD Forums

http://www.openntf.org/projects/pmt.nsf/ProjectLookup/LDDMonkey

Here's a little Greasemonkey script I've been using for the past few years to make browsing the LDD forums at ibm.com tolerable -- I'm amazed constantly that this script still works!

21 June 2011

It Always Felt Like Addon Support in IE was an Afterthought...

For some reason, I took a look at the "addons" my copy of IE8 had installed -- I wanted to sort them by date (to see which was oldest), but no matter how many times I clicked on the column header, they wouldn't seem to sort.  Just then, I realized they were sorting, just not the way you would think.


We always knew addon support in IE was an afterthought, didn't we?  Please tell me it's not supposed to be like that.  (I used to have this problem as a budding Notes developer a LONG time ago, until I learned the difference between text and datetime formats.)

20 April 2011

Configuring the IBM Domino Server to Show the Mobile Login Form to Android Users

Just like many programmers have today, I've been starting to do a little bit of mobile development on the side with the Domino server, and I've been discovering the little tweaks IBM has been doing here and there to make Domino more mobile-friendly.  For instance, upon navigating your web browser to a Domino app with your iPhone or iPad, you're greeted with a touch-friend version of the standard login screen:


Unfortunately, this special login view was apparently not extended to users of Android devices, as I found when I tried to login with my phone.  I was provided with the standard login screen, which is not very mobile-friendly at all.

Now, when you do finally login with your non-iOS mobile device, the actual database, such as your mailfile, will detect your non-iOS mobile device, and load an appropriate mobile interface.  Interesting.

So, I figured that a lot of the default Domino coding could detect non-iOS devices, but for some reason the login window portal (a database named DominoWebAccessRedirect.nsf) doesn't.  I delved into the code for a bit, finding some interesting bits of code, and a reference to @GetProfileField that apparently grabbed a list of user-agent data (from a profile document) that was checked against the user trying to login. 

Figuring that there must be some way to edit that document, I did a little bit of Google searching, and found that it's actually rather easy:

First, open up DominoWebAccessRedirect.nsf in your Notes Client:

Click on "Setup", and then click on "Ultra-lite/Mobile Settings":


Then, under "Mobile Device User Agent Keywords", enter whatever you like.  Something tells me that "android" will probably be entered here already for you by default on the next release.


[ Resources: http://www.ibm.com/developerworks/lotus/library/inotes-ultra ]

29 March 2011

Amazon Cloud Storage

I've been looking at the Storage ecosystem that Amazon released today as part of it's "Cloud Drive" system, and I'll admit I'm impressed with what I see.  I'm thinking from the view of a "regular" user:
  • The system is available to any Amazon.com customer (at least in the US and UK right now).  You get 5GB of storage by default.  If you buy an album from them this year, you're automatically given a free subscription to their 20GB service for one year.
  • You can easily upload your existing music using the Amazon MP3 Uploader, an Adobe AIR-made program, which I assume works on Windows, Mac, and even Linux.  It can easily find music automatically, or you can specify where to look.
  • This music that's uploaded can be listened to from a web browser from anywhere.
  • The corresponding Android app (that was typically used only to purchase MP3's) now also works as a streaming music player -- additionally, MP3's you upload to the Cloud Drive service can also be downloaded to your phone's storage for local playing.  This can be setup to happen automatically whenever something is uploaded to your Cloud Drive.
  • MP3's you purchase on Amazon can now be automatically added to your Cloud Drive.  You can choose to download these whenever you want -- MP3's added in this automatic way upon purchase do NOT count towards your 5GB limit.
Honestly, I'm incredibly surprised.  They beat both Apple and Google to the punch with a cloud music service -- Google, especially, who promised it at last years Google IO conference.

Now, nobody knows what kinds of deals they had to make the various record companies in order to get their "compliance" (even if you argue that it isn't needed), and they could get sued to the moon and back tomorrow, but for now, I'm applauding Android.