Fork me on Github s

Archive for category Lessons

JRuby 1.5 to provide native support for Ant

In case you haven’t heard, the next version of JRuby will provide native support for Ant.  Much like antwrap, you will be able to call ant tasks straight from Ruby.  There are some pretty good examples here, but no examples of how to get it running on your machine today.

  1. First, you will need to install Git SCM
  2. Next, create a directory, JRuby on your machine
  3. CD to that directory, and run ‘git init’
  4. Next, run ‘git pull git://github.com/jruby/jruby.git’
  5. Once it has finished downloading, you can run ‘ant’ to build it
  6. Now, just use the executable jar under bin to run the latest version of JRuby

Now get started converting those nasty ant builds to rake.

Bookmark and Share

Tags: , ,

No Comments

Function currying in Javascript

Do you catch yourself doing something like this often?


  Ajax.request('/my/url', {'myParam': paramVal}, function() {
    myCallback(paramVal);
  });

Creating a function which calls another function asynchronously is a bad idea because the value of paramVal may change before it is called.  Enter the curry function:


Function.prototype.curry = function(scope) {
  var args = [];
  for (var i=1, len = arguments.length; i < len; ++i) {
    args.push(arguments[i]);
  }
  var m = this;
  return function() {
    m.apply(scope, args);
  };
}

This function creates a wrapper around the function and ‘locks in’ the method parameters.  The first parameter is the scope of the function call (usually this or window).  Any remaining parameters will be passed to the method call.  Using the curry method the above call changes to:


Ajax.request('/my/url', {'myParam': paramVal}, myCallback.curry(window, paramVal));

Remember when passing objects to the curry method that the objects members may still change.

Bookmark and Share

Tags: ,

2 Comments

Design Patterns for Everyday Living: Front Controller

The front controller pattern has saved me a ton of time in my recycling efforts.  I started recycling about 2 years ago.  My first procedure was unsatisfactory.  I bought two trash cans, and would put all the trash we identified as recyclable into them.  Once they were full I would take them to the recycling center and put them in the appropriate containers.  The sorting procedure was executed at the facility and everything was sorted at one time.  This was both a time consuming and tedious procedure (kinda gross too).

Enter the front controller pattern…

I decided to buy separate containers and sort trash on the fly.  By moving the sorting procedure to the ‘front’ of the process, I was able to save time and effort.  Now I spend about 5 minutes at the facility and don’t have to handle any stinky trash.  From time to time I see a person who is sorting at the facility.  If only they knew how easy it was to implement the front controller.

Design Patterns for Everyday Living is a regular feature that describes how we can apply software design principles to our daily life.  Saving time, increasing productivity, and gaining a better understanding of their use in the software world.

View more Design Patterns for Everyday Living

Bookmark and Share

Tags: ,

No Comments

Sticky Note, A JavaFX Tutorial

JavaFX is Sun’s latest attempt at making an RIA friendly development technology.  It’s aim is to compete with tools such as Adobe Flash/Flex/Air, and Silverlight.  I am not going to do a comparison of these.  Instead, I will focus on my first JavaFX program, Sticky Note.

Sticky Note (launch it, dowload source) is intended to mimic the Windows 7 feature, Sticky Notes.  It provides a sticky note that the user can open and type of reminders.  These will be saved and restored between application runs.  For simplicity’s sake, this script will only allow one note.

What will I need to develop a JavaFX application?

All you need to do is download the latest Netbeans with JavaFX, and make sure you are running the latest version of Java.

In this example, we will be using a few features of JavaFX:

  • Ability to wrap swing components and use them in a JavaFX Application
  • Simple interface for storing state information on Disk
  • Variable binding with ‘bind’ and ‘on replace’ operators
  • Simple API for creating effects, like gradients and drop shadows.

It don’t mean a thing if it ain’t got that swing.

For this program we will need a multi-line textbox.  Unfortunately, the JavaFX API does not provide this.  So we will need to wrap a swing JEditorPane for use.  You can do this pretty easily,

def textbox: JEditorPane = new JEditorPane("text/plain","");
textbox.setBackground(new java.awt.Color(0,0,0,0));
textbox.setText(text);
def sbox = SwingComponent.wrap( textbox );

From here, you can easily use it as a normal JavaFX control.

Gotta save state.

JavaFX provides the Storage class to easily store & retrieve data.  We use the public-init variable source to set the name of the file to use.  This is relative to the currently running script.

var storage = Storage { source: "model.properties" }
{
  var resource: Resource = storage.resource;
  var properties: Properties = new Properties();
  var inputStream: InputStream;
  try {
    inputStream = resource.openInputStream();
    properties.load(inputStream);
    text = properties.get("text");
    noteX = Float.parseFloat(properties.get("screenX"));
    noteY = Float.parseFloat(properties.get("screenY"));
    noteWidth = Float.parseFloat(properties.get("width"));
    noteHeight = Float.parseFloat(properties.get("height"));
  } catch (e: Exception) {
    println("Exception in Model.load():{e}");
    e.printStackTrace();
  } finally {
    try {
      inputStream.close();
    } catch(e: Exception) {
      println("Exception closing inputstream {e}");
    }
  }
}

