Wednesday, February 5, 2014

JDK8 Lambdas - Syntactic Sugar Anyone?

Among the features soon to be available in JDK8 is this nice piece of syntactic sugar known as lambdas. Lambdas are not a new concept and are very familiar to C# developers. Even among them though, there are those that love lambdas and those that would rather just not use them because of lack of clarity. I am one of the latter.

I have had some limited C# development and find that these can often obscure the way that the code can be understood and are very daunting when you are new to the language. This particularly becomes an issue when used in LinQ expressions which do not necessarily work in the way expected and often times not until the data is actually used.

In an attempt to put my bias aside, I attempted to grasp the JDK8 implementation of them and provide a simple to understand tutorial on them.

What Is A Lambda?

As simply as I can put it, a lambda is a syntactic style that allows you to provide an expression about an individual object type in order to do something with the data. It allows for filtering, applying functions to them, counting them, iterating through them and more in a style that is very simple to write. A typical lambda is written as:

(argument list) -> body

If the argument list contains only one argument, the parenthesis can be omitted. The argument list can be empty also but in such a case, the parenthesis are still required. I will try to explain the lambdas demonstrated in the tutorial as needed.

Getting Started

If you have not set up your Eclipse to use JDK8, please see this post for detailed instructions. All code for this example can be found in my GIT repository at java-blog-samples.

Why Use Lambdas?

To start our tutorial, I have created a TestObject class. This will be the object we will include in a List using the TestObject.generateTestObjectList() static method. The actual examples of the various implementations of below are found in the ObjectTest class.

Example 1

Lets take our List of TestObjects. Suppose you need to find any objects in that list that hava an 'a' value greater than 20. We will be smart developers by creating a method because we know we will have to process multiple searches. So using conventional Java programing we create:
    private static void printObjectsWithAGreaterThanTwenty(List<TestObject> list) {
        // get each element in the colection and display it based on criteria
        for(TestObject t : list){
            if (t.getA() > 20) t.displayObject();
        }
    }
We implement the method in our code:
        //Ex. 1 - Hardcoded Result
        println("Ex. 1: Hardcoded Result", under);
        println();
        println("TestObject with a > 20 (hardcoded)");
        println();
        printObjectsWithAGreaterThanTwenty(objList);
        println();
When run, we get the following result:
Ex. 1: Hardcoded Result
***********************

TestObject with a > 20 (hardcoded)

TestObject (Rainmaker):  a: 21 b: 37
TestObject (Boss Hog):  a: 34 b: 47
TestObject (Terror):  a: 45 b: 58
TestObject (Pitbull):  a: 79 b: 70
TestObject (Axe):  a: 124 b: 82
This works really great. Every time we need to know which objects contain an 'a' value greater than twenty, we have it! But that means every time we have to search we have to create a method. This makes our code very inflexible but we move on.

Example 2

Next we next find some analyst added the requirement that we have to display all objects which have a 'b' value within a given range. So we again create a method to find the results but this time, we add parameters to our method.
    private static void printObjectsWithBInRange(List<TestObject> list, int low, int high, Inclusivity rule) {
        for(TestObject t : list){
            switch (rule){
                case BOTH:
                    if(t.getB() >= low && t.getB() <= high) t.displayObject();
                    break;
                case END:
                    if(t.getB() > low && t.getB() <= high) t.displayObject();
                    break;
                case START:
                    if(t.getB() >= low && t.getB() < high) t.displayObject();
                    break;
                case NONE:
                    if(t.getB() > low && t.getB() < high) t.displayObject();
            }
        }
    }
We even push its capability by adding the addition of an enum to determine which, if any, of the low and high limits should be included in the result.
    private enum Inclusivity {
        START, END, BOTH, NONE
    }
So we implement it in our code:
        //Ex. 2 - Parameterized Range
        println("Ex. 2 - Parameterized Range", under);
        println();
        println("TestObject with b between 10 and 70 inclusive");
        println();
        printObjectsWithBInRange(objList, 10, 70, Inclusivity.BOTH);
        println();
and when we run it, we get this:
Ex. 2 - Parameterized Range
***************************

TestObject with b between 10 and 70 inclusive

TestObject (Viper):  a: 3 b: 10
TestObject (Stingray):  a: 5 b: 15
TestObject (Snoopy):  a: 8 b: 21
TestObject (Archangel):  a: 13 b: 28
TestObject (Rainmaker):  a: 21 b: 37
TestObject (Boss Hog):  a: 34 b: 47
TestObject (Terror):  a: 45 b: 58
TestObject (Pitbull):  a: 79 b: 70
Again, we have made a good effort but we notice for every requirement, we are adding a new method to support the criteria being searched. What if the type of object in the result set is not a TestObject? Our code got better but it is still inflexible and can be broken easily.

Example 3

So we finally decide we need to refactor and realizing that we can use a nested inner class, we create a functional interface (an interface declaration with only one abstract method).
    // Functional Interfaces
    interface TestObjectValidator {
        boolean test(TestObject t);
    }
We also create a method which takes in a TestObjectValidator.
    // Functional Interfaces
    interface TestObjectValidator {
        boolean test(TestObject t);
    }
We then create an inner class and implement the TestObjectValidator whenever we want to provide a test condition as we did when we needed to print the TestObjects when the name field starts with "s" (case insensitive) and where three times its 'a' value is less than or equal to its 'b' value.
        //Ex. 3 - Use of Local Class
        println("Ex. 3 - Use of Local Class", under);
        println();
        println("TestObject with starting with 'S' and a*3 <= b");
        println();
        
        class TestObjectForNameAndRange implements TestObjectValidator {

            public boolean test(TestObject t) {
                return t.getName().startsWith("S") && t.getA() * 3 <= t.getB();
            }
        }
        
        printTestObjects(objList, new TestObjectForNameAndRange());
        println();
This then produces the output:
Ex. 3 - Use of Local Class
**************************

TestObject with starting with 'S' and a*3 <= b

TestObject (Shortstop):  a: 2 b: 6
TestObject (Stingray):  a: 5 b: 15
But this is still clunky and fragile. We still find ourselves writing extra inner classes for each test case.

Example 4

Growing wiser, we realize further that there is no need to create the inner class now that JDK 8 allows anonymous classes. It's the answer to our problems! We immediately set to work refactoring.

We change our code to use this anonymous class like this:
        //Ex. 4 - Use of Anonymous Class
        println("Ex. 4 - Use of Anonymous Class", under);
        println();
        println("TestObject with starting with 'S' and a*3 <= b");
        println();
        
        printTestObjects(objList, new TestObjectValidator() {
            
            public boolean test(TestObject t) {
                return t.getName().startsWith("S") && t.getA() * 3 <= t.getB();
            }
        });
        println();
Which still yields the same results as in Example 3:
Ex. 4 - Use of Anonymous Class
******************************

TestObject starting with 'S' and a*3 <= b

TestObject (Shortstop):  a: 2 b: 6
TestObject (Stingray):  a: 5 b: 15
This is better than the inner class because we code the anonymous class as we need it. It is only better when there is no other time that the same test is being performed in the span of the class or application. This is worse than the inner class as it is not maximizing reusability of the code.

Example 5

So lets take what we know a step further. Lets introduce a lambda in place of the anonymous class. We know that we can pass a parameter into the lambda and it will produce an output. We make the following change to Example 4 above:
        //Ex. 5 - Use of Lambda
        println("Ex. 5 - Use of Lambda", under);
        println();
        println("TestObject with starting with 'S' and a*3 <= b");
        println();
        
        printTestObjects(objList, (TestObject t)->t.getName().startsWith("S") && t.getA() * 3 <= t.getB());
        println();
Our lambda is this:
        (TestObject t)->t.getName().startsWith("S") && t.getA() * 3 <= t.getB()
What this says is "for a given TestObject, return true if the TestObject.name starts with 'S' and three times the value of TestObject.a is less than or equal to the value of TestObject.b otherwise, return false".

Why can this one expression substitute itself in place of the TestObjectValidator interface? Remember back in Example 3, we stated that a functional interface is an interface declaration with only one abstract method definition. It can have any number of default and static methods but only one abstract method to be considered a functional interface. Since there is only one abstract method, you do not need to include the name of the method in order to implement it. Because this is the case, you can substitute a lambda for the anonymous class as long as it returns the same type as the abstract method declares.

