Wednesday, December 29, 2010

jQuery Selector Filtering With Regular Expressions

jQuery ships with a whole host of extremely useful selector expressions that allow you to pick, choose, and otherwise narrow down exactly the items on the page that you want to manipulate with your jQuery scripts. It does not, however, ship with an obvious way to perform regular expressions using the selector syntax. Instead, one way I've found to do this is by using the library's filter() method. You simply pass a function as an argument and then use your own predicate to perform the filtering within the passed function. A short example scenario follows.

Let's say you have some items on the page that you'd like to manipulate by using a server-side property name. You might do this for some AJAX error handling, for instance. Get a response from the server containing the fields in error and add an appropriate message next to the corresponding input field.

Client-side field IDs
rates[1]_MyRateThing
Name
FirstName
LastName

So let's say "Name" had an error because the user didn't supply one. With jQuery the selector would be pretty straightforward, and there's no need for any regex in this case. This is assuming we already have the AJAX response and are iterating over the error values in a loop, each error being represented by an "item" object with PropertyName and ErrorMessage properties.

if ($(item.PropertyName + ':visible').length > 0) {
    errors++;
    $(item.PropertyName + ':visible').after('<span class="error"> *' + item.ErrorMessage + '</span>');
}

This works equally fine for FirstName and LastName as well. But what about MyRateThing? You'll notice there's a prefix on that property, the reason being MyRateThing is part of a list of items to be sent to the server. Without going off on a tangent, this is how .NET MVC happens to handle lists of things for easy manipulation server-side and the prefix is both simple and necessary. So how can we generalize our matching algorithm to fit both simple property names as well as those with more compound structures like the list prefixes? We could try using the jQuery "ends with" selector as follows:

$('[id$="' + item.PropertyName + '"]:visible')

This solves our problem for MyRateThing fairly easily. Only the visible elements ending with the specified property name are selected with this approach because it simply matches on an element whose name ends with the PropertyName value. The only problem is that now our other properties don't work as expected. Let's say we have an error with Name. Unfortunately, now both FirstName and LastName will be matched as well. We need slightly finer grained control over the pieces of our string in order to tell jQuery to filter out elements in some cases, but not in others. This is where our regex will come in. Basically, when our selection method is looking at element ID's with an underscore character "_" we want it to ignore everything leading up to, and including, the underscore. When there is no underscore character, we want the selector to look at the entire id. We'll simply add our regex onto the select class filter from our previous example. So here it is:

var matchedElem = $('[id$="' + item.PropertyName + '"]:visible').filter(function() {
    var regex = new RegExp('^(.*_)?' + item.PropertyName + '$');
    return this.name.match(regex);
});

if (matchedElem.length > 0) {
    errors++;
    matchedElem.after('<span class="error"> *' + item.ErrorMessage + '</span>');
}

Mike

References:

Friday, December 24, 2010

Export HTML List of Links With Bash/Unix/Cygwin

Why use an IDE when you can have fun with the Shell??? This little tidbit will rip through the files in the current directory and redirect the output with hyperlink wrappers to a file named links.html.

for file in *;
do
echo "<li><a href=\"$file\">$file</a></li>" >> links.html;
done

Thursday, December 23, 2010

Extracting File Names From Full Paths Using Regex

There are tons of ways to do this, and this is pretty introductory, but I felt like posting it anyway. I wanted a quick, repeatable way to print out a list of just file names, excluding the path, from a Subversion changeset. Here it is:

Unix-style
svn status mydir | grep -o '[^\/]*$'

Windows
svn status mydir | grep -o '[^\\]*$'

Wednesday, November 3, 2010

PlayStation 3 Video Problem - Fixed!

I Twittered (prematurely) not long ago about my PlayStation 3 having miraculously recovered from a video flicker and horizontal scanline problem. I thought it might have been an overheating issue or a bad solder connection on the video card and was getting ready to send it into Sony to have it repaired/replaced. Little did I realize what the real root of the problem was.


In actuality, I was the victim of a phenomenon known as a ground loop. First, I should mention that I am using the RCA connection for video as opposed to the HDMI cable (no HDTV), so if you have this problem with HDMI it might be something else entirely. In my configuration a ground loop was absolutely the issue. Often enough, electronic equipment is connected using only a two-pronged plug, not the three-pronged variety. Electrical devices connected to power in this fashion are known as a floating ground. This is normally not an issue, but in a system where devices are connected via cables and not all the devices in the system are connected as floating grounds, this can become a problem. Why? Well I'm not a certified electrician and you can certainly read a bit more about it on Wikipedia if you like, but it comes down to a difference in ground potential between the connected devices.

Electricity, in a nutshell, works on the principal of two points in a circuit having a difference in potential. You can think of it like water flowing from a point on top of a mountain down to the sea. The effect of gravity in concert with the difference in elevation is essentially the same principal as that of electrical potential. The water wants to flow from the point of high elevation (high potential) to the point of low elevation (low potential). Without a difference in gravity potential there is no reason for the water to move from point A to point B. And likewise, without a difference in electrical potential there is no reason for electrons to create electricity by moving through a conductor. Not having a common ground within a system of connected electrical devices causes this difference in potential and voila! instant video problems because we end up having a flow of electrical current where there should not be a current.

