pioto
pioto

Reputation: 2582

How do I return user-friendly errors from org.springframework.format.Formatter?

I have a few entities which relate to each other in my application, and there are forms where users can set up these relationships. For a simple example, I'll use the concept of a "parent ticket":

@Entity
public class Ticket {
    @Id
    @GeneratedValue
    Integer id;

    @ManyToOne
    private Ticket parentTicket;

    // ...
}

Elsewhere, I've defined a Formatter for my Ticket class:

@Component
public class TicketFormatter implements Formatter<Ticket> {
    // ...

    @Override
    public String print(Ticket object, Locale locale) {
        return object.getId().toString();
    }

    @Override
    public Ticket parse(String text, Locale locale) throws ParseException {
        try {
            return ticketService.getTicket(Integer.valueOf(text));
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid ticket #"+text, e);
        }
    }
}

Finally, my form has, more or less:

<label for="parentTicket">Parent Ticket:</label>
<input type="text" name="parentTicket" id="parentTicket"/>

I'd expect that the user would enter the ID number of the ticket to link, and that a blank entry would be treated as null.

So, I'd hope that the validation error shown on my form would be "Invalid ticket #[blah]", but instead, I basically get a whole long stack trace...

What's the right way to handle this? Do I need to implement a separate Validator and apply that to my parentTicket field? But, wouldn't that validate the Ticket, and not the String my formatter is failing on? How do I work out this seeming chicken-and-egg problem?

Upvotes: 2

Views: 100

Answers (1)

pioto
pioto

Reputation: 2582

Here's the best solution I've come across so far: Customize Spring Error Message

Basically, I just had to set up a MessageSource:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="/WEB-INF/messages/messages"/>
</bean>

Then set some properties in /WEB-INF/messages/messages.properties, like:

typeMismatch.com.example.domain.Ticket=is not a valid ticket number

And then that gets shown as the error message.

You can see more about how this works by inspecting the BindingResult object Spring MVC gives you, to find the "error codes". This uses DefaultMessageCodesResolver by default.

Upvotes: 1

Related Questions