Tuesday, September 05, 2006

Rails notes as I start looking at Ruby

I've started working on a Ruby on Rails side project, though I haven't had as much time for it as originally hoped. Really, I was up and running and writing code to production on an existing Rails app in a # of hours!

First, ActiveRecord is very nice. From a DAO oriented Java background (with a sprinkling of Hibernate), ActiveRecord is simply amazing. I love the Model based finds and the automatic find_by_name type methods. These guys have really developed a great framework.

Rails from a web side is very quick to develop, especially when compared to the Eclipse -> Ant -> Weblogic Deploy. You go from accepting a 2-5 minute build-deploy cycle to just a few seconds of saving a file in Rails.

Capistrano for deployments is slick. It's like having a standardized deployment environment across rails apps, something that J2EE has never gotten close to. Doing a rake remote:deploy and knowing that a backup of your production has already been made is wonderful. Rollbacks are as simple as rake remote:rollback.

I really got bit by subversion a couple weeks ago (though this doesn't deal with RoR specifically, it seems to bite a lot of us). I was updating the rails version due to the recent security holes, but subversion was coughing up all over it. Re-freezing Rails Gems Using Subversion saved my day.

(Update: It looks like my side project has died today, for reasons I cannot control. So hopefully I'll find another one to work with soon.)

Wednesday, July 26, 2006

Major Enterprise Ruby on Rails Issues?

Greg Luck has written a Report from OSCON2006: The Ruby Conspiracy where he proceeds to smash Ruby on Rails.

First, I'm just starting to get past the Rails tutorials so I have NO (zero) knowledge of Rails at an Enterprise level. And I've had similar thoughts to Greg's that Rails was being pushed for the betterment of the speakers before.

So really I'm asking a question here... Are the points that Greg makes true?

Does Active Record really not have support for Prepared Statements?
We have two production applications running on Ruby. And how is it. Well, despite being perhaps no more than 5% of the functionality of our applications, Ruby on Rails is the number one consumer of Oracle CPU and logical gets. Why? Rails does not support prepared statements, so Oracle has to reparse every time.


He then goes on to say:
And ActiveRecord seems not to have learnt Hibernate's lession; that OR tools suck for performance and need caching tricks to make them work well.

Although maybe this is a result of Prepared Statements being absent?

Then, he has issues with Rails not running through a connection pool, because fastcgi is forking processes? Really? That sux:
Also, our Rails apps running in (now unmaintained) fast-cgi regularly go awry and fork more processes. Each one creates a new connection to Oracle. So, the opposite of connection pooling; connection denial of service.


Next:
And does Ruby support Unicode. Not really. And is Rails threadsafe? No.

Not threadsafe? Woah! Is this true?

So I'm really looking for answers now. Is everyone that is pushing Ruby on Rails really looking for more money, and not thinking about the enterprise readiness of the product? I know the 37signals success stories, and there are many more, but what of these questions that Greg raises?

Wednesday, July 19, 2006

Groovy OJUG Talk last night

Last night at OJUG (Omaha Java Users Group), Scott Hickey gave an awesome talk over Groovy. I wish I had a link to his website, but I didn't see one. He is the lead on the groovy Eclipse plug-in, and is currently finishing an article for the IBM DeveloperWorks Practically Groovy series covering groovy and spring. He's been writing production groovy code for a few years on a mission critical financial app.

He covered some great code examples comparing java and groovy. Things seem to be written much easier (as like most dynamically typed languages), and it's cool that groovy runs in the same jvm as the rest of the code. From what I could tell, the syntax looks a lot like Ruby.

I liked his example showing how he did some Test First development by using a Map in his test, and later replaced with an object because of the dynamic typing.

He stressed that groovy by design uses BigDecimal behind the scenes, which is great when used in math statements. 1.1 + .1 should = 1.2, but in java it equals 1.19999999 except when using BigDecimal. He had some great examples here too.

He mentioned catching exceptions only when you want to. This was a bit scary to me, but I think in practice I might agree.

As for his Eclipse groovy plugin... They are looking for some help in finishing the code completion portion. It's a difficult task in a dynamically typed language. I'd advise him to look at the javascript Eclipse plugins. The latest ones try to guess what object you are code completing by remembering previous methods that you have called. This works surpising well, and may be enough for them to use IMHO....

Thanks to Scott for a great talk, and to Matt for pulling it all together...

Tuesday, June 13, 2006

Firefox AJAX Bug - Plus Workaround

Today we stumbled across a fairly significant firefox bug with popup windows and making XHR requests. Here is the scenario:

We have a calendar selection popup window for our users to select a date (typical of any reservation website). User clicks calendar icon, calendar select popup appears, user selects date, popup window closes & fills text field with date.

Today we wanted to add an AJAX call triggered just as the popup window closes. This call would request filtered data for another field based on the date selected. The AJAX call (via DWR) was working fine when we didn't use the calendar popup, but when using the popup we would get "No data received from server" from DWR.

Luckily we found a reference to the firefox bug on the dwr mailing list.

Basically, Firefox incorrectly tries to make the XHR call from the popup window (even though the javascript explicitly says to call the XHR from the opener). The workaround is to call the dwr function from inside a window.setTimeout('myAjaxCall()',0). This will allow the window to close successfully in Firefox.

Here's the code example from the example website:
Without seeing your code its hard to say, but I bet that from your popup you are invoking a dwr call on the popup's window.opener. (i.e. in your popup you have something like window.opener.makeDWRCall()). The problem is when you do that, the XMLHttpRequest is "owned" by the popup window even though the call resides on your main window.

If you take a look at the Firefox bug listed above you will see a workaround to the issue:

function closePickupWindow(id) {
opener.pickupId.value = id;
if (opener.pickupFunctionPointer != null) {
opener.launchLookup();
}
window.close();

}

// This is to work around the following bug in firecox
function launchLookup() {
window.setTimeout('pickupFunctionPointer()', 0);
}

Some of this code is extraneous, but the basic idea is that from your popup you call a function on window.opener that uses setTimeout to issue the DWR call. Note that the timeout can be instantaneous because all you are really trying to do is change the caller of the DWR function to window.opener instead of your popup.

Hope this helps.
John Kleinschmidt

Tuesday, May 30, 2006

My Scriptaculous Local.InPlaceEditor extension

I really like the script.aculo.us Ajax.InPlaceEditor, but it's missing two things that I need.

One, it only edits a single field at a time. It would be much nicer IMHO to edit an entire form at once.

Two, it requires Ajax to submit the form and display the result. Nice and all, but sometimes I want to submit the form old-school style with a POST or GET and have the server generate the result. I tackled this today and have called it the Local.InPlaceEditor.

Local.InPlaceEditor requires that a form already is wrapping your text. When creating it the 'url' param is needed but ignored, and you need to supply two new options: externalFormId:'reportGroupsEdit',formFieldName:'reportGroupName'

It would be nice if someone rewrote these two with a nice InPlaceEditor.Base like the AutoComplete classes. This extension is a bit of a hack, since it makes a handful of assumptions.

Here's the code that I have placed in our extensions.js file. Post any questions below and I'll try to answer them.


var InPlaceEditor = {}
InPlaceEditor.Local = Class.create();
Object.extend(InPlaceEditor.Local.prototype, Ajax.InPlaceEditor.prototype);
Object.extend(InPlaceEditor.Local.prototype, {
enterEditMode: function(evt) {
if (this.saving) return;
if (this.editing) return;
this.editing = true;
this.onEnterEditMode();
if (this.options.externalControl) {
Element.hide(this.options.externalControl);
}
Element.hide(this.element);
this.createForm();
this.element.parentNode.insertBefore(this.form, this.element);
Field.scrollFreeActivate(this.editField);
// stop the event to avoid a page refresh in Safari
if (evt) {
Event.stop(evt);
}
return false;
},
createForm: function() {
if (this.options.externalFormId) {
this.form = document.createElement("span");
// No bound onSubmit, so the ajax part won't kick off
} else {
this.form = document.createElement("form");
Element.addClassName(this.form, this.options.formClassName)
this.form.onsubmit = this.onSubmit.bind(this);
}
this.form.id = this.options.formId;

this.createEditField();

if (this.options.textarea) {
var br = document.createElement("br");
this.form.appendChild(br);
}

if (this.options.okButton) {
okButton = document.createElement("input");
okButton.type = "submit";
okButton.value = this.options.okText;
okButton.className = 'editor_ok_button';
this.form.appendChild(okButton);
}

if (this.options.cancelLink) {
cancelLink = document.createElement("a");
cancelLink.href = "#";
cancelLink.appendChild(document.createTextNode(this.options.cancelText));
cancelLink.onclick = this.onclickCancel.bind(this);
cancelLink.className = 'editor_cancel';
this.form.appendChild(cancelLink);
}
},
createEditField: function() {
var text;
if(this.options.loadTextURL) {
text = this.options.loadingText;
} else {
text = this.getText();
}

var obj = this;

if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
this.options.textarea = false;
var textField = document.createElement("input");
textField.obj = this;
textField.type = "text";
textField.name = this.options.formFieldName || "value";
textField.value = text;
textField.style.backgroundColor = this.options.highlightcolor;
textField.className = 'editor_field';
var size = this.options.size || this.options.cols || 0;
if (size != 0) textField.size = size;
if (this.options.submitOnBlur)
textField.onblur = this.onSubmit.bind(this);
this.editField = textField;
} else {
this.options.textarea = true;
var textArea = document.createElement("textarea");
textArea.obj = this;
textArea.name = this.options.formFieldName || "value";
textArea.value = this.convertHTMLLineBreaks(text);
textArea.rows = this.options.rows;
textArea.cols = this.options.cols || 40;
textArea.className = 'editor_field';
if (this.options.submitOnBlur)
textArea.onblur = this.onSubmit.bind(this);
this.editField = textArea;
}

if(this.options.loadTextURL) {
this.loadExternalText();
}
this.form.appendChild(this.editField);
}
});

Thursday, May 25, 2006

Eclipse Mac OS X CVS Update Bug?

So I go into Eclipse (3.1.2) on my OS X (10.3.9) box and do a Team Update from CVS. Anytime that a file has been deleted from cvs by someone else's commit I get this error:
Problems encountered while deleting resources.

I get this error for EACH file that was deleted. Then I have to open the properties on each file and unselect Read Only. After this I can Team | Override And Update to remove the file.

Does this happen to anyone else on their Mac? I've never had this issue on Windows. I think the bug is in OS X holding the file as read only and locked, but I don't know. It's very frustrating and time consuming to deal with.

Monday, May 22, 2006

IE Left Margin Missing Bug

This one has been bugging me for a long time before finding the answer today...

In IE I couldn't get absolute positioned elements in our left-hand Search pane to appear correctly. The would get pushed onto our right-hand content pane. After thinking about it overnight (well, over multiple nights) I realized that IE was not noticing our negative left or right margins (One True Layout stuff).

A search today reveals the answer from PositionIsEverything
If #wrapper is static or relative, it must have a width, or it and the <DIV> it contains will lose their left margins in IE. If it's absolute, lack of a 'width' will not trigger the bug.


So I went back through and added width:100% or width:998px to the container divs that were position:static or position:relative. Everything now works beautifully!

All of this stems from my desire to use script.aculo.us local autocompletion (which requires an absolutely positioned list) to replace a VERY long drop down select list that we have.

Wednesday, March 01, 2006

Apple finally coming to town!

While I don't really like the title (Middle America? come on, we're the Heartland or something, but not Middle America!), we're finally getting an Apple Store!

