Hello stackoverflow experts
I have the following InvoiceItem Class which has monetary Amounts
import jakarta.json.bind.annotation.JsonbProperty;
import jakarta.json.bind.annotation.JsonbTypeSerializer;
import jakarta.json.bind.serializer.JsonbSerializer;
import jakarta.json.bind.serializer.SerializationContext;
import jakarta.json.stream.JsonGenerator;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.eclipse.persistence.annotations.UuidGenerator;
import org.javamoney.moneta.FastMoney;
@Entity
@UuidGenerator(name = "INVOICE_ITEM_GEN")
@Table(name = "invoice_items")
public class InvoiceItem {
@Getter
@Setter
@jakarta.persistence.Id
@JsonbProperty("id")
@GeneratedValue(generator = "INVOICE_ITEM_GEN")
private String Id;
@Getter
@Setter
@Column(name = "name")
@JsonbProperty("name")
private String Name;
@Getter
@Setter
@Convert(converter = PersistentFastMoney.class)
@Column(name = "price")
@JsonbProperty("price")
private FastMoney Price;
public InvoiceItem() {
}
public InvoiceItem(String name, String price) {
this.setName(name);
this.setPrice(FastMoney.parse(price));
}
}
I generate this sucessfully in my function from a different input.
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/invoices")
public class InvoiceSystem {
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Invoice CreateNewInvoice(InvoiceInput input) {
var invoice = new Invoice();
invoice.setCreditor(new InvoiceParty());
for (var item: input.getItems()) {
invoice.Items.add(item.toInvoiceItem());
}
return invoice;
}
}
the toInvoiceItem uses the Contructor of InvoiceItem with two string parameters. Now I want to print the Class as JSON back to the Consumer after it has been created.
But this fails with
<body><h1>HTTP Status 500 - Internal Server Error</h1>
<hr/>
<p><b>type</b> Exception report</p>
<p><b>message</b>Internal Server Error</p>
<p><b>description</b>The server encountered an internal error that prevented it from fulfilling this request.</p>
<p><b>exception</b>
<pre>javax.servlet.ServletException: javax.json.bind.JsonbException: Unable to serialize property 'Items' from com.openflowlabs.faktura.Invoice</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'Items' from com.openflowlabs.faktura.Invoice</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'price' from com.openflowlabs.faktura.InvoiceItem</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'context' from org.javamoney.moneta.FastMoney</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'amountType' from javax.money.MonetaryContext</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'annotatedInterfaces' from java.lang.Class</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Unable to serialize property 'annotatedOwnerType' from sun.reflect.annotation.AnnotatedTypeFactory.AnnotatedTypeBaseImpl</pre>
</p><p><b>root cause</b>
<pre>javax.json.bind.JsonbException: Error getting value on: javax.money.MonetaryAmount</pre>
</p><p><b>root cause</b>
<pre>java.lang.IllegalAccessException: class org.eclipse.yasson.internal.model.ReflectionPropagation cannot access class sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl (in module java.base) because module java.base does not export sun.reflect.annotation to unnamed module @50c1e8e3</pre>
</p><p><b>note</b> <u>The full stack traces of the exception and its root causes are available in the Payara Server
5.2022.1 #badassfish logs.</u></p>
<hr/>
<h3>Payara Server 5.2022.1 #badassfish</h3></body>
I know I need a Custom Serializer, but I tried for a day every possible way to make one but my App simply wont eat the Annotation
How do I make a Custom serializer for the org.javamoney.moneta.FastMoney Class so that I can simply annotate all fields that have this class with @JsonbTypeSerializer(FastMoneySerializer.class) like for example Invoice Item
@Getter
@Setter
@Convert(converter = PersistentFastMoney.class)
@Column(name = "price")
@JsonbProperty("price")
@JsonbTypeSerializer(FastMoneySerializer.class)
private FastMoney Price;
Is this possible somehow? Is there some documentation on how I would need to make the Serializer so it returns the JSON like this?
{
"name": "Testing",
"price": "CHF 20"
}
Thanks for any pointers and or Solutions I am really stuck and can't find a tutorial on how to make these Serializers work. If you have a Libarary with good documentation that would also help.
OK, I found a solution.
If you want to use jakarta.json your runtime needs to support it. I was using Pyara which says it supports Jakarta EE9 but somehow it does not. Switching to GlassFish solved that problem. The Correct Serializer was then done like this
You can then add it to a property that has the FastMoney type like so: