Showing posts with label Apache. Show all posts
Showing posts with label Apache. Show all posts

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!

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.