Spring annotations and Javac debug mode

Today while preparing my Spring MVC based module for release, I faced some weird issues. My perfectly working module suddenly started giving errors which I had never encountered before. After spending a lot of time on this, I finally found that the issue was with the way I was using Spring annotations.

For an example, consider the following code snippet:

@RequestMapping(value = "/images/{imageType}", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<byte[]> getImage (
     @RequestParam(value = "id") String imageId,
     @PathVariable String imageType)  {

     //Some processing logic

     return new ResponseEntity<byte[]>(imageData, headers, HttpStatus.OK);
}

In this method, Spring creates following two variable  mappings:

  1. “id” from query parameter to imageId variable based on explicitly specified parameter name.
  2. “imageType” data from URL to “imageType” variable based on variable name as no explicit parameter name is specified.

This snippet, when compiled with a debug option “-g”, works perfectly but when compiled with a debug option “-g:none” (release mode), it stops working and gives an error saying,

java.lang.IllegalArgumentException: Name for argument type [java.lang.String] 
not available, and parameter name information not found in class file either.

When debug option “-g” is used, code is compiled in such a way that the complete debug information is preserved. So, all the variable names are kept as it is.

But with debug option “-g:none” option, no debug information is maintained in the byte-code and names of all the variables are modified. This modification of variable names leads to a problem for Spring when it tries to execute the above method. In the above method, on compilation, variable “imageType” gets converted to something like “paramString2” which leads to the above mentioned error.

The solution for this issue is to provide enough information to Spring so that it should be able to map the data to the required variable without depending on its name. Following is the correct code snippet which works perfectly with both debug options:

@RequestMapping(value = "/images/{imageType}", method = RequestMethod.GET)
public @ResponseBody ResponseEntity<byte[]> getImage (
     @RequestParam(value = "id") String imageId,
     @PathVariable(value = "imageType") String imageType)  {

     //Some processing logic

     return new ResponseEntity<byte[]>(imageData, headers, HttpStatus.OK);
}

So, while using Spring annotations, developers should provide complete information about the mapping in order to avoid this kind of hard-to-debug issues.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s