Add an Attachment Validation Step

Last modified by Eleni Cojocariu on 2026/10/05 20:19

Steps

Ship a jar extension holding one component to add a check of your own to the attachment validation chain.

  1. Implement AttachmentValidationStep as a singleton component with a hint of your own. The wrapper is everything the step is given: getSize(), getFileName() and getInputStream().
    @Component
    @Singleton
    @Named("empty")
    public class EmptyAttachmentValidationStep implements AttachmentValidationStep
    {
        @Override
        public void validate(AttachmentAccessWrapper wrapper) throws AttachmentValidationException
        {
            // Refuse the attachment here.
        }
    }
  2. Refuse an attachment by throwing an AttachmentValidationException with its four payload fields filled in. A bare message gets the reader an untranslated rejection under the wrong status.
    if (wrapper.getSize() == 0) {
        throw new AttachmentValidationException(
            String.format("Empty file [%s]", wrapper.getFileName()),
            Response.Status.BAD_REQUEST.getStatusCode(),
            "myextension.validation.empty.rejected",
            List.of(wrapper.getFileName()),
            "fileuploadisempty");
    }
  3. Declare the component in the module's META-INF/components.txt, one fully qualified class name per line and nothing else. The step then runs after the shipped size and mimetype steps, in an order you do not control.
    com.example.attachment.EmptyAttachmentValidationStep
  4. Write the message of that translation key in ApplicationResources.properties, at the root of the jar, where XWiki picks it up with no declaration of its own. Numbered placeholders take the parameters passed to the exception, in order.
    myextension.validation.empty.rejected=The file {0} is empty. Please select another one.
  5. Install the extension and attach an empty file: the upload is refused and your message is shown in place of the attachment. The same upload sent over REST answers the status you chose and the key for the client to translate.
    HTTP/1.1 400 Bad Request
    Content-Type: application/json
    
    {"message": "Empty file [notes.txt]",
     "translationKey": "myextension.validation.empty.rejected",
     "translationParameters": ["notes.txt"]}

Related

Get Connected