I was honestly surprised to see this happen, and it took a good deal of grief before I realized what it was. In the case of the PS3, Sony decided to use a three-pronged (grounded) plug similar to what is used for most computers. I'm not sure what the reason behind that decision was, but I really don't see a whole lot of danger there because the case is enclosed by plastic and would buffer you from shock in the event of a short anyhow. That aside, this is the first part of how we get a ground loop. The other part comes from your television, but not your television's power connection. Rather, it comes from your cable line connection! Yes, your cable line into the back of the television, if not properly isolated, can cause a ground loop in concert with a fully grounded piece of equipment connected to your television.

In my case, having the PS3 plugged into a grounded outlet, that is to say the PS3 is not a floating ground, along with having it connected via RCA cables to a television connected to a non-isolated cable line, caused a ground loop. Since I'm using online media exclusively now, all I had to do was unplug the cable line and I was all set. If you have cable and need the connection, you could: verify your cable box is has an isolating transformer to shield from ground loops, unground your PS3, or add a special filter to your cable line to protect it from ground loops in the way a cable box would normally do.

~Mike

Friday, October 29, 2010

Back to the Klipsch ProMedia Volume Problem

I posted a blog a number of months ago about having some issues with the volume control knob on my Klipsch ProMedia speakers. I tried some basic fixes using a light oil, which seemed to work pretty well at first, but the speakers later reverted to their original behavior. I really like the sound on these speakers, but it seems Klipsch has little, if any interest in addressing the known issues - they have even stopped producing this set of speakers altogether. Actually, this isn't the first product from Klipsch I've had problems with, but that's a whole other story.

I'd really like to get these things working again so I've taken the first steps towards that goal by disassembling the volume control from the rest of the internal electronics. I desoldered the volume pot switch from the internal PCB, but now have to figure out where to find a replacement. I found at least one posting from someone that detailed pulling the casing on the switch apart and soldering new wire connects along with a series of other steps, but I just don't care to do that. What I'd really like is to find another pot that matches the one in the photo below. We'll see where this goes.

Thursday, October 28, 2010

Dell Vostro 1500 - DVD-RW Replacement

The DVD drive on my laptop took a dive the other day, so being well out of warranty I decided to replace it myself. Even on the Dell website doing a search for parts for the Vostro 1500 wasn't very fruitful. I'm not really sure why they don't have the appropriate parts for this computer, but there's not much I can do about that. I ended up finding a new drive made for an Inspiron 1520 on Ebay for a reasonable enough price. I have no idea how compatibility works for these things, but I had come across a posting on the Dell forums that indicated the Inspiron and Vostro were virtually the same machine. On that advice, I purchased the drive.

Replacement was really pretty easy. Shut down your comp, remove the mounting screw for the drive on the bottom of the computer, and slide the drive out. Due to a funky configuration, you might have to remove the faceplate from the old drive and use it instead of what comes with your replacement drive. There are a couple plastic snaps that you can work loose with a screwdriver, but attaching the plate to the new drive is as simple as snapping it into place. From that point it's just inserting the new drive into the DVD drive bay and tightening the mounting screw.

Really, that's about it! For a quick test I played a CD and it worked without any hassles whatsoever. I did notice that similar to my old drive, the player vibrates quite loudly while ripping a CD. Seems like there may have been a missing part to control vibration on my laptop? I say this because another programmer friend of mine bought the exact same laptop at the same time I did, and not once did it have issues. I'm not really sure, but at least the thing works again.

Here's the old drive after removal.
Old hunk o' junk

~M

Friday, September 17, 2010

If At First You Don't Succeed, Make Sure You Added the DOCTYPE

I just thought of something that can be ridiculously aggravating.

Picture this: You're working along, making good progress structuring your HTML with beautiful DIV, UL, P elements, among other SEO-friendly markup. The CSS is nicely organized and as cross-browser safe as you can possibly make it. You're developing in Firefox or Chrome and everything looks fantastic, but you figure it's a good idea to check out IE since, while good developers know the tools on other browsers are vastly superior, this is largely still the public's browser of choice. And in order for any site to be successful you have to develop to the lowest common denominator, right? But wait, what's this!? IE just barfed all over your perfect markup, exclaiming "You don't know what you're doing, kid. Nice try!" Well, rather than throwing your computer out the window or starting from scratch, you might double-check that you didn't forget to include the DOCTYPE element at the top of your page. Forgetting to specify the document type can be the cause of some of the most annoying rendering bugs, so it pays to check.

Mike

Tuesday, September 14, 2010

Yet Another Syntax Highlighter For the Web and Blogs

Today I was looking at the ol' tech blog thinking that while my current code syntax rendering is okay, it's not great. There must be something better. So I poked around the web for a bit looking, at a few other prominent technical blogs, and I came across an excellent JavaScript-based syntax highlighter appropriately named, well, SyntaxHighlighter. I know, sometimes fancy marketing names just don't make the to-do list.

The library is configurable on a number of fronts. Probably the most important feature is the ability to add what the creator calls brushes. These are essentially code files specifically tuned to the particular language's syntax you're looking to highlight. For instance, there are SQL, JavaScript, Java, and C# brushes, among others. Another nice add is the ability to tune the overall formatting via a CSS theme. This allows you to tweak the colors to various display types including but not limited to Eclipse and Emacs. Pretty nice indeed. Lastly, you don't even need to host the requisite files. The creator, Alex Gorbatchev, provides free hosting - all he asks is for a donation to help with the Amazon S3 costs.

Configuration

