7 Totally Stupid Useless Ways to Invoke ColdFusion Components

Sunday, May 31, 2009

Warning: The content contained herein contains utterly useless, potentially offensive, and very juvenile language. This is not suited for just about everyone.

There are many levels of stupidity - I believe in, and have worked very hard at, exploring many such levels in theory and in practice. Though some individuals are gifted with natural stupidity, I believe to be a true and utter mooncalf demands rigorous discipline and hours of practice. To support this process, you can explore other distinct facets of stupidity ranging from the simple-moron to the mullet-sporting-crank-snorting-utter-fucking-bonehead. To be more than a mere journeyman dolt, however, demands discipline and, above all, dedication.

In this small and inane piece, I will attempt to demonstrate how a programmer can proceed from a state of being simply moronic to a high level random-self-inflicted-headwound-fuckhead. The key lies is in using what little brain power you might have towards something of little or no utility whatsoever. Remember this and I truly believe you will go nowhere but backwards.

7 Totally Stupid Useless Ways to Invoke ColdFusion Components

Full stupid source code available here (click the Download button for a zip/tar file)

This is the stupid component under test we will invoke in 7 truly dumb ass ways.

All these examples are written as MXUnit tests, which, by doing so, has arguably decreased my own stupidity rating. Note also that these are written in <cfscript>. This reduces the number of keystrokes required in order to write useless piss-ant code.

Here's the setUp(): #7 (Simply Moronic) #6 (Approaching Idiocy) #5 (The Java Loser) #4 (Douche Bag) #3 (Turd Mongrol) #2 (Dumbass Pissant) #1 (Asshat Monkey Shit Hurler)

Stupid source code here

Feel free to post stupid code or links to such. Using Gists might be cool, though they're not stupid.

CI with Hudson, CF, and MXUnit: Configuring ANT and Running Tests

Friday, May 29, 2009

In the last entry, I showed how to get Hudson set up and connected to your SVN server. In this entry, I'll demonstrate how to run your MXUnit tests in a Hudson project.

If you’re already running your MXUnit tests with ANT, then this should go quickly. If not, then you’ll need to read this first. Create your ANT build file (build.xml), create your “runTests” target (or whatever you want to call it), and get your test runs working from within Eclipse or at the command line. Only after you get those working should you try integrating with Hudson… one thing at a time.

Configuring ANT within Hudson

Hudson needs to know where your ANT install lives. If you haven’t downloaded ANT, do so now, unzip it, and put it somewhere. Then, copy the path to that location.

From your main Hudson screen, click on “Manage Hudson”, then “Configure System”. More quickly, type “configure” into the search box and it’ll take you to the same place. Go down to the “ANT” section, click “Add”, and paste that path to your ANT install. Note, this is NOT the “bin” directory… just the ANT root. Give it a name, like “ANT 1.7” or whatever. Click Save

Hudson will not treat this ANT location as the default location. You must (at least, I did) have to explicitly choose this ANT instance for every project setup. Just so you know. This tripped me up at first.

Sample ANT build file


<?xml version="1.0" encoding="ISO-8859-1"?>

<project name="Sample" basedir="." default="main">

<target name="init">

<property name="testroot" location="../tests/framework" />
<property name="componentPath" value="mxunit.tests.framework" />
<property name="server" value="localhost" />
<property name="port" value="80" />

<!-- wherever the mxunit-ant.jar lives -->
<property name="mxunitant" location="../ant" />
<property name="mxunitjar" location="${mxunitant}/lib/mxunit-ant.jar" />
<property name="mxunitxsl" location="${mxunitant}/xsl" />

<!-- this is where the xml and html will live -->
<mkdir dir="testresults" />
</target>

<target name="runtests" description="Make output directories and run the MXUnit task" depends="init">
<taskdef name="mxunittask" classname="org.mxunit.ant.MXUnitAntTask" classpath="${mxunitjar}" />
<mxunittask server="${server}" port="${port}" outputdir="testresults" verbose="true">
 <directory path="${testroot}" recurse="false" packageName="${componentPath}" componentPath="${componentPath}" />
</mxunittask>