Saving is just the opposite.  We are using the dirtyModel variable to track whether the data has been changed since our last save.  Also, we are unable to bind the JEditorPane text property, so we have to manually do it.  I also have logic to prevent multiple saves since this method is called asynchronously.

// handle model storage
var dirtyModel: Boolean = false;
var saveInProgress: Boolean = false;
function saveModel() {

  // update text
  if( not text.equals(textbox.getText() ) ) text = textbox.getText();

  // only one save at a time, and only when necessary
  if( not dirtyModel or saveInProgress ) return;

  saveInProgress = true;
  var resource : Resource = storage.resource;
  var properties : Properties = new Properties();
  properties.put("screenX", "{noteX}");
  properties.put("screenY", "{noteY}");
  properties.put("text", text);
  properties.put("width", "{noteWidth}");
  properties.put("height", "{noteHeight}");
  var outputStream : OutputStream;
  try {
    outputStream = resource.openOutputStream(true);
    properties.store(outputStream);
  } catch (ioe:IOException) {
    println("IOException saving data:{ioe}");
  } finally {
    try {
      outputStream.close();
    } catch (ioe: IOException) {
      println("IOException closing output stream:{ioe}");
    }
  }
  saveInProgress = false;
  dirtyModel = false;
}

One thing to note is the usage of brackets inside the quotes when storing in the Properties object.  Anything within brackets in a String will be evaluated.  I used this method b/c it is a little cleaner than using toString().

Binding

The most powerful feature of JavaFX is the ability to bind variables and setup triggers.  In this example, we use triggers to monitor whether the model is dirty or not.

   // model variables
   var noteWidth: Float = minWidth on replace { dirtyModel = true };
   var noteHeight: Float = minHeight on replace { dirtyModel = true };
   var noteX: Float = 100 on replace { dirtyModel = true };
   var noteY: Float = 100 on replace { dirtyModel = true };
   var text = "Click here to write notes" on replace { dirtyModel = true };

You could access the old value if you would like by using the following form:

var noteWidth: Float = minWidth on replace oldValue { dirtyModel = true; }

I have also used binding so that components are resized according to the noteWidth variable.  That way all we have to do is set the noteWidth variable and everything will adjust itself accordingly. 

The following example is the code for a rectangle that sits in the lower right corner and handles the resizing of the note.  It demonstrates binding as well as updating of the global variable ‘noteWidth’.

  // resize box
  Rectangle {
    width: 12
    height: 12
    x: bind noteWidth - 12 - dropShadowRadius
    y: bind noteHeight - 12 - dropShadowRadius
    fill: Color.TRANSPARENT
    cursor: Cursor.SE_RESIZE
    onMouseDragged: function(e : MouseEvent) {

      if( e.sceneX < minWidth ) { noteWidth = minWidth; }
      else noteWidth = e.sceneX;

      if( e.sceneY < minHeight ) { noteHeight = minHeight; }
      else noteHeight = e.sceneY;

      setTextboxSize();
    }
  }

Note: I have read that bind operators are less performant than using on replace triggers for similar functionality.  I plan to investigate this in the near future.

Graphics & Effects using JavaFX

Effects are easy to achieve in JavaFX.  In this program I used a gradient for the background as well as a drop shadow.

JavaFX Background Gradient using LinearGradient:

   LinearGradient {
     startX: 0.0, startY: 0.0, endX: 0.0, endY: 1.0
     stops: [ Stop { offset: 0.0 color: noteColorTop },
                Stop { offset: 1.0 color: noteColorBottom } ]
   }

Positional variables must be between 0 and 1 unless proportional is set to false.  In which case, the values are absolute.

JavaFX Drop Shadow using DropShadow:

   DropShadow {
     radius: dropShadowRadius
     offsetY: 3
     color: Color.color(0.4, 0.4, 0.4)
   }

I am aware of the dragging issues experienced when dragging up and down.  However, I am unable to resolve them (not having much experience in desktop app development).  Let me know if you figure out a way to fix it.

 

You can download the source code here, or run Sticky Note.

 

More JavaFX Resources:

 

UPDATE (1/16/2010):

This project is now hosted at github at http://github.com/webdevwilson/javafx-sticky-notes

Bookmark and Share

Tags: ,

4 Comments

Spring MVC Gotcha: Passing Response into Controller Method

I have a confession to make. I created this blog to not only help people out, or opine about industry topics, but as a personal scratch pad for me to help remember stuff. So with that in mind, I am going to take a personal note of a problem I had been dealing with.

