Archive for August, 2009

Sorting an ArrayCollection using SortField

Monday, August 31st, 2009

You can use ArrayCollection and SortField to sort a list of items based on one or more fields:

this.names= new ArrayCollection();
names.addItem({first:"John",last:"Travolta"});
names.addItem({first:"Miguel",last:"Nunes"});
    names.addItem({first:"Christina",last:"Aguilera"});
names.addItem({first:"Michael",last:"Jackson"});
var sort:Sort= new Sort();
sort.fields=[new SortField("last",true,true), new SortField("first",true,true)];
names.sort=sort;
names.refresh();

You can try the adobe flex example here. View source is enabled.

Uploading a file with Flex 3 and Struts 2

Monday, August 31st, 2009

In my previous post I taught you how to upload a file using Struts 2. In the example I gave you, both the presentation layer and the code that received the file were done in Struts 2.
But what if you want to upload a file via Adobe Flex? How can you do it?

The FileReference flex class allows you to upload files from a client to a server. In our case a server running Struts 2. FileReference shows a dialog box that allows the user to select which file to upload.
Enough of theory. Below is an example of the code that you can use to upload a file to a server running struts 2:

Step 1

First you need to create the dialog box that will allow the user to select a file to upload by clicking the button “Browse”.

<mx:VBox width="100%" left="10" top="10" >
   <mx:HBox>
       <mx:Label text="Image to upload:"/> <mx:TextInput disabledColor="black" enabled="false" id="fileName" width="200"  />
              <mx:Button width="80" label="Browse" click="browseFiles()" />
   </mx:HBox>
          <mx:Button id="uploadButton" label="Upload" enabled="false" click="upload()"/>
          <mx:ProgressBar labelPlacement="center"  source="{fileRef}" label="%3%%" minimum="0" maximum="100" color="blue" height="13" width="100" id="progressBar" visible="false" includeInLayout="false" />

        </mx:VBox>

Step 2

Create an object of type FileReference and add event listeners to track progress of the upload:

 fileRef = new FileReference();
 fileRef.addEventListener(Event.COMPLETE, completeEvent);
 fileRef.addEventListener(Event.SELECT, selectEvent);
 fileRef.addEventListener(IOErrorEvent.IO_ERROR, showError);
 fileRef.addEventListener(ProgressEvent.PROGRESS, progressEvent);
 fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, showError);

Step 3

Write the actionscript code that opens a dialog that calls the native “Open File Dialog” in the user’s operating system.

private function browseFiles():void {
      var validFiles:Array= new Array(new FileFilter("Images (*.jpg,*.png,*.gif,*.jpeg)", "*.jpg;*.png;*.gif;*.jpeg"));
      this.fileRef.browse(validFiles);
   }

Step 4

Write the actionscript code that uploads the file to the server.
In our previous example the struts 2 action for the upload is “/fileUpload”.
Therefore we use the following url to upload the file: ${baseUrl}/fileUpload

/**
   * Uploads a file to the server
   *
   */
   private function upload():void {
     mx.controls.Alert.show("Starting upload.");
     var sendVars:URLVariables;
     var request:URLRequest;
     sendVars = new URLVariables();
     request = new URLRequest();
     request.data = sendVars;
     request.url =baseUrl + "/fileUpload";
     request.method = URLRequestMethod.POST;
     fileRef.upload(request,"file",false);
   }

You can find sample code to upload a file here. Note however that the example only works with a server to receive the file.

Uploading a file with Struts 2

Monday, August 31st, 2009

Uploading a file with Struts 2 is really simple with the help of the FileUploadInterceptor. The steps required to upload a file using Struts 2 are:

Step 1

Create the Struts 2 Action class. In our example we have called it FileUploadAction.java

An example of an action to upload a file:

package uk.co.spltech.web.actions;

import com.opensymphony.xwork2.Action;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

/**
 * Uploads a file using Struts 2
 *
 * @author Armindo Cachada
 */
public class FileUploadAction extends ActionSupport {
     private static final long serialVersionUID = 12323232L;
     private File file;
     private String fileFileName;
     private String fileContentType;

 public String execute() {

  return Action.SUCCESS;
 }

 public File getFile() {
        return this.file;
     }

  public void setFile(File file) {
         this.file = file;
      }

  public void setUpload(File file) {
      this.file = file;
   }
 /**
       * This method is called by the action.
       * Here you can do whatever you want with the uploaded file
       */
 public String upload() throws IOException  {
        File uploadedFile =this.getFile();
        // you can do whatever you want with the file
        return Action.SUCCESS;
 }