As we can see, the result of running our code is the same as we saw in Examples 3 and 4.
Ex. 5 - Use of Lambda
*********************

TestObject with starting with 'S' and a*3 <= b

TestObject (Shortstop):  a: 2 b: 6
TestObject (Stingray):  a: 5 b: 15
Our code is now becoming a bit more flexible. We gain the simplicity of not having to define the whole anonymous class. This is the first bit of "syntactic sugar" we see as a result of lambdas.

Example 6

Now lets introduce some of the java.util.function package classes added for the purpose of serving lambdas and their implementation.

The first such class is the Predicate. The Predicate is a generic functional interface with only one abstract method, test(T t). Implementing the Predicate interface, the test method can do anything that results in a boolean response. Simply put, we can create a new method::
    private static void printTestObjectsWithPredicate(List<TestObject> list, Predicate<TestObject> filter){
        for(TestObject t : list){
            if(filter.test(t)) t.displayObject();
        }
    }
Now, our method can take any Predicate typed with a TestObject and a lambda can be passed without need for a method name and every object in the List of TestObject objects passed will be tested for the Predicate lambda and as our method says, it will call TestObject.displayObject() on that TestObject.

So we implement this new method in our code:
        //Ex. 6 - Use of Predicate in place of Lambda
        println("Ex. 6 - Use of Predicate in place of Lambda", under);
        println();
        println("TestObject with name containing 's', case insensitive");
        println();
        printTestObjectsWithPredicate(objList, t -> t.getName().toLowerCase().contains("s"));
        println();
When we run it, we find our Predicate has displayed each TestObject in the List that contained a case insensitive 's':
Ex. 6 - Use of Predicate in place of Lambda
*******************************************

TestObject with name containing 's', case insensitive

TestObject (Windsurfer): a: 1 b: 3
TestObject (Shortstop):  a: 2 b: 6
TestObject (Stingray):  a: 5 b: 15
TestObject (Snoopy):  a: 8 b: 21
TestObject (Boss Hog):  a: 34 b: 47
This makes our code less brittle but we are still bound to the one outcome for a given method definition. Or are we?

Example 7

Next we take a look at another generic functional interface, the Consumer. The Consumer can be viewed literally as the class that devours the lambda because the Consumer interface accepts a lambda which returns void. It has one abstract method, accept(T t).
We define a new method which accepts a TestObject List, a Predicate and a Consumer:
    private static void processTestObjectWithPredicateAndConsumer(List<TestObject> list, Predicate<TestObject> filter, Consumer<TestObject> voidFunction) {
        for (TestObject t : list){
            if(filter.test(t)) voidFunction.accept(t);
        }
        
    }
We then implement the method in our code:
        //Ex. 7 - Use of Predicate and Consumer Lambda
        println("Ex. 7 - Use of Predicate and Consumer Lambda", under);
        println();
        println("TestObject with name ending in 'y', case insensitive");
        println();
        processTestObjectWithPredicateAndConsumer(objList, t -> t.getName().toLowerCase().endsWith("y"), t -> t.displayObject());
        println();
The Predicate lambda performs a case-insensitive test on each TestObject to see if the TestObject.name field ends with a 'y'. It then passes that TestObject to the Consumer. The Consumer lambda invokes the TestObject.displayObject() method on it.

This produces the output:
Ex. 7 - Use of Predicate and Consumer Lambda
********************************************

TestObject with name ending in 'y', case insensitive

TestObject (Lefty):  a: 0 b: 1
TestObject (Stingray):  a: 5 b: 15
TestObject (Snoopy):  a: 8 b: 21
We now have the flexibility to use any Predicate<TestObject> lambda and any Consumer<TestObject> lambda. We therefore changed the name from print... to process because any Consumer could be passed which may or may not print the TestObject.

Example 8

