How to use FastMoney in a Spring Web application?

46 views Asked by At

Am creating a dummy money deposit form using spring web. As should be the case, wanted to try the JavaMoney API when dealing with monies. So, the @RequestBody DTO is something like this :

@Data
@Builder
@RequiredArgsConstructor
public class PaymentDto {
    private String recipientName;
    @JsonInclude
    private FastMoney amount;
}

The JSON I am posting from postman has

{"amount": 100.00} //also tried with "100.00"

The error I get is

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.javamoney.moneta.FastMoney` (no Creators, like default constructor, exist): no int/Int-argument constructor/factory method to deserialize from Number value (100)
     at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 2, column: 15] (through reference chain: com.blah.PaymentDto["amount"])

Documentation says FastMoney can be created in a few ways and static constructor is one of them. But this way ties me to use a currency with the amount, which I want to avoid. I can perhaps set the locale in the request, but thats for another time.

FastMoney m = FastMoney.of(200.20, "USD");

The examples I was google are from 11 years ago - so I am assuming JavaMoney is probably not the right API for a typical web application involving payments. So, I will be investing some time to find out if there are other APIs that ease the use of money. Meanwhile, I still wanted to find out how people are actually using JavaMoney - as I can't figure out how FastMoney would work using lombok.

Lombok provides staticConstructor but they are for classes and not fields within the classes.

 @Data(staticConstructor="of")
  public static class Exercise<T> 

So the questions are:

  • How do I use Lombok to set FastMoney fields?
  • How do I convert a (thymeleaf to spring controller) submitted forms value to FastMoney?
1

There are 1 answers

0
sare3th On

I believe the correct way to address your issue is not to rely on Lombok constructors but, instead, to implement a custom Jackson deserializer.

see e.g.

@JsonComponent
public class FastMoneyDeserializer extends JsonDeserializer<FastMoney> {
    @Override
    public FastMoney deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        Integer amount = jsonParser.getIntValue();
        return FastMoney.of(amount, "USD");
    }
}