 public String getFileFileName() {
  return fileFileName;
 }

 public void setFileFileName(String fileFileName) {
  this.fileFileName = fileFileName;
 }

 public String getFileContentType() {
  return fileContentType;
 }

 public void setFileContentType(String fileContentType) {
  this.fileContentType = fileContentType;
 }

 public String getFileUrl() {
  return fileUrl;
 }

 public void setFileUrl(String fileUrl) {
  this.fileUrl = fileUrl;
 }
}

Step 2

Create the action in struts.xml

<action name="fileUpload" class="uk.co.spltech.web.actions.FileUploadAction" method="upload">
 <result>/success.jsp </result>
 <result type="error">/upload.jsp</result>
</action>

Step 3

Create the jsp. For example:

Please select the file you want to upload:

 <s:form action="fileUpload" method="post" enctype="multipart/form-data" theme="simple">
  <s:actionerror cssClass="errorMessage"/>
  <s:fielderror cssClass="error"/>
      <s:file name="upload" label="File"/>
     <s:submit/>
 </s:form>

Step 3

The default maximum file size that struts 2 allows you to upload is only 2 megabytes. You can increase this size by specifying in struts.properties the struts.multipart.maxSize. This value is in bytes.
For example:

struts.multipart.maxSize=20480

Finally you can download the code for this example here.

Note that I didn’t include the required struts2 library files with the example.
The files you need are:

commons-fileupload-1.2.1.jar
commons-io-1.3.2.jar
commons-logging.jar
freemarker-2.3.13.jar
ognl-2.6.11.jar
struts2-core-2.1.6.jar
xwork-2.1.2.jar
struts2-convention-plugin-2.1.6.jar


Click here to learn how to upload a file with Adobe Flex

Configuring JBOSS to support UTF-8 characters in the URL

Monday, August 31st, 2009

The problem I have experienced this week. When I have chinese characters as part of the URL, the characters show up as garbage in the page. I mean request.getParameter(”chineseCharacter”) returns garbage characters. This problem happened in JBOSS 4.2.3 GA with Apache 2.0(mod_jk).

Fortunately the solution is simple:

Edit JBOSS_HOME/server/${SERVER_NAME}/deploy/jboss-web.deployer/server.xml

Add URIEnconding=”UTF-8″ to the HTTP connector and AJP connector:

<Connector port="8080" address="${jboss.bind.address}"
         maxThreads="250" maxHttpHeaderSize="8192"
         emptySessionPath="true" protocol="HTTP/1.1"
         enableLookups="false" redirectPort="8443" acceptCount="100"
         connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/>

   <!-- Define an AJP 1.3 Connector on port 8009 -->
    <Connector port="8009" address="${jboss.bind.address}" protocol="AJP/1.3"
         emptySessionPath="true" enableLookups="false" redirectPort="8443" URIEncoding="UTF-8"/>



Now restart your server and you should have no more problems with having non-latin characters in the URL.

Adding an event listener function with arguments using Actionscript

Monday, August 31st, 2009

This might come handy whenever you can’t use directly mxml and you need to add an event listener function that needs one or more arguments.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="myInitialize()">
 <mx:Script>
  <![CDATA[
   import mx.controls.Alert;

      private function myFunction(arg:String):void {
       mx.controls.Alert.show("Received call with argument=" + arg);
      }

   private function myInitialize():void {
    myButton.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void{
     var someArg:String="an_argument";
     myFunction(someArg);
    });
   }
  ]]>
 </mx:Script>

 <mx:Button id="myButton" label="Click me!"/>
</mx:Application>

See this code in action here

Adobe Flex 3 UI Components Lifecycle

Monday, August 31st, 2009

In adobe flex 3 there are certain events that are called when a component is created.
These events are raised in the following order:

1) preInitialize: This event is raised when the component has just been created but none of the child components exist.

2) initialize: This event is raised after the component and all its children have been created but before any dimensions have been calculated.

3) creationComplete: This even is dispatched after all the component and its children have been created and after all the layout calculations have been performed.

4) applicationComplete: Dispatched after all the components of an application have been successfully created

Events 1) to 3) are dispatched in the order mentioned above for all visible components.
Note however that for components that are not visible on the screen by default, none of these events will be raised. This is because depending on the creation policy the hidden components might not exist yet.
For example in a TabNavigator only the components that are inside the default tab are created because they are visible. If you do change to another non-visible tab then Flex creates the components one by one. In that case the events mentioned above are raised.