Most of us using Spring MVC are familiar with the following:

   class SomeController {

     @RequestMapping("/action")
     public void action(HttpServletRequest request) {
       // do something
     }
   }

Simple, right? Annotation-mapped controller which will use the RequestMapping annotation to determine the viewName. Confused? Check this out. But, what happens when you decide to set a cookie in the action method? For this we will need access to the HttpServletResponse object. No problem, since Spring will automagically inject it into our method.

Observe the following:

   class SomeController {

     @RequestMapping("/action")
     public void action(HttpServletRequest request, HttpServletResponse response) {
       // add cookie using response.setCookie(Cookie) method
     }
   }

Looks good to me. Only problem is, it will not work (a small problem). Apparently, the Spring Framework assumes you are handling the response if it passes it into a method with a return type of void. This is because there is no good way for it to know if you did or didn’t.

No big deal, we can use a string to prevent this behavior:

   class SomeController {

     @RequestMapping("/action")
     public String action(HttpServletRequest request, HttpServletResponse response) {
       // add cookie using response.setCookie(Cookie) method
       return "action";
     }
   }

This will fix the problem. Consult the documentation here for more information.

Bookmark and Share

Tags: , , ,

4 Comments

An easier way to clear your floats with CSS

If you are doing a lot of CSS-based layouts, it is likely that you have done the following:

some text

This never really sit well with me.  Recently, I decided to try and find a better way to accomplish this with a CSS class.  In so doing I came across this post.  If you want to know a bunch of stuff about why this trick works I suggest you read the post.  I will summarize by saying that this trick uses the :after CSS pseudo-selector which is not currently recognized by IE.  But, conveniently we can make ie execute the behavior by assigning a ‘zoom’ to it.  A css attribute that is ignored by other browsers but makes IE render it differently.  Hear is the css code.

.clearme { zoom: 1; }
.clearme:after { content: "."; display: block; height: 0; clear: both; visibility: hidden }

Then, you assign an element to be cleared by adding the ‘clearme’ class.

some text

And everything following will clear the floating div.  I have verified this works in IE 6, IE 7, IE 8, Chrome, Firefox, and Safari (mac).

Bookmark and Share

Tags: ,

1 Comment

Disable Select Options in Internet Explorer 7 with JQuery

I recently found out (unfortunately) that disabling an option with the disabled attribute does not work in IE 7.  Odd.  Here is my workaround using JQuery, it will gray out and disallow selection of all options with a disabled attribute.

   $(document).ready(function() {
     $('option[disabled]').css({'color': '#cccccc'});
     $('select').change(function() {
       if(this.options[this.selectedIndex].disabled) {
         if(this.options.length == 0) {
           this.selectedIndex = -1;
         } else {
           this.selectedIndex--;
         }
         $(this).trigger('change');
       }
     });
     $('select').each(function(it) {
       if(this.options[this.selectedIndex].disabled)
         this.onchange();
     });
   });
Bookmark and Share

Tags: , , ,

4 Comments

Increment count in MySQL with single query

Sometimes I come across a time saver so useful that I feel compelled to share it.

Supposing we are keeping track of stats on our website in a MySQL database with a table of
columns url, month, hits.  To update the hit count we can do this:

UPDATE `stats` SET `hits` = `hits` + 1 WHERE `url` = '/tips.htm' AND `month` = '6'

Now, this would work as long as we are assured the record exists.  But, we can’t be sure it exists.

So we have to do the following:

   $results = query( "SELECT hits FROM `stats` WHERE url = '/tips.htm' AND month = '6'" );
   if( $results->count() == 0 ) {
     // do insert
     query("INSERT INTO `stats`( `url`, `month`, `hits` ) VALUES ( '/tips.htm', '6', 0 )"); 

   } else { 

     // do update
     query("UPDATE `stats` SET `hits` = `hits` + 1 WHERE `url` = '/tips.htm' AND `month` = '6'");
   }

However, this can be done in one query so long as url and month are setup as composite keys, and

hits must default to 1.  With a little setup the next query accomplishes everything in one fail swoop:

query("INSERT INTO `stats`( `url`, `month` ) VALUES ( '/tips.htm', '6' ) ON DUPLICATE KEY UPDATE `hits` = `hits` + 1");

Now do something productive with all the time you saved.  Keep in mind that this syntax is valid in MySQL 4.1.0 and later.

Bookmark and Share

Tags: ,

2 Comments

Gracefully degrading AJAX calls

What happens if grandma fires up her Packard Bell and attempts to buy some medicinal ointment from your site in IE 5?  Or, what if one of your 3rd party advertisers (likely story) causes a javascript error?  Will your page still work?  Have you ever thought of what happens when javascript is not running on your fancy AJAX pages?