Although I wish it was downtown or closer to midtown instead of out in the suburban "lifestyle center", I'm more than thrilled that we're finally getting one! Good thing I have some tax refund left over :-)

Displaytag new features awesome (in theory)

I was pumped to upgrade displaytag yesterday from 1.0 to 1.1. We needed the new feature to include the caption and footer in an export, along with some of the other new features that are included in 1.1.

First step was to download and install the displaytag.jar. I also installed the displaytag-export-poi.jar so I could use the new Excel POI support.

Then I had to upgrade our commons-lang, commons-beanutils, and commons-collections jars to the latest versions because of an update of the dependencies for displaytag. No big deal...

Started up my server, and everything looked good so far. My displaytag table showed up and I thought I was good to go.

Then I tried to export... Property not found... In displaytag 1.0 I used a decorator by simply saying decorator="my.MyDecorator" in the display:table tag. But now I get errors on the export because each export doesn't use my default decorator. So now I have to add
<display:setProperty name="export.excel.decorator" value="my.MyDecorator"/>
<display:setProperty name="export.csv.decorator" value="my.MyDecorator"/>
<display:setProperty name="export.pdf.decorator" value="my.MyDecorator"/>
<display:setProperty name="export.xml.decorator" value="my.MyDecorator"/>

to every jsp that I'm using a decorator. I submitted a jira issue to the displaytag team for this.

