Upgrade issue to Grails 2.4.4
Asked Answered
C

3

8

I keep getting an error when starting my Grails application after I upgraded from Grails 2.4.3 to 2.4.4 . The full error can be read here: http://pastebin.com/UXQ34JKD

2014-10-31 16:26:32 ERROR [context.GrailsContextLoaderListener] Error initializing the application: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: java.util.List
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: java.util.List
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: java.util.List
        ... 4 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Association references unmapped class: java.util.List
        ... 4 more
Caused by: org.hibernate.MappingException: Association references unmapped class: java.util.List
        ... 4 more

It shows an Association references unmapped class: java.util.List

It doesn't say what domain class or any really helpful information. I've tried removing some domain classes and trying to figure what the cause is, but it's large application and I have been unsuccessful.

Can anyone point me in the right direction for figuring out where this is being triggered and how to fix it?

Carnivore answered 31/10, 2014 at 20:31 Comment(1)
I have seen this error already with older versions of Grails...Straightforward
N
10

Finding out what's wrong

The first thing you need to do is to find out which field(s) cause the issue. Likely it'll be any field in a domain class declared as a List.

In my case it was easy to find them, because the project is on very early stage and there is not too much domains.

However, I found a possible solution to narrow down the possible culprits set.

The interesting part is:

What sucks is the only good way to figure out where they are is to set a breakpoint on line 436 of AbstractGrailsDomainBinder and look at the state of affairs

Fixing the issue

When you find the improper fields, it's time to implement a workaround.

Let's assume that our culprit was List authors in a domain class like:

class Book {
   List<Integer> authors // keeps author ids
} 

We need to get rid of the list, of course, so the solution would be something like:

class Book {

    static transients = ['authors']

    String authorIds

    public void setAuthors(List<Integer> authorList) {
        this.authorIds = authorList ? authorList.join(";") : ''
    }

    public List<Integer> getAuthors() {
        return authorIds?.split(";")?.collect { it.toInteger() } ?: []
    }

} 

Possible side effect

I noticed that the setter needs to be called explicitly to work.

I'm quite sure that in previous Grails version the following code would call the setter:

new Book(authors: [1, 2, 3])

But it looks like in Grails 2.4.4 it needs to be done like:

def book = new Book()
book.setAuthors([1, 2, 3])
Narrows answered 31/10, 2014 at 23:50 Comment(3)
Well, I don't really consider it a workaround. I just don't think using List as a field in a domain class is a good practice at all. But of course I'm open to any suggestions. Please, provide yours.Hartill
Why is this a workaround if Grails says that it supports List of primitive types? grails.github.io/grails-doc/latest/guide/…Vinnie
Well, Grails provides a few features that are actually not the best in real world usage, e.x. hasMany (because of performance) or binding request params directly to domain objects (because of security). The fact it's supported doesn't mean it's the best practice...Hartill
N
10

You also need to specify the hasMany map. It seems that it is not more sufficient to just add List<DomainClassName> listName in your Domain-Class

you also need to add

static hasMany = [
        listName: DomainClassName
]

at least it works for me.

Nepil answered 3/12, 2014 at 12:1 Comment(0)
V
-3

Try to replace problematic List interface with something that is real class, for example ArrayList

Vargo answered 2/11, 2014 at 16:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.