<mkdir dir="junithtml" />
<junitreport todir="junithtml">
 <fileset dir="testresults">
  <include name="*.xml" />
 </fileset>
 <report format="frames" todir="junithtml" styledir="${mxunitxsl}" />
</junitreport>
</target>


</project>

Configuring your project’s test runner step

Navigate to your project, then click “Configure”. More quickly, you can search for your project by name, then search for “configure”, and you’ll get to the same screen.

Find the "Build" section. click "Add build step". Select "Invoke ANT". Select the ANT instance from the dropdown list of installed ANTs. In the "target" field, type the name of the target in your ANT build file that you use to run tests. For example, "runTests"

This might be all you need. so you could save this and try to do a build now, and see what happens.

Test Runner Step Configuration, Part 2: Properties

Now’s a good time to talk about the weirdo nature of ColdFusion projects with respect to CI. Remember, you checked out your project from Subversion into Hudson’s workspace, but that’s not the code you care about… your code already lives on a DEV server and is updated by some other means. However, there is one file that gets checked out that you do care about: Your ANT build file.

When Hudson runs your ANT file, it’ll be running the one from its workspace. And then that build file will be executing its tests against the components you specify on your DEV server. Got it? Good. Confused? I know.

It’s possible that your build file’s runTests target might need some properties that are possibly set in a properties file that you don’t keep in SVN or which otherwise you need to override. For example, for MXUnit itself, our build file looks at a file named “unames.properties” to get some configuration information such as server name, port, usernames/passwords, webroot location, and some other things. This is NOT kept in SVN b/c it’s unique for each MXUnit contributor. When MXUnit’s runTests is run, it tries to read that properties file and then set the server, port, and webroot properties. But since that file isn’t checked out from SVN, it’s not visible in Hudson’s workspace and thus those properties never get set. It’s super easy to get around this though!

In your ANT step’s “Advanced” tab, you’ll see a “properties” box. In here, you can type in any properties in name=value format, linebreak-delimited, and poof, properties problem solved. For example, here’s what I put into the properties box for the MXUnit job:

server=localhost port=80 webroot=c:/inetpub/wwwroot

Configuring your project’s JUnit XML Output

In that sample ANT build file above, you saw how easy it was for MXUnit to spit out JUnit-compliant XML. Basically, no matter where your tests actually run (http://blah/whatever/HttpAntRunner.cfc), your JUnit XML files will go in a directory relative to the build file that is running. Got that? That means that, as discussed above, your JUnit xml files will go in your Hudson workspace somewhere. This is perfect, because that’s where Hudson wants them to be.

For example, with the MXUnit build, the build file is at mxunit/build.xml. It specifies a location for the JUnit xml output as something that evaluates to tests/testresults/tmp/. So in the Hudson configuration for the MXUnit job, I specify the JUnit XML location as:

tests/testresults/tmp/*.xml

That’s it. So wherever your xml files go relative to your workspace root, simply go to the “Post Build Action” section of your job configuration, check the “Publish JUnit XML” checkbox, and enter in the path to your xml files, with *.xml, as I did above. Click save

Re-saving ant.bat

After I got the MXUnit project all set up, I ran the build; it executed the tests; Hudson read the JUnit XML (all tests passed). And then…. Failed. Failed?! WTF? WTF was failing? The Hudson console output (thank you, Hudson!) read: “The system cannot find the batch label specified”.

This wasn’t a Hudson problem. It wasn’t an MXUnit problem. Turns out, it was the ant.bat file giving me grief. That’s right… the ant.bat that ships with the eclipse ANT install. Perhaps had I been using a “proper” install, this wouldn’t have been the case. Nonetheless, I wasn’t. So, how to fix it? Simple

Open up ant.bat in Textpad. Notice that it’s in Unix format. Change the format to “PC”. Click Save.

Rerun the Hudson build. Oh Joy. Oh Rapture. A fully functioning test run with test results. Let the CI begin.

What’s Next?

Next up, configuring notifications.

Continuous Integration with ColdFusion, Hudson, and MXUnit: Getting Started

Thursday, May 28, 2009

This series will demonstrate how to set up a continuous integration (CI) environment for ColdFusion projects using Hudson CI and MXUnit. We’ll cover Hudson setup, MXUnit test runs and JUnit XML output, and a few notification mechanisms (email, IM).

Installing Hudson

This will cover the super-duper simple way to run Hudson, which you'd do for testing this stuff out. DO NOT RUN YOUR REAL CONTINUOUS INTEGRATION ENVIRONMENT IN THIS MANNER. If you already have Tomcat set up, then you know how to install war files so follow that procedure instead (i.e. drop the war where you put your war files, or use the admin to deploy the war. It's that simple)

  1. Download the Hudson war file and put it somewhere
  2. Open a command line and navigate to the war file location
  3. type “java –jar hudson.war”
  4. This will launch Hudson. You can navigate to http://localhost:8080 and from there, you’re ready to start

Pulling your project from Subversion (SVN)

  1. Click "create a new job"
  2. Give your job a name, and then select Freestyle Software Project
  3. Under Source Code Management, select SVN, and then plug in your project’s SVN location, eg http://svn.myproject/whatever/trunk
  4. From here, you can click “Save” and then perform a build by clicking “Build”. This will check out your code into the Hudson workspace for your project

But this code isn’t where I need the code to be! Good point. As I get started with this, I’m going to just keep doing it this way until I figure out a better approach. At least where I work, we have DEV servers where code is automatically updated from SVN anyways, and our unit tests all run against the DEV server. I’m not setting up a CI environment in order to set up yet another server; instead, I’m setting it up so that I can get better reporting and notifications while still executing the same tests against the same code.

Hudson does allow you to choose a “custom workspace”, but I’m not going to get into that right here as I’m not sure yet whether it’s relevant for ColdFusion projects. I can see people being tempted to set the Hudson workspace to an existing project location on a Dev server, for example. Time will tell if this proves to be a good idea

What’s Next?

See how easy that was? Next up, configuring ANT, running your tests, and recording results

ColdFusion and LiveCycle ES: Rights Management

Friday, May 22, 2009

This is the final part of a planned 3-part series on getting started with LiveCycle ES for ColdFusion developers. With this post, I aim to:

  1. walk through the steps for Configuring LiveCycle Rights Management
  2. show how to invoke the RightsManagementService webservice
  3. address some additional issues I hit which stakeholders should understand

Big Caveat: I’m just learning this stuff. I have not worked with an Adobe salesman or tech support, so it’s highly probable that the stuff I’m talking about in configuration is complete crap. This post is a diary of what I went through to merely get it all working, and by “working”, I mean “I was able to create a rights-managed PDF that communicates with the LC server”.

Configuring LiveCycle

Make sure the service is enabled in LC Admin: Services, Applications and Services, Services Management, Filter on “Rights Management”, and ensure “RightsManagementService” is running. Click on that link and ensure the default soap endpoint is enabled.

Create a new group

I’m not sure if I needed to do this, but I did it, so I’m documenting it.

  1. Settings – User management – Users and Groups
  2. Click “New Group” button. Created group named “Rights Management”
  3. Clicked through and gave the group permissions associated with Rights Management stuff. You do this when you get to Step 4 and then click “Find Roles”, then select the stuff that looks rights-management-ish. Again… consult a professional, not me.

Create a new user

For the purposes of this post, I’m going to skip anything related to creating new domains. Instead, when we invoke the webservice, we’ll just invoke with the default domain that ships with LC. It goes without saying that when you do this in the real world, you’ll need to a) know your sh*t and b) probably consult with a company to help you get all this set up. Again, this is just to get up and running for a POC.

Now, then:

  1. Settings – User Management – Users and Groups
  2. Click “New User”. Give this user a name, username, password, blah blah blah. For this POC, select “DefaultDom” as the domain. Click next
  3. Click “Find Groups”, and select the new Rights Management group that you created above
  4. At step 3, I ignored Find Roles and went to Finish.

Create a new Policy Set

  1. Services – Live Cycle Rights Management ES – Policies -- Policy Sets.
  2. Click “New”. Give it a name. Click next
  3. Search for a domain. I selected “Default Domain”. Click through and accept the addition.
  4. Click Next, then search for the User you just created. Click Next and give that user permissions to monkey with policies in documents
  5. I added that user to Document Publishers, too. Click through to finish

Create a new Policy

  1. Services – LiveCycle Rights Management ES – Policies
  2. Click the link for the Policy Set you just created
  3. Click the Policies tab, then click “New”
  4. Give your policy a name
  5. Apply whatever settings you want. Click Save
  6. Check its checkbox, then click the Enable Button. Click through to finish.
  7. In your webservice call, you’ll use the policy set name and the policy name, along with the user and domain you associated with the policy set

Grrrrrrr

If you do all the stuff I’ve just talked about, you might be thinking “Gee, the LC Administrator is a bit tough to get around”. I’d respond with “ya think, Beav?”. I have come to despise the administrator. I’m assuming that Adobe wants you to use Workbench for most of this stuff. That, to me, is the only possible explanation for creating an admin that is so user-unfriendly. It’s a navigational nightmare.

Configuring SSL

Set the Rights Management Server URL

Services – LiveCycle RightsManagement ES – Configuration – Server Configuration

Set the Base URL to an SSL URL. For my POC, I used https://localhost:8443

Enable SSL in JBoss

I followed Duane Nickull’s excellent instructions. A few gotchas though:

First, in a “note” in the middle of the page, he writes: “Note: If you installed the Adobe LiveCycle 7.2 release using the turnkey installers, the path to this will be different. It should be: $JBOSS_HOME/server/all/deploy/jbossweb-tomcat50.sar”.

Pay attention to that note. Don’t gloss over it.

Second, a very very important point that is not addressed (well… I believe it’s just plain wrong, at least as of this writing): when you create the keystore, you need to set the “first and last name” as the name of the server on which you intend to deploy this. For my POC, I used “localhost”. In fact, I used “localhost” for every damn answer. Note that this is just if you’re using a self-signed keystore; if you used a real one (i.e. you buy a cert), you won’t have to go through this rigamarole.

Finally, Duane shows how to get the cert installed via FireFox. On my Vista machine, this didn’t work. I had to use Internet Explorer, and I had to follow the steps below.

Now, if you haven’t done so already, restart JBoss.

Making your cert a “trusted” cert on your machine

  1. In Internet Explorer, navigate to the URL you specified in the Server Config above. For example, I navigated to https://localhost:8443
  2. It’ll give you a red error address bar, so you’ll need to install the certificate. Right click and hit “install” or whatever the options are.
  3. This will launch IE’s certificate install wizard. Start the process, and when you get to the certificate store page, do not accept the default. Instead, select “Place all certificates in the following store”, click “browse”, and select “Trusted Root Certificate Authorities”.
  4. Click through to the end and you should be all set up.

Invoking the RightsManagementService with ColdFusion

<cfscript>
creds = {username='administrator',password='password'};
serviceRoot = "http://localhost:8080/soap/services/RightsManagementService";
wsdl = "#serviceRoot#?wsdl";
ws = createObject("webservice",wsdl,creds);
ws._setProperty("javax.xml.rpc.service.endpoint.address","#serviceRoot#?blob=base64");

filePath = expandPath("readme.pdf");
theFile = fileReadBinary(filePath);

inPDFDoc = {contentType="application/pdf",binaryData=theFile};
documentName="readme.pdf";
policySetName="Marc Policy set";
policyName="loose2";

response = ws.applyPolicy(inPDFDoc,documentName,policySetName,policyName,"cf","DefaultDom");

outputData = toBinary(response.getBinaryData());
</cfscript>

<cfset newfile = expandPath("readme_withrights.pdf")>
<cffile action="write" file="#newFile#" output="#outputData#">

Additional Issues and Considerations

As of this writing, whenever I open a rights-managed PDF created using the above steps, the PDF still prompts me twice: Once telling me that the PDF has to connect to the LC server, and once asking me for a username/password. I am 99% certain this is a configuration problem on my end. I just haven’t dug enough to figure it out yet. If you know how, please let me know. When I get back to my LC proof of concept, I’ll get the answers and update this post.

I believe it’s important for stakeholders deciding whether Rights Management is right for them to get solid answers – with proof – regarding the user experience with RM-managed PDFs. In my specific case, the PDFs wouldn’t be for internal consumption; rather, they’d be sent out to the masses, whose technical savvy could range from “My grandmother” to “my boss”. Bottom line: know your users.

ColdFusion and LiveCycle ES: Reader Extensions

Thursday, May 21, 2009

With this post, I aim to

  1. walk through the steps I took to get LiveCycle configured for applying Reader Extensions
  2. show how to invoke the ReaderExtensions webservice with ColdFusion

With this post, I do not aim to show you how you’d actually use the ReaderExtensions in real life. I have no idea if “real” production applications would be invoking these services; It seems that “The LC Way” involves you creating new processes in LC Workbench and using watched folders and such. I do not know what benefits are conferred by that approach over the approach I’ll demonstrate below. Again, as I said in my first post on this topic, this series is my way of recording what I went through to get this stuff working as I build a proof-of-concept.

Configuring LiveCycle

Login to LC, and click “Services”. Then go to “Applications and Services”, then “Services Management”. In the resulting dropdown, select “Reader Extensions” and submit. Check off the “ReaderExtensionsService” checkbox, and hit the “start” button if it’s not started.

Click on that link, and then select the checkbox beside “Default Soap Endpoint”. Click the “enable” button if it’s not enabled.

Click on the Services tab, and from there you can control whether to require authentication (which you’ll pass in the “creds” struct below) and also how to run the service. I kept mine at “System”, but I imagine in real production you’d run it as something else. I’m no LC expert, so I have no valid opinions here.

Invoking the ReaderExtensions webservice with ColdFusion

Invoking the ReaderExtensionsService from ColdFusion is reasonably easy, once you get around a few gotchas. First, you will probably need to pass authentication credentials. To get started, I just used the credentials I use to log in to LC Admin. You can turn off the need for credentials by going into LC Admin, navigating to the ReaderExtensionsService config, and turning authentication off.

According to the docs, you can get your extended PDF back from the webservice in 4 formats: base64-encoded, mime, dime, and as binary via a URL. I’ll show you the base-64 and remote URL approaches.

Base64

<cfscript>
creds = {username='administrator',password='password'};
serviceRoot = "http://localhost:8080/soap/services/ReaderExtensionsService";
wsdl = "#serviceRoot#?wsdl";
ws = createObject("webservice",wsdl,creds);
ws._setProperty("javax.xml.rpc.service.endpoint.address","#serviceRoot#?blob=base64");

filePath = expandPath("readme.pdf");
theFile = fileReadBinary(filePath);

inPDFDoc = {contentType="application/pdf",binaryData=theFile};

usageRights = {enabledComments=true,enabledCommentsOnline=true,
 enabledDigitalSignatures=true,enabledDynamicFormPages=true,enabledFormFillIn=true,
 enabledOnlineForms=true};
applyOptions = {message="",modeFinal=true,usageRights=usageRights};

response = ws.applyUsageRights(inPDFDoc,"marc","njUvw9Lnftxxxx",applyOptions);

outputData = toBinary(response.getBinaryData());
</cfscript>
<cfdump var="#outputdata#">

<cfset newfile = expandPath("readme_extended_withbinary.pdf")>
<cffile action="write" file="#newFile#" output="#outputData#">

Notables

First, note the very important couple of lines for getting LC to return the data in base64 format. Possibly this trick is new to you. It was to me, too, before I needed to dig into CF webservices and find out how to change the endpoint address after setting the wsdl in the createObject call. If you wanted mime or dime return, you’d do blob=dime or blob=mime, respectively. You can also do blob=http and it’ll give you the same result as the way I’ll do it down below. This endpoint resetting really tripped me up at first. I kept trying to call response.getBinaryData(), and the binary was empty. So, this is for you google searchers: empty binary data.

Second, note that in your call to applyUsageRights, you need to pass valid user credentials. That crazy username/password combo was what I got from LC when I downloaded the trial version.

Finally, the webservice call returns a datatype named “Blob”. No, this isn’t like a database blob. Instead, it’s an object of Adobe’s devising (I presume) that contains several methods you can call. CFDUMP it to see what’s available to you. Anyway, when you specify blob=base64 in the endpoint address, you can get back the new reader-extended PDF by calling response.getBinaryData(), and then you write that to a new file. Not that it matters, but I really like the Blob return type. It’s a great way to get consistent webservice calls across the various LC services. Props, dudes.

RemoteURL

<cfscript>
creds = {username='administrator',password='password'};
ws = createObject("webservice","http://localhost:8080/soap/services/ReaderExtensionsService?wsdl",creds);

filePath = expandPath("readme.pdf");
theFile = fileReadBinary(filePath);

inPDFDoc = {contentType="application/pdf",binaryData=theFile};

usageRights = {enabledComments=true,enabledCommentsOnline=true,
 enabledDigitalSignatures=true,enabledDynamicFormPages=true,enabledFormFillIn=true,
 enabledOnlineForms=true};
applyOptions = {message="",modeFinal=true,usageRights=usageRights};

response = ws.applyUsageRights(inPDFDoc,"marc","njUvw9Lnftxxxx",applyOptions);
</cfscript>

<cfset newfile = expandPath("readme_extended_withRemoteURL.pdf")>

<cfhttp url="#response.getRemoteURL()#">
<cfdump var="#cfhttp#">

<cffile action="write" file="#newFile#" output="#cfhttp.filecontent.toByteArray()#">

Notables

Note that I’m using normal old createObject with a wsdl path… no resetting the endpoint here. When you call the service by default you get the response via a remote URL, NOT binary. This means you need to do a cfhttp call to the response object’s getRemoteURL() method, and then you use cfhttp.filecontent.toByteArray() to write it to a new file.

Finally, I’m using the inline struct notation in these examples, but if you’re on a previous version of CF you can convert this code to normal old structnew() and you’ll be fine. Nothing about these calls should be specific to a version of CF.

Credits

Props to this blog post, which was the first post I read on using ColdFusion and LC together. This saved me a lot of time getting started.

Getting started with LiveCycle ES for ColdFusion Developers

Monday, May 11, 2009

 

What is LiveCycle and why am I doing this?

From the website: “Adobe LiveCycle® ES (Enterprise Suite) software is an integrated server solution that blends data capture, information assurance, document output, process management, and content services to help you create and deliver rich and engaging applications that reduce paperwork, accelerate decision-making, and help ensure regulatory compliance.”

If you have trouble wrapping your mind around what exactly it is that LC ES can do you for you, you’re not alone. It’s not that LC is a solution in search of a problem; rather, it’s that LC does a lot of stuff! At its heart, LC is an enterprise Java app that provides a suite of services around document and information management.

I, however, do not yet have my head around all of its awesome. For me, it’s about one thing: doing stuff to PDFs that I otherwise couldn’t do, namely 1) unlocking functionality that lives in the PDF but which can only be exercised with Acrobat and 2) programmatically applying security policies to those PDFs. My company produces PDFs for public consumption, and the people opening those PDFs will probably not have Acrobat… just Reader.

Specifically, what I’m interested in is enabling Reader to save PDFs with form data still in tact; enabling “add comment” functionality in Reader; enabling digital signatures; and adding a “kill switch” into PDFs so that if the data goes out of date or is shown to be incorrect, the next time a user opens the PDF, the PDF can “phone home”, get instructions that the PDF is no longer valid, and give the user instructions for how to get a new version of the PDF.  And I need to do all of this programmatically.

You can do all of this with LiveCycle; you can do all of it with web service calls (i.e. SOAP); and you can do it all with ColdFusion.

To be clear: you are not dropping some jar files into your ColdFusion install. You are setting up a full JEE server (JBoss, WebSphere, whatever version of LC you download), and you are writing ColdFusion code that will send PDFs to the LiveCycle server, ask LC to do stuff to the PDF, and get new bytes in return. Then, rather than distribute the “source” PDF, you’ll distribute the new “extended” PDF.

Finally, this is not about LiveCycle Data Services (LCDS). That’s a part of LiveCycle ES, but it’s not the part I’m interested in for this short blog series. Lots of people have written (with copious examples) about using LCDS with CF. This series will be about using other parts of LC, namely Reader Extensions and Rights Management.

Installing LiveCycle ES

For me, the fastest way to get LiveCycle up and running on my machine was to download the "Turnkey" trial edition here: http://www.adobe.com/cfusion/tdrc/index.cfm?product=livecycle

I selected the JBoss option because I have no experience with WebLogic or WebSphere.

I'd say leave yourself at least a couple of hours to have LiveCycle installed and operational. This isn't a 5-second Tomcat download and 10-second exe install. It's a massive application, so adjust your expectations. Don't start this when you have an hour to go before you leave work (well... start the download then, and then let it go while you're driving home)  It's a weighty download, at almost 3 gig.

You'll notice that there's no 64 bit download. This bit me in the ass. I am running this on 64 bit Windows, running the latest 64 bit JDK. The docs tell you that this only works on JDK5. Now, I don't know about you, but I'm the kind of guy who says "yeah, right", and proceeds. Fortunately, the LiveCycle installer asks you for your JDK path, and when you give it a Java 1.6 path, it won't let you proceed. Good on you, LiveCycle.

So, off I went to get a 1.5 JDK (http://java.sun.com/javase/downloads/index_jdk5.jsp). I downloaded the 64 bit JDK cuz that's how I roll. Installed it, changed the JAVA_HOME environment variable to point to it, and off I went with the installer.

Remarkably, I hit no other problems during the install. It takes a very long time, mind you. At times it might *appear* to be hung. Let it ride.

So, it finished installing, then said "Starting JBoss Service".  And at that point, FAIL. JBoss started, then shut down right away.  Now this is more like it! I expected more of this, honestly, so I was kind of pleasantly surprised.  Off I traipsed to the Windows Event Viewer, where I found this gem: "The LoadLibrary function failed for the following reason: LoadLibrary is not a valid Win32 application."

Obviously, this is due to my 64 bit JDK. So I proceeded to futz about in the JBoss install directory, looking for a .config or .properties or .xml or .whatever file that appears to point to my jdk, thinking I can just go download the 32 bit JDK, install it, change the config file to point to that, and be done with it.  This was not to be.  I'm no rocket surgeon, but as near as I can tell, the JDK path is either a) set into a registry entry or b) stuck in the Windows service config somewhere. I doubt it's the latter though because even starting JBoss with the bat file produced the error. So my money's on the registry entry. Anyhoo, not being adventurous (this was later in the evening), and being generally lazy when it comes to this stuff, I just installed a 32 bit JDK and restarted the LiveCycle install.  A few "OK" button clicks and gin & tonics later, and I was up and running.

It takes about 10-15 minutes for LiveCycle to become responsive once JBoss starts, so don't be surprised when "starting JBoss" or 'starting LiveCycle" takes a really long time.

You hit the admin UI link that they tell you on the installer, and up it pops. You will be greeted with a login screen reminiscent of the ColdFusion administrator. You’ll log in, and the similarities will end there. Queue the spooky music… you have entered a new dimension of sight and sound….

Summary

1) download the JDK 32 bit version
2) set your java_home variable to point to that version
3) when you download the installer, you'll be given a "serial number". I imagine this is just a stock trial serial. At any rate, copy it into a text file because you will need it later.
4) You will be prompted for a "credential" at some point during all of this. This is important! Write it down. I chose "Marc" as my credential, and then it gives some gibberish password. You will need this.

Next up.... Invoking the ReaderExtensions web service.

Articles on TDD and ColdFusion on Adobe Developer Connection

Tuesday, May 5, 2009

We're happy to announce a 2-part series on TDD and ColdFusion is now on the Adobe Developer Connection. Part 1 is here: http://www.adobe.com/devnet/coldfusion/articles/testdriven_coldfusion_pt1.html Part 2 is here: http://www.adobe.com/devnet/coldfusion/articles/testdriven_coldfusion_pt2.html Enjoy!

Timesavers: GMail Keys

Monday, May 4, 2009

This is part of an ongoing series on Timesavers. The goal is simple: short, easily-digestible posts designed to help developers get faster and more productive

I’ve been a GMail user for quite some time, but only recently have I started using the GMail Keys feature. What a bonehead! Keys rock.

Why I love Keys

  • Read every single email without clicking the mouse
  • Easily "mark" emails read/unread/archived. For example, I get a lot of digest emails. I do skim most of them, but some days, I don't have time, so I'll mark em and archive em for later
  • Perform common searches (all unread items in inbox) with just a few keys
  • See the Keys Help with a single key combination (shift-Q)

Here's what that help looks like, by the way:

gmailkeyshelp

Frequently Used Keys

From a message list (like the Inbox)
  • c to compose
  • x to select messages.
  • j to go to next message. key to go to previous message
  • y to archive
  • enter to go into a message
From a message (i.e. you're reading an email)
  • x to get back to your list
  • if it’s a multi-message conversation, use n to go to the next message, and p to go to the previous message. hit enter to expand if it’s not expanded

You can also do searching really easily. Hit “/” to focus on the search box, then type some common phrases like “is:unread in:inbox” to show all unread messages in the inbox. In the video below, you’ll see more of that.

And finally, shift-? shows the help for Keys

See it in Action

This isn’t the greatest video, but I love the java posse and the content of this lightening talk is a solid intro to using GMail Keys. I give you… the Dick Wall’s introduction to Keys.

Timesavers: Firefox Goodies

Friday, May 1, 2009

This is part of an ongoing series on Timesavers. The goal is simple: short, easily-digestible posts designed to help developers get faster and more productive

This Timesaver is a quickie for some of the ways I stay fast in Firefox. I’m purposely leaving out Firebug, Greasemonkey, and any other add-ons for now. This is just native Firefox stuff.

Keyboard Shortcuts

  • Ctrl-T to open a new tab
  • Ctrl-L to focus on the address bar. I probably use this more times during the day than any other shortcut
  • Ctrl-Enter to prefix with www and suffix with .com. For example, I’ll ctrl-L to the address bar, type facebook, then ctrl-enter. This could be shortened even further by adding a bookmark for facebook and giving it a keyword, like “fb”. Then I’d just type “fb” in the address bar and off I’d go to waste more time.
  • Ctrl-F to find. I am amazed at how many times I see developers use the mouse to pop up the find box in Firefox and IE.
  • “/” to start finding text right away without hitting ctrl-F
  • ‘ to start finding links right away. That’s an apostrophe if you couldn’t make it out. This is fast because if you have an idea of the links you’re searching for, like “contact”, you can hit apostrophe, then start typing “cont…” and then when it focuses on the link, you hit “enter”
  • Backspace to go Back. Shift Backspace to go forward
  • Ctrl-page-down to go to the next tab. Ctrl-page-up to go backwards through the tabs
  • Ctrl-+ to zoom in. I need this because so many of the young hipster bloggers these days think it’s cool to write in 5 pt verdana. Ctr- - to zoom out (that’s control minus). And Ctrl-0 to return everything to normal.

The full list of shortcuts is here: http://support.mozilla.com/en-US/kb/Keyboard+shortcuts

Substitutions in Bookmarks

You know how when you focus in the address bar, and you type “google cat pictures”, and it does a Google search on cat pictures? It’s doing that with substitutions. Or try this -- Add this bookmark: "http://dictionary.reference.com/browse/%s" and give that bookmark a keyword of "dict". Then, Ctrl-L to your location bar and type “dict pedantic”. It’ll do a Dictionary search for the word pedantic. All that’s happening is that there’s a link stored in a bookmark, and somewhere in the link is “%s”. And the bookmark has a keyword assigned to it. So when you type the keyword -- “dict” for example – it loads that bookmark. Then, it sees the %s and expects something to come after the “dict”. so whatever else comes after the keyword in the address bar, Firefox will substitute for the %s.

Where I work, this is particularly useful for loading URLs with a well-known pattern whose identifiers only differ by some ID number. Let's say I have a bookmark for executing the "build PDF" function in one of our applications. We'll give it a bookmark of http://app.foo.com/index.cfm?fuseaction=build&id=%s. I'll give it a keyword of "build". Then, to execute it in the url, I would type "build 1041", and it'd replace %s with "1041".

Think of all the URLs you visit that differ only by some word or ID or whatever... they're prime candidates for keyword substitution.

Something I'm missing

I wish Firefox had a shortcut for "Send Link...". I know, I know... this is being rather pedantic. After all, you can just hit alt-f-e and do it the normal old windows shortcut start-with-alt-and-follow-the-letters way. But that feels cheap. I wish I could assign keys, so that I could do Ctrl-M.

What are some of your favorite built-in Firefox timesavers?