Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [nosql-dev] Polymorthism help needed.

Cool!

That's very similar to what I am doing.

https://github.com/soujava/helidon-oracle-json-types/blob/main/src/main/java/os/expert/demo/helidon/EngineConverter.java

You (almost) directly convert Element(s) into Json!!!:

if(dbData instanceof Element element) {
    var elements = element.get(new TypeReference<List<Element>>() {
    }).stream().collect(Collectors.toMap(Element::name, Element::get));
        return JSONB.fromJson(JSONB.toJson(elements), Engine.class);
}

As far as I understand your example won't work for deeper elements.
I created a custom JsonTypeReferenceReader for this.

You use JSON-B 3.0 polymorphism while I must use a custom JsonbDeserializer, not a big issue.

My concern in using JsonObject as an intermediate is that we replace (optimized) mapping with JSON.

We also must use jnosql Element so the model is still bound to the implementation.

Kind regards,

Dmitry


On 7/30/2024 12:48 PM, Otavio Santana wrote:
Hey Dmitry, thank you, I am checking it.


Does it help you?

On Tue, Jul 30, 2024 at 11:31 AM Dmitry Repchevsky <redmitry@xxxxxxx> wrote:

Hi Otavio,

Here is my feedback about my intention to use polymorphism with jnosql.

I have my nosql entities annotated with both jakarta nosql and jsonb annotations like.

@Column("measurementValue")
@Convert(MeasurementValueConverter.class)
@JsonbTypeDeserializer(MeasurementValueDeserializer.class)
private MeasurementValueEntity measurementValue;

1. My first question is:
Unlike implementing ValueReader / ValueWriter using @Convert requires implementing both serialization / deserialization.
I don't want / need to interfere in writing here, is there a way to do this?

2. The EntityConverter class is abstract and not easy to use from external code.

Here is my solution that is kinda awkward...

public class MeasurementValueConverter2 extends EntityConverter
        implements EntitiesMetadata, AttributeConverter<MeasurementValue, Element> {

    private final ReflectionClassConverter converter = new ReflectionClassConverter();    
    private final Map<Class<?>, EntityMetadata> classes = new ConcurrentHashMap();
    
    public MeasurementValueConverter2() {
        classes.put(QuantityEntity.class, converter.apply(QuantityEntity.class));
        // more polymorphic classes
    }

    @Override
    public MeasurementValue convertToEntityAttribute(Element e) {
        // decide concrete class (e.g.  QuantityEntity)
        return toEntity(QuantityEntity.class, e.get(List.class));
    }
... many methods from EntityConverter & EntitiesMetadata

It would be great to provide easier way to use the converter...

Finally I went with other, dubious solution.

I already have MeasurementValueDeserializer.class JAXB deserializer which converts JsonObject into the entity:

final JsonObject obj = value.asJsonObject();
if (obj.containsKey(("typedQuantities"))) {
    return jsonb.fromJson(value.toString(), ComplexValueEntity.class);
}
if (obj.containsKey(("id"))) {
    return jsonb.fromJson(value.toString(), OntologyTermValueEntity.class);
}
if (obj.containsKey(("unit"))) {
   return jsonb.fromJson(value.toString(), QuantityEntity.class);
}

So much easily is to reuse JSONB:

@Override
public MeasurementValue convertToEntityAttribute(Element e) {
    final JsonValue value = JsonTypeReferenceReader.convert(e);
    if (value != null) {
        try {
            return jsonb.fromJson(value.toString(), MeasurementValueEntity.class);

But I need a TypeReferenceReader which converts Element to the JsonObject.

Note, that in my project I need it anyway, because we have some "info" field which may be ANY Json...

Here I went another adventure... My JsonTypeReferenceReader implementation may read any JsonValue

@Column("info")
public JsonObject info;

works perfectly, but

@Column("info")
public JsonString info;

never calls the JsonTypeReferenceReader!!!
This happens because the value "string" is a primitive and jnosql internals only look into the Value Readers!

@Column("info")
public JsonArray info;

Fails miserably, because JsonArray implements a List so it just considered a collection!

Another (IMHO) strange thing is that the converter is initialized each time the converter happens:

"The converter type: class es.bsc.inb.ga4gh.beacon.nosql.converter.MeasurementValueConverter not found on CDI context, creating by constructor"

So the conclusion:

Although nosql introduced @Convert annotation, its usage for polymorphism is complicated and impossible without using jnosql internals.

Kind regards,

Dmitry


On 7/7/2024 5:56 PM, Otavio Santana wrote:
Hey, sorry for the late reply.

I will be at home for a while, until August, after the conference season ends.

If you wish to do it manually, I believe the Convert annotation fits better.

I will work in a PoC on this.









On Thu, Jun 27, 2024 at 11:33 AM Dmitry Repchevsky <redmitry@xxxxxxx> wrote:

Hi Otavio!

The principal problem is that standard JSONB / JPA / JNoSQL polymorphism is not enough for some JSON schemas.
When I have "oneOf": [], the spec. says that json must match at most one schema.

In my particular case I have a MeasurementValueEntity and ComplexValueEntity, OntologyTermValueEntity and QuantityEntity that inherit from it.
So basically I'd like to catch MeasurementValueEntity with MeasurementValueReader, manually decide which of three types should be instantiated and
return it. I just see no API to do this. Something like in JAXB:  jsonb.fromJson(value, OntologyTermValueEntity.class);

I mean - I have Object value and know the Entity class and want create the Entity object.

Kind regards,

Dmitry

On 6/27/2024 10:00 AM, Otavio Santana wrote:
Hey Dmitry, how are you?

We are doing well and thanks for all support and feedback, you are a great contributor!

About having not discriminator value, could you create a scenario?
This way, we can work together on this solution.

On Wed, Jun 26, 2024 at 11:24 AM Dmitry Repchevsky via nosql-dev <nosql-dev@xxxxxxxxxxx> wrote:
Hi all,

Great to see that spec. and implementation is moving forward.
Especially that annotations are moving to the spec.:
org.eclipse.jnosql.mapping.Inheritance -> jakarta.nosql.Inheritance

Nevertheless, I have a trouble with custom inheritance with 1.1 using
ValueReader.
The implementation has changed (was Document and its an Element now).

Is there an elegant way to implement the inheritance when I have no
discriminator field?

public class MeasurementValueReader implements ValueReader {
     @Override
     public <T> T read(Class<T> clazz, Object value) {
         if (List.class.isInstance(value)) {
             final List list = List.class.cast(value);
             if (list.stream().filter(Entry.class::isInstance)
                     .anyMatch(e -> "unit".equals(((Entry)e).name()))) {
                 return (QuantityEntity) ???;
             }
         }

How may I manually convert Object value into the concrete
(QuantityEntity) type (I catch the "Measurement" interface).

Thank you in advance,

Dmitry

_______________________________________________
nosql-dev mailing list
nosql-dev@xxxxxxxxxxx
To unsubscribe from this list, visit https://www.eclipse.org/mailman/listinfo/nosql-dev


--

Thanks a lot,

Twitter | Linkedin | Youtube



--

Thanks a lot,

Twitter | Linkedin | Youtube



--

Thanks a lot,

Twitter | Linkedin | Youtube


Back to the top