Configuration is also pretty much a breeze. If you're modifying an existing blog template on Blogger, as was the case for this site, you'll probably want to do a backup of your existing template. Login to your account and navigate to the Design tab. From here you'll be looking for the sub-menu option entitle Edit HTML. Backup your template via the supplied download link. That being done, search for "" in the template document in the textarea below. Just above the closing "" element is where you're going to insert the following code.

<!-- Syntax Highlighter code -->

<!-- SH::Setup CSS -->
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeEclipse.css' rel='stylesheet' type='text/css'/>

<!-- SH::Setup JS -->
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shAutoloader.js' type='text/javascript'/>

<!-- SH::Configure Brushes -->
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>

<!-- SH::Run syntax highlighter -->
<script type='text/javascript'>
     SyntaxHighlighter.config.bloggerMode = true;
     SyntaxHighlighter.all();
</script>

There are four main sections here:
  1. CSS
  2. JavaScript core files
  3. Syntax brushes
  4. Config and run highlighter

If you're running this in Blogger, you should include the line config.bloggerMode=true, as per the documentation. You'll notice I've included a number of brushes. There is also an autoloader feature that sounds like it should offload some downloading on pages that don't require all the brush files, but I haven't tried it out yet. The last thing to do is use the highlighter in a blog post. It really doesn't get much more complicated than the following:

<pre class="brush:js">
function testMeOut()
{
    alert("You should really try this out.");
}
</pre>

In this example I've decided to highlight a simple JavaScript function by specifying a brush type of "js" in my outer "<pre>" class definition.  One important thing to note is that there are actually two different ways to go about highlighting with this library. I've used the "<pre>" tag method, as this is the recommended method for blogs, but it requires you to HTML escape your code. It's a minor inconvenience, but still important to note because the syntax highlighting will not work if you have less-than "<" symbols in the code you are trying to highlight.

That should do it. If you're not seeing the correct results, make sure you've included all necessary files, referenced your brush types correctly, and escaped your HTML.

Links

Thursday, September 9, 2010

Dropping Multiple Stored Procedures

Occasionally when you're working with a database, e.g. your local dev environment, you need to do a little bit of cleanup. Let's say you run a stored procedure creation script from with SQL Server Management Studio and forget to specify the target database. So instead of having a bunch of procedures in the intended database you now have them in another database or, perhaps worse, in your master database.

SSMS doesn't allow you to select multiple procs to run commands on at once, so you have to select them one-by-one and issue the drop. I don't know about you, but there's no way I want to do that for ten, let alone fifty or more stored procedures. A better way to approach this is to instead write a batch processing script that loops over a list of stored procedure names and executes the DROP command on each of them.

The trick here is to get a list of user-defined stored procedures that fall under the desired catalog (database) and loop over that list with a cursor. The reason for this is that unlike a WHERE clause you can't pass a list to the DROP PROCEDURE command. To accomplish a batch DROP, you have to store the resulting value from the current row retrieved from the cursor and execute the command on each value inside a loop. The complete code is shown below.

* Please be advised this code is provided as is with no warranties of any kind. Don't run this on a production environment if you're not absolutely certain as to how it will affect your database system.

--
-- DROP USER-DEFINED STORED PROCEDURES
--

USE MASTER; -- Change to desired database
GO
SET NOCOUNT ON;

PRINT '---- STARTING ----';

DECLARE @UserStoredProcedureName    VARCHAR(200),
        @Command                    VARCHAR(200);

PRINT '---- Creating Cursor... ----';

DECLARE SPCursor CURSOR SCROLL STATIC READ_ONLY FOR
SELECT SPECIFIC_NAME 
  FROM INFORMATION_SCHEMA.ROUTINES
 WHERE SPECIFIC_CATALOG = 'master' -- Change to desired database
   AND SPECIFIC_NAME IN 
   -- This inner select is likely redundant, but I'm not clear on all the 
   -- differences between sys.objects and INFORMATION_SCHEMA
 (
    SELECT name FROM sys.objects
     WHERE type='P'
       AND is_ms_shipped = 0 
       -- A value of 0 represents user-defined procs
       -- Please note, some diagram utility stored procs don't follow this rule
 );

PRINT '---- ...Finished Creating Cursor ----'

PRINT '---- Opening Cursor... ----';

OPEN SPCursor;

PRINT '---- ...Finished Opening Cursor ----';

PRINT '---- Retrieving First Rec... ----';

FETCH NEXT FROM SPCursor
INTO @UserStoredProcedureName;

PRINT '---- ...Finished Retrieving First Rec ----';

PRINT '---- Starting Command Loop... ----';

WHILE(@@FETCH_STATUS = 0)
BEGIN

    -- Include a schema name as a prefix, if necessary
    SET @Command = 'DROP PROCEDURE dbo.' + @UserStoredProcedureName;
    
    PRINT '----     executing:: ' + @Command;
    
    --SELECT @Command
    
    --***Only uncomment the line below if you're sure the correct procs will be affected***
    --EXEC(@Command)
    
    FETCH NEXT FROM SPCursor
    INTO @UserStoredProcedureName;
    
END;

PRINT '---- ...Finished Command Loop ----';

PRINT '---- Closing Cursor... ----';

CLOSE SPCursor;

PRINT '---- ...Done Closing Cursor ----';

PRINT '---- Deallocating Cursor... ----';

DEALLOCATE SPCursor;

PRINT '---- ...Done Closing Cursor ----';

PRINT '---- FINISHED ----';

SET NOCOUNT OFF;

Monday, June 28, 2010

Klipsch ProMedia Ultra 2.0 Pot Fix

