简体   繁体   中英

Grails : Error saving object, hard to understand, don't use 'property' keyword

I get a domain class like that :

class Offer {

    Property property
    Building building
    ExternalSystem externalSystem
    OfferStatus status
    Double offerPrice
    String currency
    String description
    String adventages
    Date offerDisponibility
    OfferNature offerNature
    Surfaces surfaces

    static hasMany = [units: Unit]

    static constraints = {
        building nullable: true
        externalSystem nullable: true
        description nullable: true
        adventages nullable: true
    }
}

When populating it into a controller :

def offer = new Offer()
offer.property = Property.get(1)
offer.building = Building.get(1)
offer.externalSystem = ExternalSystem.get(1)
offer.status = OfferStatus.get(1)
offer.offerPrice = 26860
offer.currency = 'EUR'
offer.description = 'WONDERFULL OFFER !'
offer.offerDisponibility = convertDate('12/04/2014')
offer.offerNature = OfferNature.read(1)
offer.surfaces = Surfaces.get(2)
offer.validate()

I get a strange behaviour when validating, saving or whatever on this object. It is the only domain object domain wich do that.

I get two different stacktrace, tha's the most strange part of my problem, the first stacktrace apear when I'm calling my controller the first time :

| Error 2013-11-26 11:27:10,971 [http-bio-8080-exec-2] ERROR errors.GrailsExceptionResolver  - ArrayIndexOutOfBoundsException occurred when processing
 request: [GET] /Project/login/auth
0. Stacktrace follows:
Message: 0
    Line | Method
->>  116 | doCall    in com.project.security.LoginController$_closure1
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|    200 | doFilter  in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter  in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    722 | run       in java.lang.Thread

The second is alway the last stacktrace :

| Error 2013-11-26 11:01:43,704 [http-bio-8080-exec-3] ERROR [/Project].[default]  - Servlet.service() for servlet [default] in context with path [/Project] threw exception [org.springframework.web.util.NestedServletException: Request processing failed; nested exception is groovy.lang.MissingMethodException: No signature of method: static java.lang.Math.max() is applicable for argument types: (java.lang.Integer, null) values: [4, null]
Possible solutions: max(int, int), max(double, double), max(float, float), max(long, long), min(int, int), wait()] with root cause
Message: No signature of method: static java.lang.Math.max() is applicable for argument types: (java.lang.Integer, null) values: [4, null]
Possible solutions: max(int, int), max(double, double), max(float, float), max(long, long), min(int, int), wait()
    Line | Method
->>  251 | doAppend              in org.apache.log4j.AppenderSkeleton
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|     66 | appendLoopOnAppenders in org.apache.log4j.helpers.AppenderAttachableImpl
|    206 | callAppenders . . . . in org.apache.log4j.Category
|    391 | forcedLog             in     ''
|    856 | log . . . . . . . . . in     ''
|    192 | logMessage            in org.slf4j.impl.GrailsLog4jLoggerAdapter
|    167 | error . . . . . . . . in     ''
|    213 | error                 in org.apache.commons.logging.impl.SLF4JLog
|    200 | doFilter . . . . . .  in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter              in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker . . . . . . in java.util.concurrent.ThreadPoolExecutor
|    615 | run                   in java.util.concurrent.ThreadPoolExecutor$Worker
^    722 | run . . . . . . . . . in java.lang.Thread

So which stacktrace is the correct ?

How can I solve this ?

No stacktrace if I'm not calling save() or validate() message.

Adding failOnError: true did not change the stacktrace.

Making :

if (!offer.save()) {
    log.error offer.errors
}

did not change the stacktrace.

Thanks for reading,

Snite

After hours of research, I finally solve my issue.

Property myProperty

Don't know why, but 'property' as variable name (and not domain class name) seems to be a reserved keyword...

Hope it will be usefull.

I found out what is wrong and and what was blocking .

Ok, editing my classes, I see that is a problem about abstract class.

Remember my Offer class :

class Offer {

//  Property property
    Building building
    ExternalSystem externalSystem
    OfferStatus status
    Double offerPrice
    String currency
    String description
    String adventages
    Date offerDisponibility
    OfferNature offerNature
    Surfaces surfaces

    static hasMany = [units: Unit]

    static constraints = {
        building nullable: true
        externalSystem nullable: true
        description nullable: true
        adventages nullable: true
    }
}

Commenting out the (Member Variable of the above class ) Property solve my problem.

Here is my Property class :

class Property extends Content {

    AssetManager assetManager
    Owner owner
    Mandat mandat
    AddressContent addressContent

    static hasMany = [
        buildings: Building,
        propertyMandats: PropertyMandat
    ]

    static constraints = {
        assetManager nullable: true
        mandat nullable: true
        owner nullable: true
    }
}

And here is my Content class :

abstract class Content {

    String name
    ExternalSystem externalSystem

    static constraints = {
        name nullable: true
        externalSystem nullable: true
    }

    @Override
    public String toString() { name }

}

Hibernate does not generate any 'property' table, but the 'content' table is like that after a desc :

+---------------------+--------------+------+-----+---------+----------------+
| Field               | Type         | Null | Key | Default | Extra          |
+---------------------+--------------+------+-----+---------+----------------+
| id                  | bigint(20)   | NO   | PRI | NULL    | auto_increment |
| version             | bigint(20)   | NO   |     | NULL    |                |
| external_system_id  | bigint(20)   | YES  | MUL | NULL    |                |
| name                | varchar(255) | YES  |     | NULL    |                |
| class               | varchar(255) | NO   |     | NULL    |                |
| sys_admin_client_id | bigint(20)   | YES  | MUL | NULL    |                |
| is_public_offer     | bit(1)       | YES  |     | NULL    |                |
| public_offer        | varchar(255) | YES  |     | NULL    |                |
| fund_id             | bigint(20)   | YES  | MUL | NULL    |                |
| address_content_id  | bigint(20)   | YES  | MUL | NULL    |                |
| asset_manager_id    | bigint(20)   | YES  | MUL | NULL    |                |
| mandat_id           | bigint(20)   | YES  | MUL | NULL    |                |
| owner_id            | bigint(20)   | YES  | MUL | NULL    |                |
| last_name           | varchar(255) | YES  |     | NULL    |                |
| mail                | varchar(255) | YES  |     | NULL    |                |
| phone_number1       | varchar(255) | YES  |     | NULL    |                |
| phone_number2       | varchar(255) | YES  |     | NULL    |                |
| agency_id           | bigint(20)   | YES  | MUL | NULL    |                |
| begin_date          | datetime     | YES  |     | NULL    |                |
| client_owner_id     | bigint(20)   | YES  | MUL | NULL    |                |
| end_date            | datetime     | YES  |     | NULL    |                |
| mandat_number       | varchar(255) | YES  |     | NULL    |                |
+---------------------+--------------+------+-----+---------+----------------+

My Content class extends lot of classes.

So, I suppose the problem is about the fact no 'property' table is created.

Why this behavior? And is this something wrong about my content abstract class?

About your question of the content table,

"At the database level Grails by default uses table-per-hierarchy mapping with a discriminator column called class so the parent class (Content) and its subclasses (BlogEntry, Book etc.), share the same table."

The Grails Framework-Reference Documentation-7.2.3 Inheritance in GORM

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM