hilla
hilla copied to clipboard
hilla - autocrud: entities with mapped superclass not supported?
Describe the bug
Hi, I've noticed that if the entity I'm creating the autocrud component from is extending a mapped superclass, the generated UI components includes only the properties of the superclass, not the entity itself. Is this a bug or am I doing something wrong?
thanks
Expected-behavior
all mapped properties are used
Reproduction
create a jpa mapped super class and an entity that extends it. Then create an autocrud component for the entity.
System Info
gradle, spring boot, hilla. All latest
Hi @fer-marino,
I'm not sure if I'm able to reproduce this issue. There are integration tests in the Hilla repository that shows this works:
-
Maven with Java entities: https://github.com/vaadin/hilla/tree/main/packages/java/tests/spring/react-grid-test
-
Gradle with Kotlin entities: https://github.com/vaadin/hilla/tree/main/packages/java/tests/gradle/kotlin-gradle-test
If you have a case that doesn't work, please consider including a reproducible example.
Hi @fer-marino, could you send or describe how the crud service definition in Java looks like in your case? I'm asking because the Hilla parser would take the entity type argument from there.
I Will wrap up a sample project, just give me some time please
On Thu, Mar 27, 2025, 13:16 Anton Platonov @.***> wrote:
Hi @fer-marino https://github.com/fer-marino, could you send or describe how the crud service definition in Java looks like in your case? I'm asking because the Hilla parser would take the entity type argument from there.
— Reply to this email directly, view it on GitHub https://github.com/vaadin/hilla/issues/3361#issuecomment-2757830772, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOIYA6EOOTAHMX3YEG7UH32WPMYDAVCNFSM6AAAAABZIHP2ECVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDONJXHAZTANZXGI . You are receiving this because you were mentioned.Message ID: @.***> [image: platosha]platosha left a comment (vaadin/hilla#3361) https://github.com/vaadin/hilla/issues/3361#issuecomment-2757830772
Hi @fer-marino https://github.com/fer-marino, could you send or describe how the crud service definition in Java looks like in your case? I'm asking because the Hilla parser would take the entity type argument from there.
— Reply to this email directly, view it on GitHub https://github.com/vaadin/hilla/issues/3361#issuecomment-2757830772, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABOIYA6EOOTAHMX3YEG7UH32WPMYDAVCNFSM6AAAAABZIHP2ECVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDONJXHAZTANZXGI . You are receiving this because you were mentioned.Message ID: @.***>
I've investigated the issue a bit more. My endpoint returns a generic T extends Superclass which might be an instance of any mapped class inheriting from it. Vaadin generates the corresponding typescript class only for the superclass, instead of the whole hierarchy.
It is worth noting that in my endpoints there is no mention of the child classes elsewhere.
All classes are mapped entity with jpa and spring data. There is only one repository related to the superclass so no mention to child classes even there
I think it will be very helpful if you could provide a minimal project or at least some code snippet with the exact method signatures for the endpoint and the entities that reproduces your issue, otherwise we have to guess between the cases that are not supported and/or a misconfiguration.
For example, something like this:
@BrowserCallable
public class GenericCrudService {
public <T> T save(T value) {
// save using repository
return value;
}
}
will generate:
async function save_1(value: unknown, init?: EndpointRequestInit_1): Promise<unknown> {
return client_1.call("GenericCrudService", "save", { value }, init);
}
or something like this:
@BrowserCallable
public class GenericCrudService {
public <ID, T extends AbstractEntity<ID>> T save(T value) {
// save using repository
return value;
}
}
will generate:
async function save_1(value: AbstractEntity_1<unknown>, init?: EndpointRequestInit_1): Promise<AbstractEntity_1<unknown>> {
return client_1.call("GenericCrudService", "save", { value }, init);
}
or something like this:
@BrowserCallable
public class GenericCrudService<ID, T extends AbstractEntity<ID>> {
public T save(T value) {
// save using repository
return value;
}
}
will generate:
async function save_1(value: AbstractEntity_1<unknown>, init?: EndpointRequestInit_1): Promise<AbstractEntity_1<unknown>> {
return client_1.call("GenericCrudService", "save", { value }, init);
}
From the above examples, you can see the generator behavior is based on the AbstractEntity as the upper bound, since at generation phase, it is not possible to find out what could be the dynamic type of the T that extends the AbstractEntity, and if you happen to have a generic CRUD service that extends the CrudRepositoryService, of course, only the properties of the AbstractEntity are populated in the UI, though, still not sure what your service looks like, and these are just speculations.
My endpoint returns a generic T extends Superclass which might be an instance of any mapped class inheriting from it. Vaadin generates the corresponding typescript class only for the superclass, instead of the whole hierarchy. It is worth noting that in my endpoints there is no mention of the child classes elsewhere.
Since autocrud relies on static code analysis, it is not reasonable to find out which subclasses to use. It looks like using Superclass boundary is the best we could do in this case at the moment.
I would suggest to have an endpoint subclass using concrete entity classes for this case.
thanks @platosha . I thought vaadin was doing some magic using jpa annotations to infer all mapped entity and this was somehow broken. As you suggested anyway, I've added some dummy endpoint with the child classes and now the corresponding typescript code is generated.
Some further considerations about code generation are in https://github.com/vaadin/hilla/issues/3394.