Lastly in this blog, we will cover the case where you may want to do more with your initial results and then do something on that before passing it on to the Consumer interface. This is possible with the Function<T,U> functional interface. Its interface defines one abstract method, U apply(T t). Function takes a lambda function of type T with a return type of U. So we start by defining a new method:
    private static void processTestObjectWithPredicateFunctionAndConsumer(List<TestObject> list, 
            Predicate<TestObject> filter, Function<TestObject,String> mapper, Consumer<String> voidFunction){
        for (TestObject t : list){
            if(filter.test(t)) {
                String out = mapper.apply(t);
                voidFunction.accept(out);
            }
        }
    }
We see this method will perform the test defined by the Predicate Lambda and pass the TestObject match to the Function. The Function lambda defined must take a TestObject in and return a String. Finally, the String is passed to the Consumer which performs some void function on it.

Implementing this method in our code:
        //Ex. 8 - Use of Predicate, Function and Consumer
        println("Ex. 8 - Use of Predicate, Function and Consumer", under);
        println();
        println("TestObject name where a >= b");
        println();
        processTestObjectWithPredicateFunctionAndConsumer(objList, t->t.getA() >= t.getB(), t -> t.getName(), name -> println(name));
        println();
The Predicate lambda in this is looking for any TestObject in the list that has a TestObject.a value greater than or equal to its TestObject.b value. If the Predicate test is true, the TestObject has the TestObject.getName() method on it (which returns a string). That String is then passed to the Consumer wihch then calls the com.blogspot.howdoidothatinjava.utilities.PrintUtilities.println(String s) method.

The resultant output is:
Ex. 8 - Use of Predicate, Function and Consumer
***********************************************

TestObject name where a >= b

Pitbull
Axe
The lambdas can be defined for any type of Predicate, Function and Consumer action desired making the method very versatile and simplifies reuse in many different situations. Currently, there is also available a BiFunction<T, R, S> functional interface which takes two input parameters and has the return type of S. I am not sure if this is going to be extended out to further functional interfaces with even greater numbers of parameters. There is certainly nothing preventing the developer from creating a function interface of their own that does this.

Wrap-Up

We have covered ways that lambdas can be used to increase code flexibility and through the syntactic sugary goodness they provide, simplify some collection processing tasks. In my next blog, I will further detail how we can add generics to add even more flexibility. We will also look at named lambdas for reuse. We will also look at the bulk data processing functions provided through the java.util.function package.

Monday, February 3, 2014

Eclipse Setup For JDK8 Lambda Development

As developers, we all love to get a jump on learning changes to the technologies we employ to make our living. With the release of JDK8 right around the corner, March 18, 2014 from the last I read, I thought I'd give a crack at learning how to use lambdas in my code.

So, I set straight to it. I went and got the latest JDK8 beta release, set it as JAVA_HOME, downloaded Eclipse Kepler and, much to my chagrin, it had no idea how to deal with my first lambda code example.

After a significant amount of effort and almost giving up, I finally got my environment working and could spend some time learning how to use this new feature coming in the JDK release. I figured because I blog about all sorts of things related in and around Java, that maybe others might benefit from some quick tips on how to set up their environment to test this new feature.

Getting Started

  • Download Eclipse Kepler and extract it only the files inside the zipped "eclipse" folder into the location of your choice.  For this blog's purpose we will reference C:\Kepler_Eclipse.
  • Download JDK8 with Lambda Support and install it. Note: You must accept the "Pre-Production Software Evaluation Agreement for Java SE" in order to begin the download.

Changing An Existing Kepler Configuration


If you already have Kepler installed, you need only make the changes to add the support for JDK8 shown in the software update and to make sure you have JDK8 as your project JRE, project compiler and JAVA_HOME. You can jump straight to the Testing Out Ecliplse Configuration section.

Make JDK8 Your Main Java Version

 Open your System Properties
  1. Press Ã¿ + R keys together
  2. Enter the following in the input box (without quotes "control sysdm.cpl,,3")
  3. Click OK
Image 1: System Properties Dialog box