Not many of us do.  But, it is still important to think about what will happen if javascript is not running in the user’s browser.  Around 5% of user’s have javascript completely turned off.  Still other’s may have security settings which disallow ajax calls or obsolete browser’s which are not supported.  Degrading your javascript gracefully can be tedious and time consuming.   However, if you follow the pattern that I present it is hardly an inconvenience at all.

Consider the following code:


Pretty simple.  We can see that when the link is clicked an ajax call is made.  The click event returns false, preventing the browser from navigating to the href location.  If Javascript is not running the browser will just navigate to the ‘/book/details’ page.

The next part is where most people might get lost.  But, if you are using a modern MVC framework (why wouldn’t you be?), then you should be fine.  Or, at the very least, you should be implementing the view decorator pattern in some form.

Basically, your controller (or page) should be able to detect whether or not the request was made via AJAX, the XMLHttpRequest object.  Most javascript libraries make this easy by adding a special request header, ‘X-Requested-With’.  If your library does not do this, you should be able to manually add the header.  By checking this header, you can easily determine whether it is AJAX you are dealing with.

In PHP:


     function isAjax() {
       return $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
     }

     $book = Book->find($id);

     if( !isAjax() ) {
       include('includes/header.inc');
     }

   echo "

${book[title]

${book[description]}
"; if( !isAjax() ) { include('includes/footer.inc'); }

That is pretty straightforward, but the great thing is that most MVC frameworks will do it automatically!  But, what if we want to automatically create our links.  This is easy with the jquery library.  We will create a method that will run when the page loads, and add automatically add the functionality to our links (designated with the ajaxme class).

   

Keep in mind there are many situations where it is not possible to gracefully degrade an application.  In these cases a <noscript> tag should be used to warn the user that they are missing out on additional functionality.

Bookmark and Share

Tags: , , , ,

No Comments

Column Priority SQL Server Fulltext Search


I originally posted this on allthingswilson.com almost 2 years ago. However, I find it to be very helpful so I am reposting it here. I realize that I am not blazing any new trails here, but hopefully someone will find this useful.

A client of our’s recently approached us with a simple request, to create a business search which would search keywords on the business’ name and description in our SQL Server database. This was simple enough to achieve, by creating a FULLTEXT index on the table with the appropriate fields ( title, description ) and executing the following query:

   SELECT Members.*, SEARCH_TBL.RANK AS rank
     FROM   Members INNER JOIN
           FREETEXTTABLE(Members, *, ‘breakfast’) SEARCH_TBL
               ON Members.memberID = SEARCH_TBL.[KEY]
    ORDER BY rank DESC

Which yields the following results for the keyword ‘breakfast’:

id name description rank
23 Holiday Inn – Downtown <Long Text> 276
71 IHOP <Long Text> 220
2 Days Inn – North <Long Text> 155
43 Best Breakfast Buffet in Town <Long Text> 146

As we can see, these results are unsatisfactory as two businesses appear above ones that should be first. This is due to the fact that these hotels keyword-loaded their description by boasting about their, no doubt, wonderful continental breakfast. Well, we have been there and we have been to the BBBIT and IHOP, and we realize that it is not even a contest as to which one is better. So we would like for the genuine greasy spoon breakfast joints to appear ‘ranked’ above the giant monster mega hotel chains.

Unfortunately, SQL Server has no native way of ‘prioritizing’ columns in a FULLTEXT search clause, that I know of (unlike Karl Hungus, I am not an expert). However, this needed to be done, and I did not want to go messing with the code, so I set about trying to come up with a way to do it in my stored procedure. I suck at T-SQL, but I am pretty good at joining tables, it’s simpler for my simple mind.

Here is the new query:

   SELECT Members.*,
           NAME_SRCH.RANK AS rank1, SRCH.RANK AS rank2
    FROM   Members LEFT OUTER JOIN
      FREETEXTTABLE(Members, name, ‘breakfast’) NAME_SRCH ON
        Members.memberID = NAME_SRCH.[KEY] LEFT OUTER JOIN
      FREETEXTTABLE(Members, *, ‘breakfast’) SRCH ON
        Members.memberID = SRCH.[KEY]
   ORDER BY rank1 DESC, rank2 DESC

This query yielded the following result set:

id name description rank1 rank2
43 Best Breakfast Buffet in Town <Long Text> 265 146
2 Cozy Bed & Breakfast <Long Text> 265 120
23 Holiday Inn – Downtown <Long Text> <NULL> 276
71 IHOP <Long Text> <NULL> 220

Now you see we have much better results, the Holiday Inn hung in there but we also introduced a new business, Cozy Bed & Breakfast, which I think we can agree is a desirable result for a breakfast search. IHOP still came in after the hotel, because they do not have breakfast in their name. But alas, as we all know by now, outside of Google, no search is perfect.

Bookmark and Share

Tags: ,

7 Comments