Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

DisplayTag

C# has something that's a strong advantage over the base Java libraries; it has UI widgets.  If you want to show a table of search results to the user in the UI, you can write the code for the table manually, or you can just drop in a GridView and have it do most of the tedious work for you.

Java's added a *lot* of classes to Standard Edition and Enterprise Edition, but I haven't seen anything covering something like "show a table to the user".  http://displaytag.sourceforge.net/1.2/">DisplayTag is an open source project under a very http://displaytag.sourceforge.net/1.2/license.html">liberal license.  It builds and styles tables on screen as a JSP Custom Tag, allows a reasonable amount of extension, and handles things like pagination and sorting for you.  It also seamlessly handles exports to Excel/CSV and XML, and with extra libraries, easily supports PDF, XLS, and RTF formats.

We've extended it seven ways from Sunday at this point, so that our code handles the pagination, special columns can be added with AJAX-y expand/collapse of large fields, and certain columns can easily be hidden or shown.  It was easy to convince it to style exactly like our existing pages, so we were able to drop this in on the backend slowly over time; the users never saw a change, but developers writing new pages spent a lot less time typing, and moved onto the next assignment much more quickly.

At some point in the next few weeks, I'd like to kind of review in my head the "lessons learned", and see if there's anything I can contribute back to the library.  Meanwhile, the wood shop continues to eat up most of my time this month.

Java Enum

So, in Java 5, they added language support for enumeration types. There's a Java Trails tutorial that does a good job, but it left out one important bit, so here goes.

The less good way to do an enumeration is manaully, without language support.

public class Colors { 
        private static final int RED = 1; 
        private static final int BLUE = 2; 
        private static final int YELLOW = 3; 
} 
Which would be used like: 
public boolean compareColors(int color) { 
        if (color == Colors.RED) { 
                return true; 
        } else { 
                return false; 
        } 
} 
There are a bunch of problems. The two biggest
- It doesn't have type safety; anyone could call the method with any integer, not necessarily one that meant a color. Those kind of coding mistakes are hard to find.
- Printing out the value later doesn't help us much; System.out.println(Colors.RED) just returns "1". There's no useful context there.


So, enter the Java enum type.
public enum Colors { 
        RED, BLUE, YELLOW 
} 

Which would be used like:
public boolean compareColors(Colors color) { 
        if (someVariable == Colors.RED) { 
                return true; 
        } else { 
                return false; 
        } 
} 

We've gained type safety; we *know* that whatever was passed to the method .compareColors was a color; the code won't compile if a developer makes that mistake.

We've also gained context for printing/debugging; the enum type has a default .toString() method. (This is the important part the Java Trails Tutorial is missing.)

The code:
System.out.println(Colors.RED); 
Will display:
RED 


So, that's the simple enumeration. The next more complex step? Each of those RED, GREEN, BLUE values can have attributes, and also have getters and setters.
public enum Colors { 
                RED("Red"), 
                BLUE("Blue"), 
                YELLOW("Yellow"); 
                
                private Colors(String description) { 
                        this.description = description; 
                } 
                private final String description; 
                
                @Override 
                public String toString() { 
                        return description; 
                } 
        } 
So now, the code:
System.out.println(Colors.RED); 
Will display:
Red 

But that might not seem as useful, so here's a more logical example:
public enum Colors { 
                RED("Red", "#FF0000"), 
                BLUE("Blue", "#00FF00"), 
                YELLOW("Yellow", "#0000FF"); 
                
                private Colors(String description, String rgb) { 
                        this.description = description; 
                        this.rgb = rgb; 
                } 
                private final String description; 
                private final String rgb; 
                
                public String getRGB() { 
                        return rgb; 
                } 
                
                @Override 
                public String toString() { 
                        return description; 
                } 
        } 
The code:
System.out.println(Colors.RED); 
Will still return:
Red 
But also, the code:
System.out.println(Colors.RED.getRGB()); 
Will return
#FF0000 

Which would be useful at times. As an important note, even if toString() returns the same value (or same value references!) as another toString(), Colors.RED will not be equal to Colors.BLUE; they're always separate, even if they have the same values inserted.

Three Java Pitfalls

A coworker asked for a few gotchas in Java; things you just step your foot into and never saw coming.  Three seemed a good number of things to list off at once, and they're three that have come up recently.




