Wednesday, December 12, 2012

PowerMock no last call on a mock available

Seems like every other time I write unit tests with PowerMock I run into this error "IllegalStateException: no last call on a mock available" What it should read is "Hey! You forgot to include in the PrepareForTest attribute a class that is used statically and was mocked with the MockStatic function"
At least that's always the reason I see that error.

Feel free to let me know if there are other reasons it pops up.


Wednesday, December 5, 2012

Race Condition

I have this weird problem where two separate users upload a picture to my web service and user1 see's user2's error messages. Reviewing the code nothing sticks out to me, so I would like to ask what is wrong with this code and why was it creating this condition where errors for user2 would be visible to user1?

Here is some simplified code to try and demonstrate the situation.

    public class SomeService {
       
        private static SomeService service;
        private SomeService() {
        }
       
        public static SomeService getInstance() {
            if(service == null) {
               service = new SomeService();
            }
        }
   
        public ErrorStatus doSomething(ErrorStatus es) {
           
            es = new ErrorStatus(es);
            // stuff happens that causes an error
            es.addMessage(new ErrorMessage("some error happened"));
            return es;
        }
       
        public ErrorStatus doSomethingElse(ErrorStatus es) {
           
            es = new ErrorStatus(es);
            // stuff happens that causes an error
            es.addMessage(new ErrorMessage("some different error happened"));
            return es;
        }
    }
   
    public class ErrorMessage {
        String message;

        //simple constructor, getters and setters, nothing interesting
    }
   
    public class ErrorStatus {
        int id;
        String status;
        List<ErrorMessage> messages;

        public ErrorStatus() {
             id = 0;
             status = "";
             messages = new ArrayList<>();
        }

        public ErrorStatus(ErrorStatus other) {
            id = other.getId();
            status = other.getStatus();
            messages = other.getMessages();
        }
       
        public void addMessage(ErrorMessage message) {
       
            //data checks
            messages.add(message);
        }
       
        //getters and setters
    }   
   
    public class UploadServlet extends HttpServlet {
       
        public doGet(request, response) {
           
            ErrorStatus es = new ErrorStatus();
            SomeService service = SomeService.getInstance();
           
            es = service.doSomething(es);
           
            es = service.doSomethingElse(es);
           
            printErrors(response.getWriter(), es);
           
        }
               
        public void printErrors(PrintWriter pw, ErrorStatus es) {
           
            for(int i = 0; i < es.getMessages().size(); i++) {
               
                pw.write(es.getMessages().get(i).getMessage());
            }
        }
    }

The two places in the code I think something weird could be happening is the copy constructor or the fact that the service is a singleton. Maybe I'm not copying the list correctly, or maybe the service being a singleton changes how the stack and heap are used, I'm really not sure. From my understanding of how the stack, heap, singletons and servlets work one users data would never be affected by another users data.
Also they only part of this that ever had problems was the list, the primitive data was always correct, only the list of errors was ever showing up for the wrong user.

I should note, I have solved the problem I just don't understand why it was a problem. The solution was to stop using the copy constructor and to just let the ErrorStatus object get modified in the doSomething and doSomethingElse methods. So the revised code would have a void return type for doSomething and would just call es.addMessage, also the copy constructor was deleted from ErrorStatus.

Any help understanding why this caused a race condition would be appreciated.

I'll update this post once I find the answer to why this was a problem.

Update 1/8/13:
So in my spare time I tried to reproduce the error programmatically, I wrote a multithreaded test program which would run the code thousands of times, unfortunately I couldn't reproduce the race condition. As I have more spare time I might try a few more things but I'm beginning to think there was something more going on that I didn't include when I simplified the process to post here.

Monday, November 5, 2012

Java's Jimi pro library

