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