The time and date libraries in Java are a bit broken; getting the values you want usually takes a couple lines of code, and things like time zones aren't well represented.  There are inconsistencies you get somewhat used to (getTime vs getDate returning milliseconds and the day of the month, respectively), trying to represent dates before 1970 can't work, and the Calendar implementations add a whole new level of odd choices.


Joda Time is a full replacement for java.util.Date and all of the implementations of java.util.Calendar, and sidestepping some of java.sql.Date.  It's likely to be the java.util.Date replacement starting with Java 7, if Java 7 makes it to developers any time soon.  In the meanwhile, just use the library, and save the headaches.







I've been waging a war in our codebase to *always* have developers use braces, even on one-line code blocks.

if (true) 
    System.out.println("print this"); 
    // And this comment here makes this a bit more confusing    
    else {         // Bad indentation might make it worse
    System.out.println("not true"); 
} 


Becomes a lot more clear if *every* if/else result must have braces.
if (true) {     
    System.out.println("print this"); 
}  else {           
    // Bad indentation might make it worse.         
    System.out.println("not true"); 
} 


The reasonable counter-argument  is that code on one line shouldn't need braces:
if (true) System.out.println("print this"); 


However, Ctrl-Shift-F in Eclipse autoformats code, and I'd recommend it, but it tends to reformat that back to two lines, breaking the original rule.





Finally, I suggested that learning which data types are synchronized goes a long way.  Synchronized code will often be significantly slower; unsynchronized code won't be thread safe.  It might have been better had the classes been ArrayList and ArrayListSynchronized, instead of ArrayList and Vector, but it is what it is.


The other half of synchronized data types is that some types don't have a 1:1 replacement in the standard API; you need to go to third party libraries for that.  SimpleDateFormat isn't thread safe, and it's replacement, FastDateFormat, is in Apache Commons Lang. 


At that point, I realized that *all* of Apache Commons is pretty much a must-read for this question, and recommended the online reference The Common Java Cookbook, on discursive.com.   It's a step by step methodical walkthrough of *all* of Apache (formerly Jakarta) Commons, and it's great for finding small parts of their  work that you might have missed before.

AppFuse

Not sure if it has any level of acceptance or not, but AppFuse 2.1 is out.

AppFuse is a group of folks bundling together a set of technologies to build a web site using Java. Instead of starting from scratch on a new project, the goal is to give you a running start, which hugely speeds up small projects.

It'll automatically generate code with your choice of persistence framework using a few easy to understand best practices. It can use Struts, Spring MVC, Stripes, or Tapestry. Dojo, DWR, and Scriptaculous are built in. It uses Maven2. It ties into all major databases. Acegi security. SiteMesh, all of Spring, and a couple more touches on top of all of that.

I played with in in V1, and it was an excuse to get familiar with Maven. Might have to dig in now that they've updated, and added quite a few more kitchen sinks.

JDK7, Closures, Dynamic Typing Support in JVM

So, some interesting items have shown up in the Java 7 specs. Equally as interesting to me is that they have more ideas they intend to implement than they have manpower; for some reason, I mentally assumed that the Java language was mature enough that the feature additions/maintenance would match the available manpower by now. Wrong on my part, I suppose.

Anyways, in the article I'm pointing at, they're announcing:


  • Switch statements can now be based off of Strings, not just char types.
  • Automatic Resource Management - try/catch blocks can now automatically close streams quietly on exit, so you don't need two nested try/catch blocks anymore. I'm wondering how much different than Apache IOUtils.closeQuietly() this will be.
  • Generics get a shortcut for creation: List list = new List<>(); you don't have to type String the second time.
  • Binary literals (0b01010110), underscores in Strings (ala Ruby, int ONE_MILLION = 1_000_000)
  • Lists may be created similar to arrays (List list = {"One","Two","Three"})

And the two bigger chunks:

  • Support for dynamically typed languages in the JVM (JSR 292). Dynamic typed languages are things like JavaScript; you don't have to declare a variable's type, it figures it out for you. This update sounds like "optimize the JVM so that JavaScript can be more easily made into a Java bytecode."
  • Closures. Basically, a closure is a method that can be passed as a parameter to another method. Which is a huge change in the way code is written today in Java