One of my favorite audio companies for years now has been Klipsch. They've offered unparalleled THX certified sound for the computer audio enthusiast and as a result I've happily purchased multiple sets of speakers from them. Unfortunately, I've come to find that the volume and bass potentiometers (a.k.a. pots or rheostats) on the ProMedia Ultra 2.0 series are faulty. I put up with the irritations that go along with the knob adjustment crackling and popping sounds for a while, but finally had to do something about the issue when the sound started to cut out altogether.

I concluded there to be a couple options in this case since I'm out of warranty by at least a couple years and Klipsch no longer produces these speakers. I could have certainly attempted to switch out the pots with new, perhaps higher quality ones but this option didn't thrill me all that much because it's invasive, time consuming, and a last ditch effort in the event there are no other options. Fortunately, I was able to find evidence that people were successfully fixing the pots by opening up the speaker enclosure, spraying compressed air onto the pot, and subsequently lubricating the knob with a light oil of some variety. This solution seemed a lot better to me so that's what I went ahead and did. Sure enough, the speakers are already performing more reliably than they had been before this fix. However, I must report that as I write this they have already cut out one time and I had to turn the speakers off and on again in order to get the faulty pot to work. We'll see how things go moving forward. Who knows? I may soon find myself writing an article about replacing the potentiometer with a new one...

Mike

Friday, June 4, 2010

Compiling Java From the Command Line - Part 1

Introduction
More often than not Java developers end up using an IDE like Eclipse or Netbeans for writing, compiling, and packaging their projects. There's also a good chance a tool such as Ant or Maven is being leveraged in this environment. These are all great tools for productive development which I actually use myself, but they shield a developer from what's going on under the hood. This is generally a good thing, but for those occasions when something goes wrong or you're having a hard time understanding why class Foo is not being picked up by the compiler, it's good to have an understanding of what magic is really happening underneath all the bells and whistles.

In this article we'll be discussing the ins and outs of the javac compiler and how it's used with the sourcepath and classpath arguments as well as how the compilation process is affected by code packaging schemes. This article assumes you already have java 1.6 installed and properly configured on your machine and that you're using Windows XP. While some of the commands are OS-specific, the lessons are fairly universal so Unix/Linux users shouldn't have much trouble following along as well. By no means will this be an exhaustive discussion, but it should have you well on your way to using the command prompt (or shell) for compiling Java applications.

Javac Me Gently
Let's start with a simple example to get the ball rolling. First, open up a command prompt and get your project structure in order. Here's my sample project structure:
C:\>cd DevProjects\ExampleProject
C:\>tree /F
C:.
├───classes
└───src
        MainClassNoPkg.java

I *strongly* urge you to put your code in a location that has no spaces in the folder names. It's possible to get around this, but the headaches you'll get especially with more complicated projects and tool dependencies make it not worth the hassle.

and the java class, MainClassNoPkg.java, is as follows:
// MainClassNoPkg.java
// Default package

class MainClassNoPkg {
    MainClassNoPkg() {}
    
    public static void main(String[] args) {
        System.out.println("Msg from MainClassNoPkg");
    }
}

For a text editor I've grown quite fond of gvim. It's a Windows port of the popular and ubiquitous Unix editor, Vi, and has many powerful text editing features. I highly recommend learning an editor like this, but it's not something you pick up overnight so feel free to use any plain text editor you like for this tutorial.

The last thing I'd like you to do here is clear out the CLASSPATH environment variable. More on why I'm having you do this later, but for now just go with it and run the following in your command shell:
C:\DevProjects\ExampleProject>set CLASSPATH=

Now let's run javac and see what happens...
C:\DevProjects\ExampleProject>javac -verbose src\MainClassNoPkg.java
[parsing started src\MainClassNoPkg.java]
[parsing completed 31ms]
[search path for source files: .]
[search path for class files: C:\java\jdk1.6.0_18\jre\lib\resources.jar,C:\java\
jdk1.6.0_18\jre\lib\rt.jar,C:\java\jdk1.6.0_18\jre\lib\sunrsasign.jar,C:\java\jd
k1.6.0_18\jre\lib\jsse.jar,C:\java\jdk1.6.0_18\jre\lib\jce.jar,C:\java\jdk1.6.0_
18\jre\lib\charsets.jar,C:\java\jdk1.6.0_18\jre\classes,C:\java\jdk1.6.0_18\jre\
lib\ext\dnsns.jar,C:\java\jdk1.6.0_18\jre\lib\ext\localedata.jar,C:\java\jdk1.6.
0_18\jre\lib\ext\sunjce_provider.jar,C:\java\jdk1.6.0_18\jre\lib\ext\sunmscapi.j
ar,C:\java\jdk1.6.0_18\jre\lib\ext\sunpkcs11.jar,.]
[loading java\lang\Object.class(java\lang:Object.class)]
[loading java\lang\String.class(java\lang:String.class)]
[checking MainClassNoPkg]
[loading java\lang\System.class(java\lang:System.class)]
[loading java\io\PrintStream.class(java\io:PrintStream.class)]
[loading java\io\FilterOutputStream.class(java\io:FilterOutputStream.class)]
[loading java\io\OutputStream.class(java\io:OutputStream.class)]
[wrote src\MainClassNoPkg.class]
[total 297ms]

That might look overwhelming at first, but bear with me and all we'll walk through it. On the first line we're actually executing javac. I've intentionally included the -verbose argument so we can take a look at what's going on under the hood, but normally you can feel free to leave it out. Immediately following you will see the reference to our MainClassNoPkg.java class file we wrote. Everything else that follows is output from the javac compiler.

First, you can see that the compiler picked up our java source file and parsed it. Notice that immediately following the compiler mentions searching paths for source and class files. The default for both sourcepath and classpath is the current directory. In addition, the compiler will add the bootstrap and extension classes that shipped with the javac compiler being used, though you can modify this behavior with the -bootclasspath and -extdirs options if you wish. However, we won't be changing these options in this article. You can see all the bootstrap and ext classes listed in the output for the class file search path. Finally, the output shows the compiler loading the classes MainClassNoPkg references.

For one simple java source file that was pretty painless, right? You could even simplify this further by using wildcards
C:\DevProjects\ExampleProject>javac src\*.java

But we've only compiled one file, you might say. The standard Java tutorial shows me how to do that, there must be more to it than this, right? Indeed, there is. Next we'll discuss compiling multiple source files at once and using the -sourcepath and -classpath options.

Let's Get To the Source

In this section I'm going to cover how the compiler searches for your uncompiled Java source files and turns them into executable bytecode. We're going to add to our example now by creating another class appropriately named AnotherClass with the following contents
// AnotherClass.java
// Default package

class AnotherClass {
    AnotherClass() {}

    public void printMessage(String msg) {
        System.out.println("The message is: " + msg);
    }
}

Next, modify the MainClassNoPkg.java to use the newly created class.
// MainClassNoPkg.java
// Default package

class MainClassNoPkg {
    MainClassNoPkg() {}
    
    public static void main(String[] args) {
        System.out.println("Msg from MainClassNoPkg");
        AnotherClass lAnother = new AnotherClass();
        lAnother.printMessage("Hello Java developers!");
    }
}

Your source tree should look as follows, assuming you've cleaned up the previously created .class file.
C:\DevProjects\ExampleProject>tree /F
Folder PATH listing
Volume serial number is
C:.
├───classes
└───src
        AnotherClass.java
        MainClassNoPkg.java

Now run javac as we did before, specifying the main class name. Don't use the wildcard character this time.
C:\DevProjects\ExampleProject>javac src\MainClassNoPkg.java
src\MainClassNoPkg.java:8: cannot find symbol
symbol  : class AnotherClass
location: class MainClassNoPkg
        AnotherClass lAnother = new AnotherClass();
        ^
src\MainClassNoPkg.java:8: cannot find symbol
symbol  : class AnotherClass
location: class MainClassNoPkg
        AnotherClass lAnother = new AnotherClass();
                                    ^
2 errors

Uh-oh what happened!? That is most definitely NOT what we want to happen, but no worries as this was just a way to make a point about how the javac compiler finds the classes it needs during compilation. Remember when we cleared out the CLASSPATH environment variable? By doing so we instructed javac to default it's classpath to the current directory (normally denoted by a period). The compiler also takes a -sourcepath argument and when we don't specify this the default is also the current directory.

The point to make here is that while we specified a java file to compile in the src directory, the compiler couldn't find the referenced AnotherClass.java file. Why, you might ask? But isn't the compiler smart enough to grab other files in the same directory as the source file we instructed it to compile? Well, no actually. The Java compiler does not really do any searching based on the source files (and their paths) you pass as arguments to javac. If you want javac to find AnotherClass.java you have to handle it like this:
C:\DevProjects\ExampleProject>javac -sourcepath src src\MainClassNoPkg.java

or this
C:\DevProjects\ExampleProject>javac -cp src src\MainClassNoPkg.java

or this
C:\DevProjects\ExampleProject>cd src
C:\DevProjects\ExampleProject\src>javac MainClassNoPkg.java

In the first two examples we specified a location for the compiler to find other ancillary classes by passing the src directory as the -sourcepath or -cp (same as -classpath) options. In the third example we cd'ed into the src directory and executed the javac command. Specifying a sourcepath or classpath was unnecessary because remember that the compiler uses the current directory as the default when those options aren't specified. If you need to pass more than one directory, simply separate them with a semicolon (;), no spaces. Also note that we could have set the CLASSPATH environment variable instead of using the command line arguments. This is particularly well-suited for long path definitions or for occasions when you'll need to run the javac command more than once.

A more complete order of operations for searching for source files is as follows and additional details can be found in the javac documentation listed in the references at the end of this article.
  1. paths listed via the -sourcepath option are searched
  2. -cp or -classpath arguments are searched
  3. The CLASSPATH environment variable is searched
  4. The current directory
OK, now assuming you've successfully run one of the examples above, the compiler should spit out a couple .class files and you should be able to run your program without any errors as follows:
C:\DevProjects\ExampleProject>java -cp src MainClassNoPkg
Msg from MainClassNoPkg
The message is: Hello Java developers!

The point in this section's example is to show that you must include the relative or absolute path in your source file list and you must include at least one reference to a source file, whether by wildcard or explicit declaration, regardless of what you include as arguments to -cp and -sourcepath. The following, while seemingly clever enough and seemingly within javac's rules, just simply will not work!
C:\DevProjects\ExampleProject>javac -sourcepath src *.java
javac: file not found: *.java
Usage: javac <options> <source files>
use -help for a list of possible options

C:\DevProjects\ExampleProject>javac -sourcepath src MainClassNoPkg.java
javac: file not found: MainClassNoPkg.java
Usage: javac <options> <source files>
use -help for a list of possible options