We have created a simple example to demonstrate this. The DataGrid shows you a list of the events that have been raised during the lifecycle of the main application window. If you change to the second tab you will see additional entries in the list due to the creation of a Label UI component.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" preinitialize="preInitialise()" initialize="initialise()" applicationComplete="applicationComplete()" creationComplete="creationComplete()" viewSourceURL="srcview/index.html">
 <mx:Script>
  <![CDATA[
   import mx.collections.ArrayCollection;

   [Bindable]
   private var eventsCalled:ArrayCollection=new ArrayCollection();

   public function preInitialise():void {
    eventsCalled.addItem({label:"preInitialise called",event:"preInitialise"});
   }

   public function initialise():void {
    eventsCalled.addItem({label:"initialise called",event:"initialise"});
   }

   public function creationComplete():void {
    eventsCalled.addItem({label:"creation complete called",event:"creationComplete"});
   }

   public function applicationComplete():void {
    eventsCalled.addItem("applicationComplete called");
   }

  ]]>
 </mx:Script>
<mx:TabNavigator width="400" height="400">
  <mx:Canvas label="tab1">
   <mx:DataGrid id="datagrid" dataProvider="{eventsCalled}" top="10" left="10" width="300" />
  </mx:Canvas>
  <mx:Canvas label="tab2">
   <mx:Label text="This label is created only when it is displayed" creationComplete="creationComplete();" preinitialize="preInitialise();"  initialize="initialise();" />
  </mx:Canvas>

 </mx:TabNavigator>
</mx:Application>

To see this example in action click: here

You can change this behavior by setting the creationPolicy attribute, for example in the application mxml node. This attribute is only valid for containers.

There are 4 possible values for this attribute:

1) creationPolicy=”auto” – the container delays creating some or all of its descendants until they are needed. This is known as deferred instantiation

2) creationPolicy=”all” – the container immediately creates all its descendants even if they are not selected.

3) creationPolicy=”queued” – all components inside a container are added to a creation queue. The application waits until all children of a container are created before moving to the next container.

4. creationPolicy=”none” – all components inside a container are never created. Whoever decides to go with this strategy needs to manually create all items inside a container.

For example to change the behavior seen above we could set the creationPolicy=”all”:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationPolicy="all" preinitialize="preInitialise()" initialize="initialise()" applicationComplete="applicationComplete()" creationComplete="creationComplete()" viewSourceURL="srcview/index.html">
...
</mx:Application>


SEO Urls/Hierarchical Actions with struts 2.1

Monday, August 31st, 2009

I have added a working struts 2.1 project that gives you a working example on how to create SEO optimised urls for struts 2.1. You can find the previous post here.

Minifying CSS and JS with Yahoo YUI Compressor

Monday, August 31st, 2009

In my previous blog post I explained how to use Ant to concatenate javascript and css files in a way to minimize the number of http requests.
Another recommendation by yahoo for building high performance websites is to minify JS and CSS files. The reasoning is that the smaller the size of the javascript/css, the less time it takes for them to be interpreted.

Yahoo provides a great utility – yahoo yui compressor that minifies both javascript and css.

We can therefore improve our build script and add the following task:

<!-- this compresses all the css and js in the static folder -->
        <target name="js.minify">
                <property
                    name="yui-compressor.jar"
                    location="lib/yuicompressor-2.4.2.jar" />
                <property
                    name="yui-compressor-ant-task.jar"
                    location="lib/yui-compressor-ant-task-0.3.jar" />

                <path id="task.classpath">
                  <pathelement location="${yui-compressor.jar}" />
                  <pathelement location="${yui-compressor-ant-task.jar}" />
                </path>

                <taskdef
                    name="yui-compressor"
                    classname="net.noha.tools.ant.yuicompressor.tasks.YuiCompressorTask">

                  <classpath refid="task.classpath"/>
                </taskdef>

           <yui-compressor warn="false" charset="UTF-8" jsSuffix="-min.js" cssSuffix="-min.css" fromdir="${build.dir}/static" todir="${build.dir}/static">
           <include name="**/*.js" />
           <include name="**/*.css" />
       </yui-compressor>

                  <move todir="${build.dir}/static" includeemptydirs="false">
                    <fileset dir="${build.dir}/static">
                                <include name="**/*-min.css"/>
                    </fileset>
                    <mapper type="glob" from="*-min.css" to="*.css"/>
                  </move>
                  <move todir="${build.dir}/static" includeemptydirs="false">
                    <fileset dir="${build.dir}/static">
                                <include name="**/*-min.js"/>
                    </fileset>
                    <mapper type="glob" from="*-min.js" to="*.js"/>
                  </move>

        </target>

