Friday, September 03, 2010

JPivot/Mondrian + Struts 1.x file upload issue

After we integrated JPivot (front-end for Mondrian) library in one of our Struts 1.x based web application, all file uploads working fine so far, started to fail with NullPointerException (NPE). JPivot request filter is configured to intercept all requests for action (e.g. *.do). I could not find direct discussion about this issue on Google.

After debugging for few hours myself, noticed that JPivot RequestFilter intercepts and consumes the HTTP multipart request stream through a MultipartEnabledRequest wrapper even before it reaches Struts controller. Therefore FormFile object is null in FormBean.

The simple solution that worked was to extend the JPivot RequestFilter class and override doFilter(), something like shown below and use this custom filter in place of default JPivot RequestFilter.

...
import com.tonbeller.wcf.controller.RequestFilter;

/**
* This extension modifies default behavior of JPivot controller for file uploads
* (multipart requests) . It allows Struts layer to handle such requests rather
* than processing itself.
*
* @author bjha
*/
public class MyJpivotFilter extends RequestFilter {

@Override
public final void doFilter(
ServletRequest req,
ServletResponse res,
FilterChain fc) throws IOException, ServletException {


if( isMultipartRequest( req ) ){
//let Struts handle upload
fc.doFilter(req, res);
return;
}

super.doFilter(req, res, fc);
}


static boolean isMultipartRequest(ServletRequest req) {

if (req instanceof HttpServletRequest) {

String reqMethod = ((HttpServletRequest) req).getMethod();

if ( reqMethod != null
&&
"post".equals(reqMethod.toLowerCase())) {

String content = req.getContentType();
return (
content != null
&&
content.toLowerCase().contains("multipart/form-data"));
}
}

return false;
}
}


Another option that could work would be to configure JPivot RequestFilter not to intercept requests for upload URIs via web.xml or use commons-fileupload library to handle uploads.