thombergs / docx-stamper

Easy-to-use template engine for creating docx documents in Java.
MIT License
213 stars 90 forks source link

Get Error messages during processing programmatically #91

Open t-oster opened 3 years ago

t-oster commented 3 years ago

Hi,

btw great library. During stamping there are some error messages logged like ' Expression ${transaction.desription} could not be resolved against context root of ...'. It would be great if I could intercept those messages and show them to the user, so they can check for typos or other mistakes. Is there a simple possiblity to hook into that logging, or should I provide a pull request? I would suggest somehting like and ErrorHandler Interface handleError(String expression, Object context) and a addErrorHandler(ErrorHandler h) the configuration builder.

dallanmc commented 2 years ago

Did you end up implementing this? I added a DefaultErrorHandler (which implements a new ErrorHandler interface) which can be overridden in the configuration by your own implementation.

The interface has one simple method:

public interface ErrorHandler {
    void handleError(Throwable var1);
}

My own implementation simply takes the exceptions and adds the error messages to a list:

class CustomErrorHandler extends DefaultErrorHandler implements ErrorHandler {

        private List<String> errors = new ArrayList<>();

        @Override
        public void handleError(Throwable throwable) {
            super.handleError(throwable); // calls default implementation which just logs the errors
            errors.add(throwable.getMessage());
        }

        public List<String> getErrors() {
            return errors;
        }
    }

You then add the ErrorHandler as a member variable to the following classes DocxStamperConfiguration sets the ErrorHandler on CommentProcessorRegistry BaseCommentProcessor PlaceHolderReplacer

In some cases the error handler is set by the comment processor.

Anyway, any time you want to handle an error just insert errorHandler.handleError(exception) in the catch block.

I've also added in a new error condition - this is when the contents of the replaceWordWith expression resolves to null. In my use cases, I never want this to resolve to null and for me it's an indication that there is something wrong with the expression, so I do this in the ReplaceWithProcessor:

    @Override
    public void replaceWordWith(String expression) {
        if (expression == null) {
            handleNullError();
        } else if (this.getCurrentRunCoordinates() != null) {
            RunUtil.setText(this.getCurrentRunCoordinates().getRun(), expression);
        }
    }

    private void handleNullError() {
        String errorMessage = String.format(
                "Comment '%s' has resolved to null. Please check the comment syntax",
                CommentUtil.getCommentString(getCurrentCommentWrapper().getComment()));
        handleError(new DocxStamperException(errorMessage)); // calls the ErrorHandler implementation
    }
caring-coder commented 4 weeks ago

Shipped this feature in 2.5 of the office-stamper fork, it should arrive in the maven repos this day or tomorrow. We added an ExceptionResolver interface, settable in OfficeStamperConfiguration class:

interface ExceptionResolver {
     String resolve(Placeholder placeholder, String message, Exception cause);
}

The placeholder is the expression it tried to replace, the message is the library error message, and the cause is the underlying error during resolution.

The String return return value is to let you define a behavior of replacement for those error case. You can decide to wrap one of the three included behaviors in ExceptionResolvers or directly roll your own.