On Mon, May 1, 2023 at 4:11 PM Marcus Biel <indu.c...@gmail.com> wrote:
>
> Hello everyone,
>
> I'm dealing with a project that has a complex setup, and I'm trying to 
> simplify it. Our application allows users to establish Conditions or Filters 
> in the UI. These Conditions/Filters are stored in a database and can be used 
> to limit database queries using WHERE conditions. Interestingly, these 
> filters can be built recursively from other filters.

While I haven't built anything quite like this myself, I have seen
similar use cases, for what it is worth.
So maybe others with direct experience can share their learnings.

>
> Our current structure involves DTO classes marked with Jackson annotations, 
> which build a hierarchy. This hierarchy is mapped into business objects, 
> despite not having real business logic. These are later converted into 
> database DTOs. The system is quite intricate as it spans across three layers 
> - REST, Domain, and ORM Mapper. Additionally, the code, written two years ago 
> by another developer, extensively uses Jackson Annotations, which increases 
> the complexity and makes it difficult for me to understand.

Yes, that sounds like a complex beast.

> Here are the two code snippets for the REST DTOs and the ORM Mapper:
>
> REST DTO sample:
>
> @JsonTypeInfo(use = DEDUCTION)
> @JsonSubTypes({
>         @Type(AndDto.class),
>         @Type(OrDto.class),
>         @Type(ConditionDto.class),
>         @Type(FieldDto.class),
>         @Type(LabelDto.class)
> })
> public interface ExpressionDto {
> }
>
> ORM layer DTO sample of basically the same interface:
> @JsonTypeInfo(
>         use = JsonTypeInfo.Id.NAME,
>         property = "type")
> @JsonSubTypes({
>         @JsonSubTypes.Type(value = AndDbDto.class, name = "and"),
>         @JsonSubTypes.Type(value = OrDbDto.class, name = "or"),
>         @JsonSubTypes.Type(value = ConditionDbDto.class, name = "condition"),
>         @JsonSubTypes.Type(value = FieldDbDto.class, name = "field"),
>         @JsonSubTypes.Type(value = LabelDBDto.class, name = "label")
> })
> public interface ExpressionDbData {
> }
>
> ---
> I'm faced with the task of integrating about 15 more logical operators into 
> the model, on top of the two already present - Equals for Field and Contains 
> for Labels. Incorporating these operators would significantly ramp up the 
> complexity of the existing model.
>
> Each field type is linked to a data type - Text, Number, or Date. Each data 
> type should support its specific logical comparison operators:
> TEXT: EQUAL, EQUAL_IGNORE_CASE, NOT_EQUAL, START_WITH, ENDS_WITH, CONTAINS
> NUMBER: EQUAL, NOT_EQUAL, GREATER, SMALLER, GREAT_EQUAL, SMALLER_EQUAL
> DATE: EQUAL, BEFORE, AFTER, BEFORE_OR_EQUAL, EQUAL_OR_AFTER
>
> I'm searching for a more straightforward yet valid method to accept these 
> conditions/filters from the frontend, store them in the database, and later 
> apply them to database queries. At present, we're achieving this with a 
> custom JPA CriteriaBuilder.
>
> Could using a custom Serializer / Deserializer or maybe an AttributeConverter 
> be helpful in this case? I'm not sure, and I'm open to suggestions. 
> Currently, the project is using the latest versions of Java and Frameworks - 
> Java 20, Hibernate 6.2, and Quarkus 3.x. I could leverage Sealed classes if 
> Jackson supports them.

Custom deserializers can be tricky: obviously you can do anything and
everything, but at the same time if they need to interoperate with
standard Jackson (de)serializers there's quite a bit more work to do.

Another approach that can be helpful is 2-pass (or  multi-pass), in
which a JsonNode-based model is bound from/to JSON, modified, then
used as source for ObjectMapper. This can be used for all kinds of
pre-/post-processing.

>
> Also, could someone clarify the difference between the use of DEDUCTION in 
> the REST layer and JsonTypeInfo.Id.NAME in the database layer version of the 
> same class?

Ok, so: DEDUCTION basically means that no explicit Type Id (property,
or wrapper Object/Array) is used; type is deduced solely from the
existence of specific property names. Value types then must have,
each, at least one unique property name (something no other type has).
On serialization no type id is written, only regular properties.

The other choice used is to add (and use) specific Object Property
(here "type") to contain Type Id; and as id use logical, annotated
"name" (instead of Java class, the main alternative).
Type Id is written as Object metadata in addition to regular
properties (or in general, regular value representation).

I must say I am not sure why DEDUCTION was used here: I think it's
more common to use explicit Type Ids for both.

-+ Tatu +-

>
> Thanks a lot in advance!
>
> Marcus
>
> --
> You received this message because you are subscribed to the Google Groups 
> "jackson-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to jackson-user+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/jackson-user/14120539-f3f0-4458-b206-c2b31002a9e2n%40googlegroups.com.

-- 
You received this message because you are subscribed to the Google Groups 
"jackson-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jackson-user+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jackson-user/CAL4a10iJEUgC0qU3MFpvLMV2CF2uxye0XW41QiuPrJZC7D3c1w%40mail.gmail.com.

Reply via email to