Showing posts with label Programming. Show all posts
Showing posts with label Programming. Show all posts

Sunday, November 02, 2008

Launch OS Applications From Java

It's not a good idea to reinvent the wheel when programming for various platforms; you'll live happier when you can just use what the operating system already offers - straight from your Java application. This is especially helpful if the OS program you are interested in supports command-line invocations: this tip shows how to run those programs and capture the output those programs would produce back into your Java application. Then you could use regular expression or other means to parse the output.
Here's all you need:
    public static List<String> runCommand (String... cmd) {
List<String> output = new ArrayList<String>();
try {
// Create the process
ProcessBuilder pb = new ProcessBuilder(cmd);
Process proc = pb.start();

// Obtain the input stream
InputStream is = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

// Read what is returned by the command
String line;
while ((line = br.readLine()) != null) {
output.add(line);
}

// Close the stream
br.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}

// Return the output
return output;
}
As a utility method, just pass it an array of strings used to build the command, first the fully-qualified name of the program to invoke, followed by program arguments. For example, if I needed to run a Perl script called lockdown.pl and have the Perl interpreter at C:\Perl\perl.exe, then the string array would be something like {"c:\\perl\\perl.exe", "c:\\security\\lockdown.pl"} - notice the use of fully-qualified names everywhere - this process is cross-platform and doesn't look up environment variables to help resolve relative filenames.
The methods returns the output - what you would have seen on the console - as a list line by line. Easy stuff.

Saturday, February 23, 2008

Caching Nightmares

If you are a web developer, you will be very familiar with this problem: browsers and web servers cache stuff to help speed up response. The idea is great when things don't change much, but it ain't rosy when pages, scripts, code, and content are changing constantly and quickly.
Most browsers offer a "refresh" button that's supposed to get the latest content. Don't be surprised if it's not always the case. I think I relied too much on that feature and it screwed me over, causing me to hack my own code before I realized it could be the browser's fault (and rightly so). I've seen instances where refresh can load an old (cached) script even when a newer version exists. Reducing cache size to mere MB helped - my first clue. Usually when I suspect this kind of issue, i switch to another browser (IE does cache better) and see if things look the same.
Web servers also cache stuff. The most dangerous are what they save when shutting down so that they can restore when they are back online. I've seen instances where old stuff was used instead of newly deployed code. Tomcat is notorious for this. I disabled this kind of caching a while back (don't recall how I did it, but suddenly it was gone as I tweaked around).
Compilers are the third and final source of caching issues. Most advanced IDEs have a "clean project" feature that helps. In a nutshell, if your files didn't change, some compilers won't recompile them when you build the project - even when dependencies may have changed. The result is a product with mixed code, old and new together. The surest sign of this is new features with old data - what I call "history playback".

Saturday, February 09, 2008

Liquid Templating Language ... Say What?

I pride myself in being a diligent programmer with enough experience to be able to use any programming language under the sun, until I came across a small scripting language called Liquid. It's a server-side language - an offshoot Shopify/VBScript - that is used in some web applications to generate dynamic content in reporting views. It is touted as a simple language that anyone can use with ease.

I don't really agree with all the hype about it. In terms of flexibility and robustness, this language doesn't even come close to what modern scripting languages (both client-side and server-side) offer. To start with, it is poorly documented - an attempt to find full documentation and usage samples leads to Google Code and SVN preview to check out code if you want. It doesn't seem like people use it much.
Having a small set of constructs might make it easy to learn and use, but it severely limits what else it can do. Consider the simple idea of named variables: it doesn't have it! By extension, there's no concept of code reuse, regular expressions, and arrays/hashes - components that are useful for processing text repeatedly. In working with this language, part of me wanted to implement a Javascript engine that'd reprocess at the client whatever content Liquid produced so that it meets even the simplest requirements such as treating data with certain keywords specially.

The bottomline is this: if search engines know nothing about a language you choose to use in your application, chances are that you will be one of a dying generation of that language's users, or it is proprietary. Programming languages thrive on a huge user base in addition to a rich feature set - Liquid really has none of these. A time will come when applications written in obscure languages like this will need to be shredded in favor of simpler, fully-featured, modern languages. Consider Pascal and Cobol - they are still in use today because of the huge code base from ages ago, but there's a rapid move from them to C/C++ because of progress in programming languages. Companies that don't keep up will be stuck with antiquated and inefficient code - a long term cost. Especially for web applications where change is more rapid, I don't see this language surviving more than 7 years really. As more people find out about it, the more disadvantages out it they will see, and the less it will seem appealing for use in web projects.

Tuesday, January 15, 2008

Back To Language Basics

My friend Rachael can speak the language from Papua New Guinea as fluently as she does English, and that impressed me. For a while I hadn't been around people that spoke anything other than English and Spanish well, and I was getting bored, so this was something refreshing, and it inspired me to tap back into languages I used to know or learn some new ones. At one time, I spoke up to 6 languages well, but it's all eroded into a heavily accented English breeze. I tend to mumble much these days, have a very low voice volume (I swear it sounds really loud inside my head - that's why), and it affects how I communicate.

Some people like the accent (sounds more British than anything normally), but a majority others don't get it. People place me as being from the islands (Caribbean) and others wonder soon enough where I am from when I speak. Thing is: my accent is all languages I ever spoke rolled into one thick thing - the intonations, the phonetics, and expressiveness of my voice are heavily influenced by the African languages I learned as a child. Depending on what mood I am in (tired, stressed, happy, cheezy, etc), you might hear something different. Sometimes I can be really hard to understand ... and yet other times I'm as clear as day. My family doesn't notice anymore and for a long time I didn't care.

This year I'm doing something I enjoy much: learning languages. I started English (??) this week with my friend Jessica's mom coaching me (which I think she does professionally). On the side, I am also working through a French series using software by Topics Entertainment (Instant Immersion French Deluxe v2.0). The software has speech recognition features and some pretty good exercises to get you up to speed. If you have never spoken or learned French, even the beginner level is not for you - you need some background for this software to be useful at all. I sound ridiculous now repeating words and sentences many times over, but that's how I'll get back in the groove.
As I worked through the French series, I realized how much my experience as a musician helps me: I "sing"/sound the words and sentences I hear, and that's the only way I get them right. If I can't hear it, I can't say it - even if I can read it and understand it. I think I have an ability to imitate sounds quite well. Languages are my newest escape from the daily grind of computers, programming, music, and the social others.

After English and French, I'll be back to Swahili and Arabic (build on the little I knew), and then get caught up with other African languages. Some new languages I'd like to learn: Spanish or German. I'm not messing with Chinese and other Asian languages, like Ben and Megan have successfully done. For my friend Rochelle and the huge collection of Brazilian music I have, Portuguese would be an interesting language to pick up, I think.
The key to keeping in shape linguistically is practice, practice, practice. Any chance I have, I'll speak these languages. A while back, I switched to reading my news from French RSS news feeds ... and I haven't missed anything worthwhile on the world scene. That's just a start.

Tuesday, March 13, 2007

Losing Sleep Over A Compiler

If you are an overachiever like I think I am, you probably lose sleep over petty things; except that this isn't that simple. I am charged with maintaining and improving an application at work that was developed using Borland's C++Builder 6 a few years ago. I've sought to move the code to more modern compilers such as Microsoft Visual C++ 6.0 or Bloodshed DevC++ without success because Borland's compiler institutes a lot of dependencies on proprietary libraries. That particular IDE is no longer supported by Borland Corporation as of Dec 2006. Even DLLs developed in C++Builder are incompatible with Microsoft's or Bloodshed's IDE, defeating the whole idea of dynamic libraries in development. You can deploy DLLs built in either to an OS and they'll work fine - just if you wish to debug the DLLs, you better find the original compiler/debugger for that job.
Further demonstrating why the compiler you choose matters to the bit, there's something curious happening when I build versions of the application. At some point, the application is supposed to attempt to corrupt data on a hard drive (we test some features by creating error conditions and ensuring our chips handle them correctly - exception testing). The older version performs the task as expected, but the newer one doesn't. The problem is that the same exact command that accomplishes the task in the old version is used in the new one, but the OS responds differently. Not only that, it doesn't report any errors - the response message is the same whether it did the task or not! I spent a whole day analyzing memory dumps and data structures and I find no differences between these two applications (code changes are in an unrelated module). Walk the code in a debugger all you want, there's no difference as far as I can see.
This leaves one arena to blame - the compiler. Could there be build options that are causing this difference in behavior? I don't see any! Compiler options? Data alignment issues? If I had Windows source code, I could figure it out. My application calls the same win32 API function DeviceIoControl() - which is a pain to work with in its own right - and get the same status and error messages whether it did the task or not! There is some sense data I haven't looked at, but it shouldn't matter because it is the same in both cases. I don't know what the hell is going on, short of analyzing the assembly produced at compile time. Who knew that my assembly language class at school would come in handy like this (well, except this is an Intel assembly as opposed to what we use at school - MIPS). But it's made it vivid in my mind that in the end, the compiler choice does matter.
My tool set includes Microsoft Visual C++ 6.0, Microsoft Visual Studio C++ 2005 Express, Borland C++Builder 6, and Bloodshed DevC++ for C/C++ development. Choose your compilers wisely - it could make or break you. I find Microsoft's Visual C++ 6.0 IDE most flexible for big projects, unpolluted by the .Net stuff they've bundled in succeeding IDEs in Visual Studio.

Saturday, December 02, 2006

JSTL <c:if> Tag

Tests whether an expression is true.
Taglib
: http://java.sun.com/jsp/jstl/core (Core)
Prefix: c
Attributes:
test | boolean = expression that evaluates to true or false.
var | String = variable holding the result.
scope | String = scope for var e.g. page, session, request, or application.
Example:
<c:if test="${empty param.name}" >
// Stuff to do if the expression is true
</c:if>

JSTL <c:forEach> Tag

Used as a for loop in JSP to process elements of a collection.
Taglib
: http://java.sun.com/jsp/jstl/core (Core)
Prefix: c
Attributes:
items | String = collection to operate on.
var| String = variable holding the current item in iteration.
varStatus| String = variable holding the LoopTagStatus object.
begin| String = first index, 0-based.
end| String = last index, 0-based.
step| String = increment value, numeric.
Example:
<c:forEach items="${headerValues}" var="h">
<c:out value="${h.key}" />
</c:forEach>

JSTL <c:out> Tag

Taglib: http://java.sun.com/jsp/jstl/core (Core)
Prefix: c
Attributes:
value | String = the value to output as HTML.
[default] | String = the value to output if value is null.
[escapeXml] | boolean = whether to convert special characters to character entity codes. Default is true.
Example:
<c:out value="${param.name}" /> // To output the value of the name parameter.