Tuesday, October 5, 2010

Differentiating objects in Java

Use System.identityHashCode(obj) to differentiate objects in java

Wednesday, September 22, 2010

Use JSTL's "c:out" instead of ${} for display

JSTL has a tag called "c:out" which allows variables to be dumped to the screen. Here is an exmaple:

<c:out value="${aUrl}" />

But many people often ask why not use the less verbose method as follows:

${aUrl}

Although ${} is much simpler, there are many reasons for using c:out instead. One of the main reasons is escaping of HTML characters. If the variable holds a string that contains tags such as
<div> , then the browser will read it as a tag and screw up the layout of your page.

For a list of what gets escaped click here.

Escaping of user input is very important for security reasons. Recently, there has been an article on the net about how Twitter was hacked by "Javascript Injection". Here is one of the articles:

http://blog.trendmicro.com/twitter-mouseover-flaw-allows-script-injection/

Bascially, the problem for Twitter was that they were not escaping user input when displaying links. Had they used something similar to JSTL's c:out tag, then they would have been protected.

Tuesday, September 14, 2010

spring 3 mvc annotation-driven with DWR annotations

I am currently working on a new project that uses Spring 3 MVC Annotation-driven model. I had used DWR on previous projects successfully, but without using annotations, and relying on XML configuration.

After having played around with Spring's annotation driven model, I found it much easier than it's XML counterpart, and so I was determined to get DWR working in the same manner.

mvc-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
    
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
       http://www.directwebremoting.org/schema/spring-dwr
       http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd">


    
    <!-- ================================== DWR configurations ===================================== -->    
    <dwr:configuration>
        <dwr:convert type="bean" class="podd.apn.tab.FacsImportStatus" />    
    </dwr:configuration>
    <dwr:annotation-config />
    <dwr:url-mapping />
    <dwr:controller id="dwrController" debug="true" />    
    
    <!-- Configures the @Controller programming model -->
    <mvc:annotation-driven />

    <!-- Forwards requests to the "/" resource to the "welcome" view -->
    <mvc:view-controller path="/" view-name="welcome"/>
    <!-- 
    <mvc:view-controller path="/*" />
     -->    

    <!-- Configures Handler Interceptors -->    
    <mvc:interceptors>
        <!-- Changes the locale when a 'locale' request parameter is sent; e.g. /?locale=de -->
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
    </mvc:interceptors>

    <!-- Saves a locale change using a cookie -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />

    <!-- Resolves view names to protected .jsp resources within the /WEB-INF/views directory -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>



    

</beans>


web.xml
  <!-- =============
      SERVLETS
   ============  -->
  <servlet>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
                /WEB-INF/spring/app-config.xml
            </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  
    <servlet>
        <servlet-name>uploadServlet</servlet-name>
        <servlet-class>podd.apn.servlet.UploadServlet</servlet-class>
    </servlet>

    <!-- =================
        SERVLET MAPPINGS
     ================  -->
  <servlet-mapping>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <url-pattern>/spring/*</url-pattern>
  </servlet-mapping>
  
  <!--  DWR -->
  <servlet-mapping>
    <servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
    <url-pattern>/dwr/*</url-pattern>
  </servlet-mapping>


And then to verify that it DWR is integrated correctly you can visit:

http://localhost:8989/podd-apn/dwr/engine.js

Referneces:

http://www.codercorp.com/blog/spring/configuring-dwr-30-with-spring-using-annotations.html

Sunday, August 15, 2010

Caused by: java.lang.Error: This version of SLF4J requires log4j version 1.2.12 or later.

I recently synched up to a project to make a new build and upon deployment I encountered a frustrating error:

Caused by: java.lang.Error: This version of SLF4J requires log4j version 1.2.12 or later.

This issue was a real pain, because the error message was very misleading. Basically, the error message is complaining that I don't have a log4j version 1.2.12 or greater.

I checked my classpath, performed a cleaned build, cleared my tomcat cache and restarted tomcat, and none of them fixed the issue. Indeed, my log4j version 1.2.14!!

Bah, I started to dig deeper into the issue and it boiled down to this:

I had replace

        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.5.0</version>
        </dependency>


With:

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.5.6</version>
    </dependency>     
                        
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.5.6</version>
    </dependency>   

I hope this saves somebody else hours of pain

Tuesday, August 10, 2010

Customizing swfupload

After playing around with swfupload, there were a few customizations I needed to make.

1) I wanted to add the files to the user's session.
2) After uploading has completed, by default, swfupload will remove all the items. I wanted to keep the listed items so that the user can review which files were uploaded if they needed to.

Adding to the user session

Since swfupload uses Flash as the underlying mechanism for uploads, the behaviour for executing flash is different for each browser. It turns out Firefox opens a new process and a new cookie for performing the upload as noted in this article:

http://www.thanksmister.com/index.php/archive/firefox-flex-urlrequest-and-sessions-issue/ 

So to work around the issue, the jsessionid was explicity passed into the URL of the upload. With the jsessionid in the URL, Tomcat was able to attach the session to the request.

Here's another article the describes the problem in more detail:
http://blogs.bigfish.tv/adam/2008/04/01/cakephp-12-sessions-and-swfupload/

Below is the code for adding the jsessionid:


function createSwfUpload(fieldName, sessionId,swfUploadUrl, swfButtonUrl, swfButtonPlaceHolderId, swfFlashUrl, progressTarget, buttonCancelId) {
    
    var uploadUrlSession = swfUploadUrl+";jsessionid="+sessionId;
    
    var swfUpload = new SWFUpload({
        
        // The name of the field name that the files are attached to
        file_post_name : fieldName,
        
        // Backend Settings
        upload_url: uploadUrlSession,
        post_params: {"JSESSIONID" : sessionId},

        // File Upload Settings
        file_size_limit : "102400",    // 100MB
        file_types : "*.*",
        file_types_description : "All Files",
        file_upload_limit : "100",
        file_queue_limit : "0",

        // Event Handler Settings (all my handlers are in the Handler.js file)
        file_dialog_start_handler : fileDialogStart,
        file_queued_handler : fileQueued,
        file_queue_error_handler : fileQueueError,
        file_dialog_complete_handler : fileDialogComplete,
        upload_start_handler : uploadStart,
        upload_progress_handler : uploadProgress,
        upload_error_handler : uploadError,
        upload_success_handler : uploadSuccess,
        upload_complete_handler : uploadComplete,

        // Button Settings
        button_image_url : swfButtonUrl,
        button_placeholder_id : swfButtonPlaceHolderId,
        button_width: 61,
        button_height: 22,
        
        // Flash Settings
        flash_url : swfFlashUrl,
        

        custom_settings : {
            progressTarget : progressTarget,
            cancelButtonId : buttonCancelId
        },
        
        // Debug Settings
        debug: false
    });    
    
    return swfUpload;
    
}

Keep list of Uploaded Items

After the upload completes, swfupload automatically hides the progress results. I wanted our users to review which files got uploaded if they needed to. Surprisingly, there was no easy way to configure this. This is what I meant in my other post that swfupload was a bit clunky, but at least it works compared to the "uploadify" alternative. To make the change I commented out some of the code in the fileprogress.js file:

FileProgress.prototype.setError = function () {
    this.fileProgressElement.className = "progressContainer red";
    this.fileProgressElement.childNodes[3].className = "progressBarError";
    this.fileProgressElement.childNodes[3].style.width = "";

    // COMMENT OUT TO STOP REMOVING UPLOAD RESULT
    //var oSelf = this;
    //this.setTimer(setTimeout(function () {
    //    oSelf.disappear();
    //}, 5000));};

Reference: http://www.swfupload.org/forum/generaldiscussion/2123

Multiple file uploads

I've recently been faced with a project where a client needs to be able to upload multiple files in a form submission. I've faced this problem before and there have been many solutions:

One of the older solutions was to expect that the user would ZIP up all the files so that we effectively convert a multiple file problem to a single file. While this did work, it relied on the user to know how to ZIP up files and expect them to perform an extra step of zipping up the files. Not so elegant.

Another solution, is to use a Java applet. The con of using this implementation is that users are expected to have Java already installed on their system. This is a barrier since not all computers will have them installed. The advantage is that once it is installed, then works regardless of what browser is being used.

Flash uploader has recently been popularized by several websites which include Youtube, Flickr and Facebook. Because of this websites, many users will already have flash installed and therefore is less of a barrier. One of the disadvantages is that behaviour of Flash can be different across browsers and different versions of Flash can behave differently as we will soon see.

Many of my users are not very comfortable with using computers, and many of them will only use a computer when they have to. That being said, having to install something on their computer would seem to be a daunting task. Therefore I decided to go with Flash because most people will already have it installed.

At first I went with a utility called "Uploadify" which can be found here:

http://www.uploadify.com/

What I liked about this solution was that it was very elegant and easy to use. But I learned very quickly, that it just didn't work. It was broken for the latest flash version (version 10) and had very little support. It's been noted on their bug list from so many people, but none of the developers acknowledged any plans to fix it.

http://www.uploadify.com/forum/viewtopic.php?f=4&t=5627

I went to look for another solution that was actively being maintained. I stumbled upon "SwfUpload" found here:

http://code.google.com/p/swfupload/

The coding wasn't as elegant as Uploadify, but at least it worked, and it worked across all major browsers. The Javascript coding is a bit clunky, but once you have it up and running, it works great.

For those of you looking at comparing other solutions heres a good reference website:

http://qubit-toolkit.org/wiki/index.php?title=Multiple_file_upload

Wednesday, July 28, 2010

Cygwin: less reports WARNING: terminal is not fully functional

I have been using the "less" command Cygwin without problems for almost a year. For a new project I needed to have perl installed so I downloaed "Strawberry Perl" and installed it.

Afterwards, in cygwin everytime I tried to issue the "less" command it complained that the "terminal is not fully functional".

Turns out Strawberry perl was adding the environment variable TERM with a value of dumb.
Deleting the TERM fixed the issue.