Add or Update JAVA_HOME

  1. In the System Properties window displayed, click the Environment Variables button to display the Environment Variables dialog shown in Image 2.

    Image 2: Environment Variables Dialog

  2. As you can see, I develop with multiple versions of Java and need to switch my JAVA_HOME between them from time to time. I have set up the releases I run so I can easily change which one the system is using. You do not need to do this if you are using only one Java release.

    If JAVA_HOME is not in your System Variables section, you will need to click the "New..." button. If it is present and not currently pointing to JDK8, you will need to click it in the table to highlight it then click the "Edit..." button. The New (or Edit depending on which button was pressed) Environment Variable dialog box will open as shown in Image 3. Note the values for a new dialog are empty on first display.  I entered the values shown to use the image for multiple steps.

    Image 3: New System Variable dialog
  3. In the New Environment Variable Window, enter the the Variable name as "JAVA_HOME" and the value as the location to the Java folder (not java/bin) where you installed Java (i.e. "c:\jdk1.8.0"). The example above shows how I set mine up to reference my JDK8 instance I had assigned to the JAVA_1_8 environment variable I created.
  4. Click "OK"
  5. Before we can close the Environment Variables dialog, we need to modify the Path variable.  Scroll through the System Variables and find the "Path" environment variable and click the "Edit..." button.
  6. Referring to Image 4, left-click the cursor in the value field once and then using the left and right buttons, look through the value field for a %JAVA_HOME%\bin entry. If it is found, skip to Step 7. If it is not found, move the cursor all the way to the home (left arrow until cursor moves left no further or just press the "Home" key when the edit cursor is in the variable value) and enter, sans double-quotes, "%JAVA_HOME%\bin;" at the start of the Path value.

    Image 4: Edit Path System Variable

  7. Click OK
  8. Click OK in the Environment Variables dialog to close it.
  9. Click OK to close the System Properties dialog to close it.

Prepare Eclipse

  1. Open Eclipse by double-clicking the eclipse.exe icon in the C:\Kepler_Eclipse folder (or the folder where you extracted it to). If the extract was done incorrectly, the files for Eclipse may be inside an additional "eclipse" folder.
  2. In the Workspace Launcher dialog, enter the location where you would like to save your projects (or you can point it to an existing workspace).

    Image 5: Eclipse Workspace Launcher dialog
  3. Once Eclipse is open, from the menu, go to Help->Install New Software... (see Image 6)
    Image 6: Available Software dialog
  4. Type, without quotes "org.springsource.ide.eclipse.java8.site - http://dist.springsource.com/snapshot/TOOLS/java8/e43" into the "Work with:" field and hit "Enter". After a few seconds, the main listing of software found will be updated.
  5. Click Next to see the Install Details view.
  6. Click Next to see the Review Licenses view.
  7. Click "I accept the terms of the license agreement" and Click "Finish"
  8. If you get a Security Warning dialog about installing software that contains unsigned content, click "OK"
  9. When prompted to restart Eclipse, click "Yes"

Testing Out Eclipse Configuration


At this point, we are ready to try out the Eclipse configuration.  If you know how to use GIT and want to pull my code for this example directly, you can find the code in the java-blog-samples repository. As the subject of this blog is neither to teach how to import a project from GIT into Eclipse nor is it to teach how to use GIT, please refer to the excellent tutorial that can be found at vogella.com.