Going on about closures, if you have a class with all static methods that implements an interface, and is only referred to one method at a time, there's circumstances where it might be much cleaner just to pass the method. Being more specific, SortedSet is implemented by TreeSet. TreeSet has a constructor that takes an initialized Comparator, which implements compare(a,b) and equals(a,b). compare(a,b) returns an int, and returns 0 if equals(a,b) would be true. With closures, in theory, it'd be much less verbose to just call TreeSet's constructor with a closure - send it compare(a,b) directly, without spending time implementing the comparator in another class or in an internal class.

Or not. I'm really interested to see how this plays out.

instead of having a class that implements an interface, you could simply pass the f

OOP Job Opening in Washington, DC

So, I'm moving back to Pittsburgh to be closer to family, and sat down and talked with my current employer about it, and am trying to make the transition smooth on their end. So, a friendly small employer has a job opening:

Systems Analyst
-Small group of software developers and a sysadmin working on custom solutions for a DoD human resources office
-Technologies include C#.NET, Java/J2EE, SQL Server, Visual Studio, NHibernate, Ant, IIS, BEA, Subversion, of which OOP and SQL are necessities
-Candidate will have bachelors in CS or related field and three years experience, or six years relevant experience
-Candidate must be eligible for a Secret level clearance

Upsides: Everyone here is friendly. There are very specific goals for what must be accomplished, but enough extra time on top of that so that developers can work on what they feel is important to be addressed. There's a reasonable budget for new hardware and software, so you're never hamstrung by details. The pay and benefits are quite competitive. Everyone here is friendly.

Downsides: It isn't rocket science, it's software for an HR department. If you see yourself going home at the end of the day with code on the next lunar lander, keep looking. One of the projects in particular is in very mediocre shape from a maintenance standpoint, and is a pain to poke at when it breaks. There are no nearby restaurants to grab lunch, as well.

I've enjoyed the up much more than the down. I'm moving for family, and would really like to see my spot filled by someone awesome for a clean transition.

Worst Practices

I'm working on a project where the original authors of the code weren't competent with the tools they chose to use, or the tools that were chosen for them.

The technology involved is BEA Weblogic, Java, Servlets, JSP, HTML, JavaScript, MSSQL.

This is from 1999, and there's no real concept of MVC. Some HTML occurs in the Java instead of the JSP. Part of the business logic is in Java, but more than half happen as SQL stored procedures and functions. Cut-and-pasted blocks of SQL repeat the same task in multiple places with different variables, so if you find a bug in one place, it may be everywhere, and a quick search may not turn it up.

Several bits of that business logic appear to happen by accident. A variable may be returned from a multi-return stored procedure that has been set to a constant at return-time, or may be the value of an uninitialized variable in the SQL that's never used anywhere. Why these weren't set as constants in the Java object, I don't know.

Meanwhile, in using Java, they chose to use as little of the object oriented features as possible. Instead of having an employee, who has a first name, a last name, an id, and so on... they chose to represent groups of employees as rows in two-dimensional arrays with undocumented column names.

Nothing is commented. The primary language of the coders was not English, so the variable names I do have are often misspelled in misleading ways. The variable names in the database are truncated, and often misnamed for what they represent. There is no documentation of what any of the business logic is supposed to do.

The Java itself isn't archaic, it's written in a style I've never seen before. Today, I track back and find out the value of the variable mainPay is always "1", "2", or "3". I stagger across this:
if ( "1".indexOf(mainPay) > -1 )
else if ( "23".indexOf(mainPay) > -1 )


The database isn't normalized, and indeed, isn't planned by someone who understood relational databases. All numbers are stored as strings. Some of the numbers are padded with whitespace, and others aren't, and the distinction is both important and arbitrary. One column that I've found takes user input positive numeric data (1, 2, 3, 4, 5), and stores it as Roman numerals, space-padded to three spaces, but not beyond. However, if one checkbox on screen was selected, the column then stores the character 'Y'.

This is the second ugliest code I've ever worked on, and refactoring doesn't seem to be an option that the management will consider, as we don't have the manpower to do it. I now understand how Cobol was still a problem for Y2K, at least.

My working assumption was that this was done by a group of classic Visual Basic developers who were learning Java as they went, as a VB coder's thought processes would account for most of these problems. The software, given very carefully massaged input, is rock-solid, and I'm astounded every day at how hard these folks must have had to work to get this big of a turd polished to shine on the outside.