First we copy all the javascript and css files to the build/static folder and then we use yahoo compressor to minify all the files in this directory.


Click here to download an example.

Minimizing number of http requests by concatenating all the CSS and Javascript files

Monday, August 31st, 2009

If you have installed yslow in your browser you will know all about yahoo’s high performance rules for a website. One of the most important rules is to minimize the number of http requests. There are several ways of doing that. I will cover one of them in this post – minimizing the number of http requests by concatenating all the javascript files and css files into two big files.

Apache Ant makes the task of concatenating files together extremely easy by using concat.

<concat destfile="${build.dir}/concatenated.js">
        <filelist dir="${src.dir}/js"
           files="one.js, two.js"/>
</concat>

This is a simple solution but I chose not to use it for the following reasons:

1. I don’t always want every single javascript/css to be included for all pages.
You could create multiple concatenated files with different combinations but that would be too messy.

2. We are creating a dependency between the jsps and the ant build script. Do you really want to do that?

3. Javascript, css can be notoriously difficult to debug, so for development purposes
it is useful not to do any concatenation.

Ant has a neat feature that allows to do string replacement on any file by using a filterset.

<copy file="${build.dir}/version.txt" toFile="${dist.dir}/version.txt">
 <filterset>
   <filter token="DATE" value="whatever"/>
 </filterset>
</copy>

You can specify the string that you want to be replaced at build time by surrounding it with ampersands. So in the template jsps instead of including javascripts/css in the normal way, I did the following:

@IncludeCSS css/file1.css css/file2.css ...@
...
@IncludeJS js/jquery.js js/thickbox.js js/vmSlider.js js/blockUI.js@

Then I created the following ant task:

<ExtendedFileTransform concatenate="true"  propertiesfile="${build.dir}/static.mapping.properties" >
  <jspfileset refid="jspFileset">
  </jspfileset>
  <staticfileset dir="${static_content.dir}">
 <include name="**/*.js" />
 <include name="**/*.css" />
 <include name="**/*.png" />
 <include name="**/*.jpg" />
 <include name="**/*.jpeg" />
 <include name="**/*.gif" />
 <include name="**/*.PNG" />
 <include name="**/*.JPG" />
 <include name="**/*.GIF" />
  </staticfileset>
</ExtendedFileTransform>

ExtendedFileTransform is a custom task I created, based on Julien Lecombte’s File Transform.
This custom task inspects all the jsps and searches for javascript(IncludeJS) and css includes(IncludeCSS). If concatenated=”true” we concatenate the files specified within the IncludeXXX directory and we replace it with a valid html javascript/css include to the generated files. If concatenated=”false”, i.e. for development, there is no concatenation and the IncludeXXX directory is replaced with an include for each javascript/css file.

The full ant target that you could use for production looks like this:

<target name="-copy.static.files-prod">
        <taskdef name="ExtendedFileTransform" classname="uk.co.simpletech.ant.ExtendedFileTransform" classpath="${build.dir}/classes" />

        <mkdir dir="${build.dir}/staticpre" />

        <!-- we copy all jsp files to a temporary location -->
        <copy todir="${build.dir}/jsppre">
            <fileset dir="jsp" includes="**/*" />
        </copy>

        <fileset dir="${build.dir}/jsppre" id="jspFileset">
            <include name="**/*.jsp" />
        </fileset>
        <!-- we concatenate the files together -->

        <ExtendedFileTransform concatenate="true">
        <jspfileset refid="jspFileset">
            </jspfileset>
            <staticfileset dir="${build.dir}/static">
                <include name="**/*.js" />
                <include name="**/*.css" />
            </staticfileset>
        </ExtendedFileTransform>

        <delete dir="${build.dir}/jsppre" />=
    </target>

Here is an example project where you can see the css/js concatenation in action.

Case insensitive search in hibernate

Monday, August 31st, 2009

It is very simple to do case insensitive search in hibernate.
Here is an example HQL query:

Query q = this.entityManager.createQuery("SELECT * FROM User u where lower(u.firstName)=:firstName");
q.setParameter("firstName", firstName.toLowerCase());

In this case lower() will convert the firstName property to lower case allowing you to do case insensitive search.