If you need to do the testing manually, here are the basic steps.
  1. Right click in the Project Explorer box in any blank area
  2. Select "New" -> "Project..."
  3. In the Filter Box, enter "Java Project" without quotes
  4. Select the Wizard that is just called "Java Project" and click "Next"
  5. In the new Java Project dialog, enter the project name "JDK8_Sandbox". (Refer to Image 7 below)

    Image : Create a Java Project
  6. Select the JRE option "Use an execution environment JRE and select "JavaSE-1.8". If it is not available, click the Configure JREs... link and add jdk1.8.0 to the list of JREs configured
  7. Click "Finish". A new project will be created.
  8. Create a new package in the src directory, given any name you want to call it
  9. Create a class in that package called "Sandbox"
  10. Select all lines but the package name and delete them.  Copy the following code and paste it in the Sandbox class

    import java.util.List;
    import java.util.function.Predicate;
    
    public class Sandbox {
     
     public static void main(String[] args) {
      List<TestObject> objList = new TestObject().generateTestObjectList();
      Predicate<TestObject> objFilter = tO -> tO.getA() > 20;
      objList.stream().filter(objFilter).forEach(tO -> tO.displayObject());
     }
    
    }
    
  11. Create a new class in the same package called "TestObject"
  12. Select all lines except the package name and copy and paste the following code into the TestObject class.

    package com.blogspot.howdoidothatinjava.sandbox;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class TestObject {
     int a, b;
     
     public TestObject(){
      a = 0;
      b = 0;
     }
     
     public TestObject(int a, int b){
      this.a = a;
      this.b = b;
     }
     
     public List<TestObject> generateTestObjectList(){
      List<TestObject> out = new ArrayList<TestObject>();
      int[] aArray = new int[]{0, 1, 2, 3, 5, 8, 13, 21, 34, 45, 79, 124};
      int[] bArray = new int[]{1, 3, 6, 10, 15, 21, 28, 37, 47, 58, 70, 82};
      for (int i = 0; i < aArray.length; i++){
       out.add(new TestObject(aArray[i], bArray[i]));
      }
      return out;
     }
     
     public int getA(){
      return a;
     }
     
     public int getB(){
      return b;
     }
     
     public void displayObject(){
      System.out.println("TestObject: a: " + getA() + " b: " + getB());
     }
     
    }
    
  13. Build the project (if not set to automatic) and any errors should be cleared.
  14. Switch to the Sandbox.java file tab again in Eclipse
  15. Right click on the code and Select "Run As" -> "Java Application"
  16. If you followed the configuration exactly as above, the following should be displayed in the Eclipse Console view:

    TestObject: a: 21 b: 37
    TestObject: a: 34 b: 47
    TestObject: a: 45 b: 58
    TestObject: a: 79 b: 70
    TestObject: a: 124 b: 82
    

Wrap-Up

As this has been intended to discuss setup of Eclipse Kepler to use for JDK8 development, I won't take more time to discuss more of the details of lambdas in JDK8.  I will cover that in a later blog post but for now, you are set up to do further learning and experimenting with JDK8.

Wednesday, January 29, 2014

Making Ant Scripts Smarter Using Macrodef

General:


Have you struggled using Ant? Have you experienced the frustration of getting scripts to work exactly the way you want?  I have been dealing with the Ant-isms that seem to make the process of creating a build difficult to accomplish for some time now.  I have added the Apache.org ant-contrib jar file to add some intelligence but it can fall short.  Sometimes it even causes the build to run longer because of a need to create objects to handle some of the tasks that I need done.   Not wanting to create my own "addon" classes to address my issues due to current time constraints I reached the point where I felt my only solution was to write copious lines of redundant targets to address multiple tasks.  Then I found the macrodef task and my Ant scripts have now picked up considerably in the smart department.

As fair warning this blog topic is not to replace the Ant documents already in place which document the macrodef task.  My intention is only to give some basics to people needing some intelligent Ant scripts.  By introducing them to the macrodef task through a few simple examples, they may have confidence to tackle the official documentation to get more details on all the sub tasks, properties and nuances of this very useful Ant task.   To this end, only required properties and sub-tasks will be listed where a task is described.

The Basics:


A macrodef should be a child of the project task in the ant script. If enclosed inside a target task, it can only be used within that target task.

Here is the most basic example so we can start discussing some of the elements:
<macrodef name="mymacro">
    <sequence>
    </sequence>
</macrodef>
The main XML element for this is <macrodef>.  This task has only one required property: "name".   This will be the name by which you will call the macro in future targets.  We will see this more in a bit.

The macro, "mymacro" does nothing.  So, lets improve on it a bit.  Consider the following:
<macrodef name="sayhello">
    <sequential>
        <echo>Hello World! I am "sayhello" macrodef!</echo>
    </sequential>
</macrodef>
Now, to run the macro, you only need to put the following as a child of project task or in a target.:
<sayhello />
which produces:
    [echo] Hello World! I am "sayhello" macrodef!
If entered as a child of the project task, it will run every time the ant XML file is run whereas if it is in a target, it will only run when that target is run.