Furthermore, the compiler will oblige you to grab source files referenced by any source files you are compiling, but only if it can find them on the source or class paths. There is simply no way to instruct javac to search recursively for a source or class file. This comes into play when we deal with packages, but we'll discuss this further in the next section. Now onto our next lesson, compiling using references to source that's already been compiled.

Javac and Source Files Vs. Class Files and JARs - What the Diff?

We've already compiled a number of example projects so now let's expand on this code to illustrate another point - how javac treats java source files differently from previously-compiled class files (java bytecode in a file with a .class extension).

Imagine you've been coding a project for a while now and have numerous source files distributed across multiple packages (we'll cover this later) and projects and are using a couple external libraries. Obviously, there are times that we might not want to compile every last bit of code in our project, but more importantly there are times when this might not be feasible. Think of the situation where you've purchased a jar file from an external company and all you've received is compiled java bytecode. In other words, you don't have the source code because it's proprietary. But you still want to use the wonderful API/library that, perhaps ClevelandFlash, has developed for you. Will ClevelandFlash let it be so? Can this be done? Of course it can! Otherwise we wouldn't be here and instead developers would be off using some other language for its code reuse facilities. Even if you have access to the source code, which is par for the course for open source projects (thus the term "open source!"), you don't want to be compiling them from source unless absolutely necessary. Leveraging previously compiled code is in fact pretty simple to do, but first let's modify our code so that it's not using the yucky default package anymore.

Hopefully you're familiar with Java packages as I'm not going to go into the details here, but if not no worries as you should still be able to run the examples. I do, however highly recommend your taking the time to check out the Java Tutorials basic package explanation and package trail at your earliest convenience. Okay, onto the examples now. First, let's move our java source files to their new package locations and rename MainClassNoPkg to MainClass. I'm going to be using com.clevelandflash as my root package name to stick with convention, but you're free to use your own values here if you wish. Just be sure to adjust the source code and command prompt commands accordingly to reflect these changes!

My tree now looks like the following
C:\DevProjects\ExampleProject>tree /F
Folder PATH listing
Volume serial number is
C:.
├───classes
└───src
    └───com
        └───clevelandflash
            └───javac_tut
                ├───core
                │       MainClass.java
                │
                └───helper
                        AnotherClass.java

And here are the updated source files:
// MainClass.java
// No longer the default package
package com.clevelandflash.javac_tut.core;

import com.clevelandflash.javac_tut.helper.AnotherClass;

class MainClass {
    MainClass() {}
    
    public static void main(String[] args) {
        System.out.println("Msg from MainClass");
        AnotherClass lAnother = new AnotherClass();
        lAnother.printMessage("Hello Java developers!");
    }
}

// AnotherClass.java
// No longer the default package
package com.clevelandflash.javac_tut.helper;

public class AnotherClass {
    public AnotherClass() {}

    public void printMessage(String msg) {
        System.out.println("The message is: " + msg);
    }
}


Now, run the following command
C:\DevProjects\ExampleProject>javac -d classes -sourcepath src src\com\cleveland
flash\javac_tut\core\MainClass.java

Here we've used the -d option with a value of classes to instruct the Java compiler to output the .class files to the classes directory rather than alongside the .java source files, as is the default. The compiler does something additionally useful in that it automatically generates the package folder structure in the output directory. Cool!
C:\DevProjects\ExampleProject>tree /F
Folder PATH listing
Volume serial number is
C:.
├───classes
│   └───com
│       └───clevelandflash
│           └───javac_tut
│               ├───core
│               │       MainClass.class
│               │
│               └───helper
│                       AnotherClass.class
│
└───src
    └───com
        └───clevelandflash
            └───javac_tut
                ├───core
                │       MainClass.java
                │
                └───helper
                        AnotherClass.java

This is really good considering the Java language requires you to match the folder structure to your package names. One small exception, though not considered a best practice, would be if you had a source file in the core directory but left it declared as part of the default package. Javac would compile it just fine, but when it writes out the .class file it would put it in .\classes instead of in .\classes\com\clevelandflash\javac_tut\core. Another important thing to note is that unless you use the *.java wildcard on a each directory or enumerate each file that needs compiling, the compiler will NOT pick up non-referenced source files. So for instance, if you had a file IO helper class (just thinking of something random here) in the helper directory that was atomic from the rest of the code, you'd have to be sure and include it in your javac command explicitly, otherwise it won't get compiled. The compiler only picks up necessary references (i.e. import statements in code) or files you explicitly declared in the source files list when calling javac. Make sense so far? Good! Let's just run our sample real quick to make sure everything works with our new package structure.
C:\DevProjects\ExampleProject>java -cp classes com.clevelandflash.javac_tut.core
.MainClass
Msg from MainClass
The message is: Hello Java developers!

Looks good, but I do want to draw attention to the fact that you need to specify two things when running the program so that the JVM can find your program. First, you must specify the classpath to include the classes directory, and second, call the class that contains the main method (MainClass) by its full qualified name. If you went through the packages trail on the Java tuts site (if you didn't, now's a great time) you would immediately notice this is done simply by appending the class's package name as a prefix to the class name. If you've made it this far, you're well on your way to understanding Java compilation and classpaths from the command line. Thanks for reading!

But You Didn't Cover JAR and External Class Files Yet!@#%

The last section was just getting so long and it seemed only appropriate to wrap it up. Alright, on with the show as promised. In this final section we'll be compiling source code against some external libraries as well as some previously compiled code that we wrote ourselves. First thing's first, we need to setup another project directory and download a good library to use for our code examples.