Now my exports are working, but the caption and footer were still not included, even though the release notes and jira issues say that this is fixed. I tried tweaking a few properties but nothing has worked. Anybody know the answer?

Next I wanted to switch the Excel export to use the new POI support. The one comment in the changelog says to
configure it into your displaytag.properties using 'export.excel.class=org.displaytag.export.ExcelHssfView'

...Oops, I get a message saying that ExcelHssfView is not found. So I explode the jar and see that the package is incorrect. I changed to this
export.excel.class=org.displaytag.export.excel.ExcelHssfView

and now my Excel exports look pretty :-)

Lastly I wanted to add the new RTF export feature (which is very vaguely documented, but has a cool demo). Here is what I added to my displaytag.properties:
export.types=csv excel xml pdf rtf
export.rtf.class=org.displaytag.export.DefaultRtfExportView
export.rtf=true

It seems like it starts to go, but then I get an exception during the RTF export. I'm wondering if this deals with my usage of the export filter?

I really love displaytag, and I'd really like these new features to work! Please fill me in, if anyone has gotten these items working. I added comments to the displaytag jira for each of these, and I'll update this post if I hear back from anyone...

[Update 11:27] Thanks to Jorge for responding so quickly on the jira issue for rtf exporting and caption/footer exporting. I'm working with him to see if we can get these two working...
[/Update]