The macrodef task requires a nested sequential task. Any ant task can be put inside the sequential task. This is the unit of work the macrodef task will perform.

At this point, the macro still is not very useful. It would seem a waste to write all the macrodef when you could have just enclosed the echo task directly inside a target task.

So, we introduce the attribute task.  Attribute tasks are the parameters passed to the macro from the calling function with no nested tasks.  The name of each attribute is the name of the corresponding property you pass in the call.  An example will explain better:
<macrodef name="sayhello">
    <attribute name="addressee" />
    <sequential>
        <echo>Hello World! I am "sayhello" macrodef!</echo>
    </sequential>
</macrodef>
So the call to implement the macro would look like:
<sayhello addressee="Bob"/>
This has now passed the parameter addressee with a value of "Bob" to the macro.  We still have a problem because the macro does not do anything with the parameter.  Again, lets go back to the macrodef task and connect the attribute.
<macrodef name="sayhello">
    <attribute name="addressee" default="World"/>
    <sequential>
        <echo>Hello @{addressee}! I am "sayhello" macrodef!</echo>
    </sequential>
</macrodef>
As you can see there are two changes.  First, I added an optional parameter "default" to the attribute task and set the value to "World".  This is because we do not want the line to print to the console as:
    [echo] Hello @{addressee}! I am "sayhello" macrodef!
If not defined, the attribute, as does an undefined property, will not expand in the Ant processor.

Secondly, note the use of the "@{someattribute}".  It is used to expand an attribute just as ${someproperty} is used to expand a property in Ant.

Now, lets finally run the call again.  First using:
<sayhello />
We see the output still is the same as the original macro:
    [echo] Hello World! I am "sayhello" macrodef!
If we call it with the parameter "addressee", we see the glory of parameters because this:
<sayhello addressee="Bob"/>
will now display this:
    [echo] Hello Bob! I am "sayhello" macrodef!

Tuesday, January 28, 2014

Using the Java Keyword: final

So, you have been coding for some time and you happen across the occurrence of the Java keyword final. What does it mean? How does it apply to what I am doing? I thought I would give some examples of the use of the word in order to better aid in clearing up the use of this keyword.

The 'final' Class

Declaring a class final makes it so no other code can subclass it. This prevents a stable, reliable class from being changed in a way so as to break code dependent on it. This can be seen in many classes in the Java standard library such as java.lang.String and java.lang.System.

Example 1:
package com.blogspot.howdoidothatinjava;

public final class UnextendableClass {
    
}

If you were to try compiling the following:
package com.blogspot.howdoidothatinjava;

public class ExtendedClass extends UnextendableClass {
    
}

... you would get the following compiler error:
ExtendedClass.java:3: error: cannot inherit from final UnextendableClass
public class ExtendedClass extends UnextendableClass {
                                   ^

The 'final' Method

A method that is marked final cannot be overridden by any of its subclasses. Typically a method is marked final when it should no longer be changed because it behaves exactly as it is desired and no further change could improve it or if changing it would cause critical functionality to break. At times, constructors call methods and these should generally be final because a subclass could cause unexpected behavior if it were to override that method.

Example 2:
package com.blogspot.howdoidothatinjava;

public class FinalMethodClass {
    
    public void nonFinalMethod(){
        // does something can be redefined
    }
    
    public final void finalMethod(){
        // does something that shouldn't be changed
    }
}

If you tried compiling the following subclass:
package com.blogspot.howdoidothatinjava;

public class FinalMethodClassSubclass extends FinalMethodClass {
    
    public void nonFinalMethod(){
        // does something differently from super class implementation
    }
    
    public void finalMethod(){
        // this causes compiler error
    }
}

You would recieve the following error at compile time:
FinalMethodClassSubclass.java:9: error: finalMethod() in FinalMethodClassSubclass cannot override finalMethod() in Final
MethodClass
    public void finalMethod(){
                ^

The 'final' Variable

final variable is a variable that can only be initialized one time, either at declaration or in the class constructor. Any attempt to initialize the variable outside the constructor or any attempt to reassign a final variable will result in a compile error. A final variable which is declared only first and then initialized in the constructor is called a blank final.

Typically, constants in a Java program are declared static final. This is because the constant only needs to be declared once so it should be "static" and it is final because it cannot be changed. Common practice is to give constants names which are all uppercase and words are separated with underscore characters. (i.e. SECONDS_IN_MINUTE, HOURS_IN_DAY, PI, etc.)

Any mutable object declared final can be modified by any class or method referencing it.  It cannot be reassigned.  The declaration of a mutable object only makes the variable name of the object final.

Example 3:
package com.blogspot.howdoidothatinjava;

import java.util.ArrayList;
import java.util.List;

public class FinalVariableClass {
    
    private final static int SECONDS_IN_MINUTE = 60;
    private final static int MINUTES_IN_HOUR = 60;
    private final static int SECONDS_IN_HOUR;
    
    { SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR; }
    
    private final List<String> finalThings = new ArrayList<String>();
    private final int int1, int2;
    private int total;
    
    public FinalVariableClass(){
        int1 = 17;
        int2 = 42;
        total = getTotal();
    }
    
    public int getTotal(){
        return int1 + int2;
    }
    
    public void setInt1(int in){
        int1 = in;
    }
    
    public void setupFinalThings(){
        String[] strings = new String[]{"ball", "cat", "tree"};
        for(String s : strings){
            finalThings.add(s);
        }
    }
}

There are several issues which will prevent the code from compiling. First, the static final SECONDS_IN_HOUR is not initialized. The attempt to initialize it in a static block failed because you cannot initialize a final variable outside of  a constructor and final static fields must be declared in the same manner as SECONDS_IN_MINUTE or MINUTES_IN_HOUR.

FinalVariableClass.java:12: error: cannot assign a value to final variable SECONDS_IN_HOUR
    { SECONDS_IN_HOUR = SECONDS_IN_MINUTE * MINUTES_IN_HOUR; }
      ^

Additionally, there is an issue with the method setInt1(int in). This method is trying to reassign the value of the variable 'in' to 'int1' which is final. The compiler promptly tells us so.

FinalVariableClass.java:29: error: cannot assign a value to final variable int1
        int1 = in;
        ^

I would like to also direct your attention to the setupFinalThings() method. This is an example of a method altering a mutable object which was declared final.  As you can see, we can add new items to the List (or we could have removed them) even though the variable finalThings is final. We can do this outside any constructor because the variable was initialized with a mutable object when it was declared. We could never reassign a new list to the variable but we can modify the list whenever and wherever we like without fear of compile-time errors.

It should be pointed out here that the method getTotal() called in the constructor would have been better declared as a final method as described previously to avoid unexpected results.

"Final"-ly

That about covers most things you would need to know about the Java final keyword. It certainly can be very useful and at times troublesome if you don't pay attention to what you are doing. In the end though, you should be sure to exercise the right to make use of this keyword for its intended purpose.

Friday, January 24, 2014

Struts Framework - Introduction to Struts

General

Struts is a framework from the Apache Software Foundation (www.apache.org) for creating J2EE applications using an MVC (model-view-controller) architecture. It is open-source software that extends the Java Servlet API and the latest evolution of this is in the Apache Struts 2 Framework which was released in February 2007. The original Struts 1.x version has reached end of life and is no longer supported by the Apache Software Foundation.  For purposes of this article, I am limiting the discussion to Struts2.

At the core, as previously mentioned is the need to create applications using the MVC architecture. Figure 1 illustrates, albeit simplistically, the MVC architecture as it is used in Struts2.

Figure 1: Simplistic Struts2 MVC Architecture

Description of Process Flow (refer to Figure 1)

  1. The HTTP servlet request is received from the interaction of the user with the JSP/HTML in their browser.
  2. The Action Mapper passes the request to one or more interceptors.
  3. The Interceptors refine and pass the requested Action to the Model.
  4. The Action then interacts with the database or some external system (possibly via MQ)
  5. The Action passes the completed action to the Result.
  6. The Result response is passed to the Template to generate the output (JSP, JSF, JasperReport, etc)
  7. The templated result is then passed in reverse order through the interceptors it arrived through as an action request.
  8. The HTTP servlet response is sent to the browser for display of the result to the User.