Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I dynamically register a domain? #875

Open
ifree-zm opened this issue May 14, 2024 · 12 comments
Open

Can I dynamically register a domain? #875

ifree-zm opened this issue May 14, 2024 · 12 comments

Comments

@ifree-zm
Copy link

with gorm-hibernate5-spring-boot:7.3.1
my code was:

def groovyCode = """
      package com.example.gorm.entity

      import grails.gorm.annotation.Entity
      import org.grails.datastore.gorm.GormEntity
      
      @Entity
      class Person implements{
          String firstName
          String lastName
      }

      """
      def groovyClass2= loader.parseClass(groovyCode);
      def person = groovyClass.getDeclaredConstructor().newInstance()
      person.invokeMethod("find", { lastName == "John" })

Running the above code will throw an exception:

Either class [com.example.newgorm.entity.Person] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.

I found that domain will be registered to STATIC_APIS at project startup. Can I dynamically register Person domain now?

@matrei
Copy link
Contributor

matrei commented May 22, 2024

Hi, out of curiosity, what is your use case for this?
I guess you could try to use the GormEnhancer.registerEntity(PersistentEntity entity) (if you can get a hold of it) or something like that.

@ifree-zm
Copy link
Author

ifree-zm commented May 23, 2024

Hi, out of curiosity, what is your use case for this? I guess you could try to use the GormEnhancer.registerEntity(PersistentEntity entity) (if you can get a hold of it) or something like that.

@matrei Thank you for your reply! My application scenario is for users to dynamically define domain models and be able to query data, so I need to dynamically compile and generate domains. I have noticed that GormEnhancer. registerEntity (PersistentEntity entity) should meet my requirements, but how should I obtain an instance of GormEnhancer? I have obtained a PersistentEntity through the following code. Is the usage correct?

ApplicationContext applicationContext = grailsApplication.mainContext
MappingContext mappingContext=applicationContext. getBean ('grailsDomainClassMappingContext ') as MappingContext
Class<?> clazz = groovyClass2
PersistentEntity entity=mappingContext. addPersistentEntity (clazz)

@ifree-zm
Copy link
Author

Hi, out of curiosity, what is your use case for this? I guess you could try to use the GormEnhancer.registerEntity(PersistentEntity entity) (if you can get a hold of it) or something like that.

@matrei Thank you for your reply! My application scenario is for users to dynamically define domain models and be able to query data, so I need to dynamically compile and generate domains. I have noticed that GormEnhancer. registerEntity (PersistentEntity entity) should meet my requirements, but how should I obtain an instance of GormEnhancer? I have obtained a PersistentEntity through the following code. Is the usage correct?

ApplicationContext applicationContext = grailsApplication.mainContext
MappingContext mappingContext=applicationContext. getBean ('grailsDomainClassMappingContext ') as MappingContext
Class<?> clazz = groovyClass2
PersistentEntity entity=mappingContext. addPersistentEntity (clazz)

@matrei I have made some progress. Through the following code, I have implemented the registration of Person, which triggers a listener and calls the registration logic

@Autowired
    MappingContext mappingContext

def entity = mappingContext.addPersistentEntity(groovyClass2)

But when I try to use it through the following code, I still get an error message "Unknown entity: Person"

def method = entity.newInstance().metaClass.getMetaMethod('find', { lastName == "Tom" })
method.invoke(this, { lastName == "Tom" }).find()

@rainboyan
Copy link

I think the main cause of the problem is the GroovyClassLoader, which does not compile the script as we would expect, resulting in code that is not a valid GormEntity. You can check the class file generated by the program to be sure, but it's difficult.

Grails has its own GrailsAwareClassLoader, but it doesn't offer enough flexibility, but you can try it.

@ifree-zm
Copy link
Author

I think the main cause of the problem is the GroovyClassLoader, which does not compile the script as we would expect, resulting in code that is not a valid GormEntity. You can check the class file generated by the program to be sure, but it's difficult.

Grails has its own GrailsAwareClassLoader, but it doesn't offer enough flexibility, but you can try it.

Thank you for your answer! I tried the method you mentioned, but the error is still the same as before.

@rainboyan
Copy link

@ifree-zm Could you provide a minimal and runnable example to reproduce the error, so I can test it with my version to find out how to fix it.

@ifree-zm
Copy link
Author

@ifree-zm Could you provide a minimal and runnable example to reproduce the error, so I can test it with my version to find out how to fix it.

That's great! The attachment is a demo built using Gradle. If you need a demo inherited from Springboot, I can also provide it! Thanks! @rainboyan g-app.zip

@ifree-zm
Copy link
Author

ifree-zm commented May 28, 2024

@puneetbehl Are there any plans to add this feature?

@rainboyan
Copy link

@ifree-zm I spent some time researching and found out that the GORM and Hibernate plugin don't support dynamic registration of entities at this time.
Can you elaborate on the background to this feature requirement and how it will work in your application? I think there could be a better way. Dynamically registering entities can extend the functionality of an application, but it can also lead to system security and data security issues.

@ifree-zm
Copy link
Author

@ifree-zm I spent some time researching and found out that the GORM and Hibernate plugin don't support dynamic registration of entities at this time. Can you elaborate on the background to this feature requirement and how it will work in your application? I think there could be a better way. Dynamically registering entities can extend the functionality of an application, but it can also lead to system security and data security issues.

@rainboyan I plan to let users design their own domain models and directly manipulate the data. For example, if a user defines a Person model, I can automatically concatenate the code and compile it (if possible), and then obtain a Person through the code [Person. find { name=='Tom'}]. Therefore, I need to dynamically compile the Person class instead of defining it in the code beforehand. I have tried to find other similar frameworks, but none of them are ideal...

@rainboyan
Copy link

@ifree-zm Although GORM's Entity seems simple to use, I don't think it's really suitable for users to write and run as a script on the web front end, since anytime there's user input, there's the possibility of error and the need for back-end data validation. It seems that using SQL or HSQL may be able to realize some data query and export functions, sorry, I don't know the specific needs of your system, and can't give a more definite suggestion.

On the other hand, I also don't think Hibernate supports the ability to dynamically configure entities, because if the configuration is changed, it can affect the entire data persistent layer of the framework, causing the system to crash.

@ifree-zm
Copy link
Author

@rainboyan Thank you for your suggestion! Of course, this is just an attempt I want to make. Currently, it seems that this idea is not feasible. Perhaps I can find other better ways. Thank you again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants