Summary: Attacker sends a malformed Content-Type header on file upload, which throws an exception due to the Content-Type being unknown. But, in the exception text is the direct, unsanitized user input from the header.
There is not a specific text localization handler for struts.messages.upload.error.InvalidContentTypeException, so a generic exception handler ends up being used to process the exception. This generic handler turns out to parse the unsanitized user input as OGNL markup, running the attacker code when processing the exception text.
Some effort is made to blacklist loading other Java libraries in the text rendering context, however it was easily defeated by emptying the blacklist in the attacking code before calling the blacklisted modules.