1
votes

I have a problem with using JPA annotated class in Grails (tried on grails-3.1.11 and grails-3.2.0) in my test application.

I followed description in Grails documentation mappingWithHibernateAnnotation and multiple answers on Stackoverflow for similar problems (question 1, question 2 and question 3), but no luck. Here is a description what I do (same on both versions of Grails):
1. Create a new Grails project (I'm using IntelliJ Idea 2016.2.4).
2. Set up a datasource in application.yml:
dataSource:
    configClass: org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration.class
    pooled: true
    jmxExport: true
    dialect: org.hibernate.dialect.PostgreSQLDialect
    driverClassName: org.postgresql.Driver
    username: postgres
    password: masterkey

3. Add PostgreSQL JDBC dependency to build.grandle:

compile group: 'org.postgresql', name: 'postgresql', version: '9.4-1200-jdbc41'

4. Create a new class DictionaryEntity.groovy in src/main/groovy:

package persistence.postgresql.mapping

import javax.persistence.*;

@Entity(name = "persistence.postgresql.mapping.DictionaryEntity")
@Table(name = "dictionary")
public class DictionaryEntity implements Serializable {
    private int id;
    private int word;
    private int language;
    private String txt;

    @SequenceGenerator(name = "dictionary_id_seq_gen", sequenceName = "dictionary_id_seq", allocationSize = 1)
    @Id
    @GeneratedValue(generator = "dictionary_id_seq_gen", strategy = GenerationType.SEQUENCE)
    @Column(name = "id", nullable = false)
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Column(name = "word", nullable = false)
    public int getWord() {
        return word;
    }

    public void setWord(int word) {
        this.word = word;
    }

    @Column(name = "language", nullable = false)
    public int getLanguage() {
        return language;
    }

    public void setLanguage(int language) {
        this.language = language;
    }

    @Column(name = "txt", length = 128)
    public String getTxt() {
        return txt;
    }

    public void setTxt(String txt) {
        this.txt = txt;
    }

    public DictionaryEntity() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        DictionaryEntity that = (DictionaryEntity) o;

        if (id != that.id) return false;
        if (word != that.word) return false;
        if (language != that.language) return false;
        if (txt != null ? !txt.equals(that.txt) : that.txt != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + word;
        result = 31 * result + language;
        result = 31 * result + (txt != null ? txt.hashCode() : 0);
        return result;
    }
}

5. Create hibernate.cfg.xml in grails-app/conf directory (tried grails-app/conf/hibernate as well):

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <mapping class="persistence.postgresql.mapping.DictionaryEntity"/>
    </session-factory>
</hibernate-configuration>

6. Created a new DictionaryEntityController in grails-app/controllers/grailsproj directory (scaffolding plugin has included to dependencies):

package grailsproj

import persistence.postgresql.mapping.DictionaryEntity

class DictionaryEntityController {

    static scaffold = DictionaryEntity
}

When I'm running the application there is no domain classes ("Domains: 0" in Artefacts). If I go to my controller ("/dictionaryEntity/index") I'm getting the following error:

    ERROR org.grails.web.errors.GrailsExceptionResolver - MissingMethodException occurred when processing request: [GET] /dictionaryEntity/index
    No signature of method: static persistence.postgresql.mapping.DictionaryEntity.count() is applicable for argument types: () values: []
    Possible solutions: print(java.lang.Object), print(java.io.PrintWriter), wait(), find(), collect(), any(). Stacktrace follows:
    java.lang.reflect.InvocationTargetException: null
    at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:210)
    at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:187)
    at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
    at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
    at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    Caused by: groovy.lang.MissingMethodException: No signature of method: static persistence.postgresql.mapping.DictionaryEntity.count() is applicable for argument types: () values: []
    Possible solutions: print(java.lang.Object), print(java.io.PrintWriter), wait(), find(), collect(), any()
    at grails.rest.RestfulController.countResources(RestfulController.groovy:277)
    at grails.rest.RestfulController.index(RestfulController.groovy:64)
    at grails.transaction.GrailsTransactionTemplate$2.doInTransaction(GrailsTransactionTemplate.groovy:96)
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
    at grails.transaction.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:93)
    ... 14 common frames omitted

Looks like DictionaryEntity hasn't recognized as domain class. My pure Java+Hibernate application works fine with the same mapping class so I need your advice how to resolve this issue.

Update
Added annotation @grails.gorm.Entity regarding to Joshua's answer, the error has changed to:

Either class [persistence.postgresql.mapping.DictionaryEntity] 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.
1

1 Answers

1
votes

GORM 5 does not seem to support JPA with hibernate.cfg.xml. Take a look at this pull request conversation for more details. The main grails docs seem like they are incorrect and need to be updated https://github.com/grails/grails-data-mapping/pull/678

also consider @grails.gorm.Entity if you control the source