Axon PostgreSQL without TOAST (Having issues)

Hello Daniel,

thanks for your feedback. Unfortunatey, it wasn’t an actual choice on our side. This is Hibernate/the Postgres dialect choosing to store a byte[] as an OID.
For the event store, that’s generally not an issue, as objects are created once and left alone. The TokenStore chanfes continuously.

We have been sharing some information on this list, I believe, about best practises on Postgres, providing some example configuration to ‘persuade’ Hibernate to store these fields as bytea instead of OID.

Our friends at Trifork have written a blog about it too:
https://blog.trifork.com/2017/10/09/axon-postgresql-without-toast/

Cheers,

Allard

Hi Allard,

I already checked out the link, and the workaround described there actually works.
However, it would be better if it was a part of Axon framework itself, for example configurable by some properties.
Otherwise like I said it’s a memory leak. And even if we use Axon Server, we’ll still need Postgres as a token store. From a mature framework I don’t expect to have such memory leaks.

Best,
Daniel

Hi Daniel,

we could debate whether it’s a memory leak or just garbage creation. I’d argue it’s the latter.

We’d love to have a simple property, or better, do it based on dialect. The challenge is to do it in a way that doesn’t break compatibility with current solutions. If you have any suggestions, we open to hearing them.

Cheers,

Allard

Hi,

i use PostgeSQL column type “jsonb” for “METADATA” and “PAYLOAD” columns via JPA.
My “orm.xml” for PostgreSQL contains:

`

`

The converter looks like this:
`

@Converter(autoApply = false)

public class JpaPostgreSqlJsonbBytearrayConverter implements AttributeConverter<byte[], Object> {

@Override

public String convertToDatabaseColumn(byte[] bytes) {

return (bytes != null) ? new String(bytes, StandardCharsets.UTF_8) : null;

}

@Override

public byte[] convertToEntityAttribute(Object json) {

return (json != null) ? json.toString().getBytes(StandardCharsets.UTF_8) : null;

}

}

`

This is not guaranteed to be the best or fastest way to do it. I even don’t know, if there is a memory leak (never experienced it).
But it uses “jsonb”, which has some advantages with json data.
I also wanted to do it JPA-provider-independent (as Converter). This is always advisable.

Cheers. Johnny

Allard,
The way you call it doesn’t matter: memory leak, garbage creation, leftover objects, etc. The outcome is the same.
Anyways, I understand that the solution has to be backwards compatible. Hence I would suggest to add this trigger property with a default value to work the “old” way. This way at least for new users there would be a chance to avoid this “garbage creation”, assuming that it’s well documented somewhere.

Johnny,
The problem is not in the event store (“domain_event_entry” table), it’s in the token store (“token_entry” table). The token in stored in the “token” field of the “token_entry” table. It’s basically a serialised XML object. And when the token advances its position, the old serialised object never gets deleted. Hope this helps.

Hi all,

Very worthwhile conversation we’re having here, with lot’s of good info contained in it for our users.

Daniel, could I ask a favor of you?
As I feel you have quite a thorough understanding of the problem at hand in regards to PostgreSQL and feeling of how to resolve this, would you be up for adding an issue to the issue tracker?

I’d hate to lose the conversation in this user group, whilst you’re obviously looking to improve the framework for everybody through your comments.

Cheers,
Steven

Hi!

Same problem here for us. I liked daniels Idea of having a switch to get a better behaviour for at least new users.
Is there already an issue you can point to?

Thanks,
Dirk

Hi Dirk,

I haven’t heard anything from Daniel after my request to introduce an issue on this point.
So sorry Dirk, no, there is no issue on the board for this yet.

Thus for now, I would suggest to follow the blog post Allard shared on the topic, as that has been the most pragmatical solution for all Axon users up to now.
For clarity, I am talking about this blog post.

Hope this helps!

Cheers,
Steven

Revisiting this thread and trying to accomplish the same task. I’m using v4.2 of Axon Framework (Spring Boot Starter) w/ postgres 12. I’ve attempted to use Johnny’s solution using a converter, which makes the most sense to me as it leaves BLOBs intact for other purposes. The insert is not reaching the server, and I’m receiving:

`
org.postgresql.util.PSQLException: Unsupported Types value: 792,791,759

`

which is perhaps a result of:

xyz_1 | 2019-11-10 18:09:30.698 DEBUG 1 --- [ scheduling-1] tributeConverterSqlTypeDescriptorAdapter : Converted value on binding : [B@7820b8e0 -> {"traceId":"4a62c7c4-977d-4a0a-b062-5f691ad1c666","correlationId":"4a62c7c4-977d-4a0a-b062-5f691ad1c666"} xyz_1 | 2019-11-10 18:09:30.698 TRACE 1 --- [ scheduling-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [UNKNOWN(792791759)] - [{"traceId":"4a62c7c4-977d-4a0a-b062-5f691ad1c666","correlationId":"4a62c7c4-977d-4a0a-b062-5f691ad1c666"}]

My converter (in Kotlin) looks like:

@Suppress("unused")
@Converter(autoApply = false)
class JpaPostgreSqlJsonbBytearrayConverter : AttributeConverter<ByteArray, Any> {
    private val mapper = ObjectMapper()

    override fun convertToDatabaseColumn(bytes: ByteArray?): String? {
        return if (bytes != null) String(bytes, StandardCharsets.UTF_8) else null
    }

    override fun convertToEntityAttribute(json: Any?): ByteArray? {
        return json?.toString()?.toByteArray(StandardCharsets.UTF_8)
    }

    companion object : KLogging()
}

I was considering that it may have something to do with the Kotlin representation of Strings and Hibernate not knowing how to map them. I tried explicitly returning java.lang.String, but this also failed, and I think it’s the same under the hood.

The bytea representation described in the attached article worked perfectly, and is a big step up from the BLOB representation, but I would like my events to be in jsonb.

Is there an updated solution for Axon 4.2? Thanks!