Modify your folder setup so that you now have another project named LibProject at the same level as ExamplProject. Mine looks like this:
C:\DevProjects\LibProject>tree /F
Folder PATH listing
Volume serial number is
C:.
├───classes
├───lib
├───resources
└───src
    └───com
        └───clevelandflash
            └───goodtimes
                ├───core
                │       ClassForXerces.java
                │
                └───model
                        Company.java

Go ahead and also create the additional subdirectories and files as I have shown above. We'll work out the source code for the two java files shortly but first we need to find a library.

Just for fun, let's go with the Xerces XML parser. XML parsing, while potentially memory intensive, is a very popular and necessary activity for programmers these days. You can download it for yourself here - Xerces2 Java Parser. I'm not going to go into setup instructions, but at the very least you'll need the following jar files:
  • resolver.jar
  • serializer.jar
  • xercesImpl.jar
  • xml-apis.jar
Let's put these in the lib directory located in the LibProject you just created. Also, we're going to need an XML file to work with. Seeing as the focus of this article is not XML nor Xerces, we'll save the complicated examples for another day and use something simple. This is the XML file, companies.xml.
<companies> 
    <company status="spectacular">ClevelandFlash</company> 
    <company status="good">Some Company</company> 
    <company status="bad">Terrible Corporation</company> 
</companies>

You can also download it here if you're so inclined companies.xml. Place this in resources directory in your LibProject folder.

Okay, so let's code something already. We'll put the XML parsing code in ClassForXerces.java and the model structure in Company.java. This is an admittedly contrived example with very little if any emphasis on elegant design patterns, but we're not really concerned with that right now.

Here's ClassForXerces.java
package com.clevelandflash.goodtimes.core;

import java.io.IOException;

import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.SAXException;

import com.clevelandflash.goodtimes.model.Company;

public class ClassForXerces extends DefaultHandler {
    private Company mCompany;
    private StringBuffer mCurrentName;
    private String mCurrentStatus;

    public ClassForXerces() {
        this.mCompany = new Company();
    }
    
    public Company getCompany() {
        return this.mCompany;
    }

    public void parseFile(String pFileToParse) {
        SAXParserFactory lSpf = SAXParserFactory.newInstance();
        try {
            SAXParser lSp = lSpf.newSAXParser();
            lSp.parse(pFileToParse, this);
        } catch(FactoryConfigurationError fce) {
            fce.printStackTrace();
        } catch(ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch(SAXException se) {
            se.printStackTrace();
        } catch(IOException ioe) {
            ioe.printStackTrace();
        }
    }

    // Handle events from SAX parsing
    
    public void startDocument () {
        System.out.println("Start document");
    }


    public void endDocument () {
        System.out.println("End document");
    }
    
    public void startElement(String pUri, String pName, String pQName, Attributes pAtts) {
        this.mCurrentName = new StringBuffer();
        this.mCurrentStatus = "";
        if(pQName.equalsIgnoreCase("company")) {
            this.mCurrentStatus = pAtts.getValue("status");
            if(this.mCurrentStatus.equalsIgnoreCase("spectacular")) {
                this.mCompany.setStatus(pAtts.getValue("status"));
            }
        }
    }

    public void characters(char pCh[], int pStart, int pLength) {
        this.mCurrentName.append(new String(pCh, pStart, pLength));
    }

    public void endElement(String pUri, String pName, String pQName) {
        if(pQName.equalsIgnoreCase("company")) {
            if(this.mCurrentStatus.equals("spectacular")) {
                this.mCompany.setName(mCurrentName.toString());
            }
        }
    }
     
}

and Company.java, our model class that will act as a container for Company data:
package com.clevelandflash.goodtimes.model;

public class Company {
    private String mStatus;
    private String mName;

    public Company() {}

    public Company(String pStatus, String pName) {
        this.mStatus = pStatus;
        this.mName = pName;
    }

    // Getters and Setters

    public void setStatus(String pStatus) {
        this.mStatus = pStatus;
    }

    public String getStatus() {
        return this.mStatus;
    }

    public void setName(String pName) {
        this.mName = pName;
    }

    public String getName() {
        return this.mName;
    }

    // Override toString so we have something pretty to show
    public String toString() {
        StringBuffer lSb = new StringBuffer();
        lSb.append("Company detail: ");
        lSb.append("name=" + getName() + ", ");
        lSb.append("status=" + getStatus());

        return lSb.toString();
    }
}

Also go ahead and update MainClass.java to use the Xerces parser classes we created in LibProject:
// No longer the default package
package com.clevelandflash.javac_tut.core;

import com.clevelandflash.goodtimes.core.ClassForXerces;
import com.clevelandflash.goodtimes.model.Company;
import com.clevelandflash.javac_tut.helper.AnotherClass;

class MainClass {
    MainClass() {}
    
    public static void main(String[] args) {
        System.out.println("Msg from MainClass");
        AnotherClass lAnother = new AnotherClass();
        lAnother.printMessage("Hello Java developers!");

        // Use Xerces!
        ClassForXerces lParser = new ClassForXerces();
        lParser.parseFile("..\\LibProject\\resources\\Companies.xml");
        Company lComp = lParser.getCompany();
        System.out.println("Found a company here...");
        System.out.println(lComp.toString());
    }
}

Now that you've typed, copied/pasted, or dictated your way through getting that code where it needs to be we're ready to compile. The first logical thing we'll want to do is compile the LibProject source code and this will be our first chance to include some external Java libraries (jars) in our compilation. There are no other code dependencies, unlike ExampleProject which depends on LibProject, so it's safe to start here when compiling. At this time, go ahead and clear out any previously compiled .class files from your projects as well as the entire directory tree under the classes directories so we have a fresh start. Your project directories in their clean state should look like the following:
C:\DevProjects\LibProject>tree /F
Folder PATH listing
Volume serial number is
C:.
├───classes
├───lib
│       resolver.jar
│       serializer.jar
│       xercesImpl.jar
│       xml-apis.jar
│
├───resources
│       companies.xml
│
└───src
    └───com
        └───clevelandflash
            └───goodtimes
                ├───core
                │       ClassForXerces.java
                │
                └───model
                        Company.java

C:\DevProjects\ExampleProject>tree /F
Folder PATH listing
Volume serial number is
C:.
├───classes
└───src
    └───com
        └───clevelandflash
            └───javac_tut
                ├───core
                │       MainClass.java
                │
                └───helper
                        AnotherClass.java

Now, navigate to the LibProject directory and execute the following:
C:\DevProjects\LibProject>javac -d classes -cp "lib/*" -sourcepath src src\com\c
levelandflash\goodtimes\core\ClassForXerces.java

You shouldn't receive any errors. If you do, you should first do a thorough job reading the error output to make sure it's not something simple like a misspelled word (case sensitivity matters in Java, if you haven't run into this yet) or missing semicolon.

The first argument to javac you should recognize from earlier - we're just telling the compiler again to output compiled bytecode to the classes directory instead of alongside our source files. The next argument, -cp, is where the dependency magic really happens. Here we're telling the compiler to include lib directory on the classpath. Even better, the compiler allows us to use the wildcard symbol "*" to automatically include any and all jar files that happen to be in that directory. This saves us from having to type every single jar file in the classpath, though you could just as easily do that if you so desire. One more thing to note is that in using the wildcard symbol I'm forced to surround my classpath with quotes. This isn't true for all environments but it is for my Windows XP machine as it's currently configured. Again, check the javac documentation in the references below for more information about using the -classpath argument. The next argument, -sourcepath, is nothing special and again we include the full relative (that's relative from where we're executing javac) path to the root class we want to compile.

Now, navigate to the ExampleProject directory and execute the following:
C:\DevProjects\ExampleProject>javac -d classes -cp ..\LibProject\classes -source
path src src\com\clevelandflash\javac_tut\core\MainClass.java

This time we're leveraging the classes we just compiled from LibProject, thus we include their relative root compiled classes location as a classpath argument to javac. Unlike when we compiled LibProject there's no need to include the Xerces jar files on the classpath. Why? Because while the project ultimately needs those jars to execute, the dependency on them is further down the chain and we've already compiled the code that depends on those jars directly. In other words, since ExampleProject's source code doesn't directly rely on the Xerces jars, we don't need to worry about them when compiling ExampleProject.

The last thing for us to do is run our little experiment with the java tool. So finally, type the following in your command prompt and hit enter.
C:\DevProjects\ExampleProject>java -cp ..\LibProject\classes;..\LibProject\lib\*
;classes com.clevelandflash.javac_tut.core.MainClass
Msg from MainClass
The message is: Hello Java developers!
Start document
End document
Found a company here...
Company detail: name=ClevelandFlash, status=spectacular

Assuming all goes as planned, you should see the output as I've shown above. This time, the classpath includes references to the classes directories for both projects as well as the lib directory from the LibProject. Remember when I said you'd still need to think about that? Now, had our code not actually invoked any classes/methods that depended on those Xerces jar files we would not run into any problems. However, if you want to see what happens, rerun the example excluding the jar directory on the classpath, and you will be greeted with a grotesque error message from the JVM complaining about not being able to find such and such class. Last thing to note - the path you include to the Companies.xml file is relative to where you are actually call "java" from. Just something to keep in mind if you decide to do some of your own tinkering (which I encourage). Sorry, just one more thing... Those Xerces jars I had you download? Well, they come packaged with Java as of JDK 1.5, so really we probably didn't need to download them separately. But then again, that would have ruined the jar dependency lesson ;-) Okay, that's about it for this article on using the Java compiler and Java execution tool from the command line.

Conclusion

Give yourself a hand! In the world of advanced tooling and IDEs, many developers never get a chance to learn the basics and sometimes they just plain forget them. Now that you understand the Java compiler, go download Ant, or better yet, Maven!

Thank you for reading and I hope this article leaves you much more informed in compiling and running your own projects. Stay tuned for the next part in this series when I show you how to create your own class libraries in conjunction with the jar command!

Cheers,
Mike

Reference:

Wednesday, May 26, 2010

Where to Find Previous Java JDK Releases

Today I was trying to update my JDK installation to include the src.zip file. For whatever reason it didn't install with the JDK+EE install I did months back and I it's really nice to include it with your Eclipse IDE. If you're looking for a specific version of a previous version of the Java platform (JDK, JRE, etc.) simply go here - http://java.sun.com/products/archive/ - this will give you anything and everything you could hope for and it beats having to navigate through the Java website.

~Mike

Saturday, March 27, 2010

Turing machine

A friend of mine passed along this excellent site about a guy who put together his own Turing machine using a Parallax microcontroller. Enjoy!

http://aturingmachine.com/