doanduyhai / Achilles

An advanced Java Object Mapper/Query DSL generator for Cassandra
http://achilles.archinnov.info
Apache License 2.0
241 stars 92 forks source link

Schema validation fails for UDT when keyspace name is in Uppercase #354

Closed mykapp closed 5 years ago

mykapp commented 5 years ago

Hi, When using a keyspace name in "Uppercase" and the schema contains an UDT, the schema validation fails with an error when comparing the datatype. It works correctly if the keyspace is in lowercase.

See the error below:

Exception in thread "main" info.archinnov.achilles.exception.AchillesBeanMappingException: Data type 'frozen<"""TestUDT""".udt_details>' for column 'udt_details' of entity 'class com.mytest.TableWithUdt' does not match type in live schema '"TestUDT".udt_details'
    at info.archinnov.achilles.validation.Validator.validateBeanMappingTrue(Validator.java:125)
    at 
info.archinnov.achilles.internals.schema.SchemaValidator.validateColumns(SchemaValidator.java:120)
    at info.archinnov.achilles.internals.metamodel.AbstractEntityProperty.validateSchema(AbstractEntityProperty.java:365)
    at info.archinnov.achilles.internals.runtime.AbstractManagerFactory.lambda$validateSchema$539(AbstractManagerFactory.java:187)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
    at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
    at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418)
    at info.archinnov.achilles.internals.runtime.AbstractManagerFactory.validateSchema(AbstractManagerFactory.java:187)
    at info.archinnov.achilles.internals.runtime.AbstractManagerFactory.bootstrap(AbstractManagerFactory.java:121)
    at info.archinnov.achilles.generated.ManagerFactory.<init>(ManagerFactory.java:28)
    at info.archinnov.achilles.generated.ManagerFactoryBuilder.build(ManagerFactoryBuilder.java:31)
    at com.mytest.App.testUdtType(App.java:31)
    at com.mytest.App.main(App.java:24)

The database script is the following (also in the project in attachment):

create keyspace "TestUDT" with replication = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };
use "TestUDT";

create type udt_details (
  quantity int,
  value text,
);

create table table_with_udt(
    user_id text,
    udt_id text,
    udt_details udt_details,
    modification_date timestamp,
  primary key((user_id), udt_id)
);

The gradle example project with the annotated classes is in attachment.

myapptest.zip

doanduyhai commented 5 years ago

The error message is very clear:

Data type 'frozen<"""TestUDT""".udt_details>' for column 'udt_details' of entity 'class com.mytest.TableWithUdt' does not match type in live schema '"TestUDT".udt_details'

The problem comes from your code:


    @Frozen
    @Column("udt_details")
    private UdtDetails udtDetails;

The runtime schema does not match the mapping in the code

create table table_with_udt(
    user_id text,
    udt_id text,
    udt_details udt_details,  ---> NOT FROZEN HERE !
    modification_date timestamp,
  primary key((user_id), udt_id)
);
mykapp commented 5 years ago

Hi, I am sorry but this is a bug. Because everything is working when I use a keyspace name in lowercase but not in uppercase.

Moreover 1) the annotation processor forces me to annotate the field "udt_details" with @Frozen, even if it is not a frozen in the schema. See the error below if I don't annotate the field with @Frozen in the class :

info.archinnov.achilles.exception.AchillesBeanMappingException: UDT class 'com.mytest.UdtDetails' in field 'udtDetails' of class 'com.mytest.TableWithUdt' should be annotated with @Frozen
    at info.archinnov.achilles.internals.apt.AptUtils.validateTrue(AptUtils.java:507)
    at info.archinnov.achilles.internals.parser.validator.cassandra2_1.NestedTypeValidator2_1.validate(NestedTypeValidator2_1.java:69)
    at info.archinnov.achilles.internals.parser.FieldParser.parse(FieldParser.java:68)

2) even if I set the field as udt_details frozen<udt_details> in the schema (and let the annotation @frozen in the class) I have an error with the message below :

Exception in thread "main" info.archinnov.achilles.exception.AchillesBeanMappingException: Data type 'frozen<"""TestUDT""".udt_details>' for column 'udt_details' of entity 'class com.mytest.TableWithUdt' does not match type in live schema 'frozen<"TestUDT".udt_details>'
    at info.archinnov.achilles.validation.Validator.validateBeanMappingTrue(Validator.java:125)
    at info.archinnov.achilles.internals.schema.SchemaValidator.validateColumns(SchemaValidator.java:120)
    at info.archinnov.achilles.internals.metamodel.AbstractEntityProperty.validateSchema(AbstractEntityProperty.java:365)
    at info.archinnov.achilles.internals.runtime.AbstractManagerFactory.lambda$validateSchema$539(AbstractManagerFactory.java:187)

So there is still the bug related to the validation of UDT used inside a keyspace whose name is in uppercase.

Regards, Mickaël

doanduyhai commented 5 years ago

If you want to support unfrozen UDT, you can specify the CassandraVersion on your project compile time config: https://github.com/doanduyhai/Achilles/blob/master/achilles-model/src/main/java/info/archinnov/achilles/type/CassandraVersion.java#L294-L307

For the issue of comparing between code mapping and runtime, let me try to reproduce it

doanduyhai commented 5 years ago

Ok issue successfully reproduced, attempting a fix

doanduyhai commented 5 years ago

Bug fixed, will be available on next release

mykapp commented 5 years ago

Good to know. Thanks.