[Update 15:31] I've found some progress on my issue:
For the caption/footer issue:
I had to setup the new export classes for PDF/Excel in my displaytag.properties file like this:
export.pdf.class=org.displaytag.export.DefaultPdfExportView
export.excel.class=org.displaytag.export.excel.DefaultHssfExportView

Apparently only these new classes will display the caption/footer? I didn't realize this before...

Secondly, the new classes only work when I remove my Decorator. So I'm going to look into my decorator and see why it fails on the exporting. My decorator works fine for any of the old export classes, but not the new ones that were added for the caption/footer. It throws the previous stack trace with the new export classes for RTF, Excel, and PDF.

For the RTF issue:
My setup from before works for RTF when I don't use my Decorator. There must be something that has changed in the new export classes that is different from the old for Decorator's.

Thanks again to Jorge for helping me out....
[/Update]

[Update March 2: 08:23] After some more trial and error, and a little help from Jorge, I found that the new export classes require your Decorator to implement
org.displaytag.decorator.hssf.DecoratesHssf for Excel and
org.displaytag.render.ItextTableWriter.ItextDecorator for PDF and RTF


I just left the implemented methods blank, since I don't need them. But they need to be there for everything to work...
[/Update]

Monday, February 06, 2006

Where are the open source car computer readers?

After having some car troubles this weekend I began wondering... Why do I have to take my car into a service shop and pay them to hook it into a computer for 5 minutes? Why do they charge to hook up to a computer for 5 minutes again? And if the computer in my hood knows something, and LCD readouts are dirt cheap, why can't the car companies put a small readout under the hood to tell me what is wrong? I'll never understand...

And why couldn't I just buy a little reader for $40 at AutoZone that could tell me the problem, AND I could reuse it, AND would be cheaper than the $50 - $100 that I'll be charged at a service shop? I'll never understand...

Monday, January 16, 2006

Vegas Conference? I'm there!

I've just registered for TheServerSide.com Symposium at Caesar's Palace in Las Vegas! I wish I could say that every month :-)

The weather near the end of march should be near perfect, even if I'll spend 80% of my time indoors...
March: 68 F / 43 F
April: 77 F / 50 F

Compared to my usual Omaha, this will be awesome (with the low in Vegas > the high in Omaha)!
March 38.6
April 51.9

Better than the weather should be the speakers. Here's what my agenda looks to be for the speakers that I am signed up for: Cedric Beust, Craig McClanahan, Cameron Purdy, Justin Gehtland, Dion Almaer, Rod Johnson or Kito Mann, Gavin King, Scott Ambler, Jonas Boner, Ted Neward, Bruce Snyder, and Bruce Tate (not to mention possible others!). I'm stoked to listen to these guys. My only question is Where's Matt Raible?