So a few months ago I was asked to add the ability to our web app to allow tiff files to be uploaded. I'm not familiar with all the caveates of images and the Java language but apparently there are a few formats that aren't allowed by default, one of them being TIFF. So I had to find an open source library to facilitate uploading TIFF images. I looked into a few and by far the easiest to use and incorporate into our app was JimiPro. It's one jar file and only one command for most cases. Simple enough. I included the jar and started using the Jimi.getImage method and got everything working just the way we needed.
Six months later.... Web Ops tells my boss they are noticing something very strange, the servers crash every few weeks because too many threads are running. So being the go to guy for all the strange issues I started looking into this. Luckily a thread dump gave us a starting point somewhere in the Jimi library. So I dove in and found that the getImage call in one of the three places I used it was creating a waiting thread that never got notified. With some direction from my boss I started looking into why only one of the three didn't work. Turns out when you use getImage you need to force it to recognize all the pixels were loaded and that it should stop. One easy way to do that is to create an ImageIcon and call getImage on it. So adding one simple line 'new ImageIcon(image).getImage()' solved my problem and got the waiting thread to stop waiting.

Gotta love those handy undocumented 'features' that cause your whole system to crash!

Friday, October 26, 2012

jQuery, ajax and click functions that don't work

So the issue today dealt with a page that uses jQuery to turn a selection box into a drop down multi select box. Check it out here it's a pretty nice plugin.
Anyway, I populate the page with my data, create the drop down and then when the drop down changes the page makes an Ajax request to reload the page with new data. The problem was that when the page reloaded the items in the drop down didn't work the same. each item consists of a label and a checkbox. The checkbox still worked fine the problem was that now if you clicked on the label it wouldn't select the checkbox. After some research I found there is a pretty common problem with Ajax and jQuery where the dynamically assigned functions stop working after an Ajax call. I set some break points in the javascript and verified that wasn't my problem, the functions to check the box when you click the label were still working. With some help from a co-worker we found that the plugin was creating a hidden div on the page and when I made the Ajax call that div was getting created a second, third fourth... time on the page. So a simple remove before making the Ajax call solved my problem and got the labels working again.

Tuesday, October 23, 2012

Character encoding, java, javascript and tomcat

Today my main issue has been with character encoding. This seems to pop up every couple of months and I either learn something new or deal with the same thing all over again. This time I learned a few things that were new.

The Setup: Users are allowed to type in custom tags for photos in the app I'm working on, so QA tested every character we might care about which revealed a few major problems. We allow the user to filter the photos by these tags. The filter sends the tags over a GET request to the server, the server parses the request and builds a new photos page with only those photos that match the selected tags.

The Issue: The app is older and foreign language support is new, so we constantly find places in the app where foreign characters don't work or cause strange problems. So when the javascript sent these foreign characters as a GET request they were getting converted to something other than UTF-8 when I tried to get them from the request as a parameter. 
When the request arrived at the server the characters would get converted wrong again by tomcat, and then when the information about a photo is retrieved from the database some of those foreign characters were HTML encoded before getting saved in the database.

The Solutions:
First off, I made sure each jsp contained the following line:
<%@ page contentType= "text/html; charset=UTF-8" pageEncoding="UTF-8" %>
This fixed the problem with the javascript sending the characters in the wrong format.
Second I made sure the Tomcat server.xml contained the following line:
<?xml version="1.0" encoding="UTF-8"?>
This didn't fix anything but was something I read should be done anyway to ensure we support UTF-8.
Third, in the java code I made sure to use StringEscapeUtils.unescapeHtml when retrieving the photo tags from the database.
Finally, I couldn't use the HttpServletRequest.getParameter function because tomcat was doing something to the strings before returning them. From what I read, step two above was supposed to help with that but isn't a guarantee. The best thing to do is use the getQueryString() function and decode the string yourself. So I did that and used URLDecoder.decode(string, "UTF-8") and finally got the tags from the GET request in the correct format.

These steps combined got the tags into a regular readable format instead of those annoying ? symbols. Once the tags were in the right format all my other code started working correctly.