String size in Grails too big for database field - grails

I have Message domain class that is used to send an email to site administrators
class Message {
String name
String subject
String body
}
I thought String would not have a maximum size but when people put in messages that are too big then I see exceptions in my log files. For now I put a constraint in to limit the size of the message to 250 but cannot make it bigger or else the save fails. I am using PostgreSQL 9.1.1 and Grails 1.3.7. Does anyone know a way to fix this?

You can specify the data type using a constraint:
static constraints = {
body type:'text'
}

Add this to your domain class:
static constraints = {
body(maxSize:1000)
}

Setting type in constraints block doesn't work!
Put in the mapping block instead.
static mapping = {
body type: 'text'
}

The max size of a VARCHAR is set in the database, Grails doesn't have any say in the matter. What you can do is tell Grails what you need, and it will generate DDL that uses a clob instead of a string.
Change the mapping for the column to use type: "text", while adding the maxSize you want in your constraints. Grails will figure out from this that it should set the column data type to clob.
(Generally a clob field will hold up to 4GB, though some databases allow changing that.)

Related

Trim domain field by default

What is the best way to trim field value in domain?
My suggestion is to use beforeSave(), but would work something like this?
class Book {
String name = name?.trim()
}
You have a couple options depending on what behavior you want.
A custom setter, which will trim the value every time you set it
class Book {
String name
void setName(String name) {
this.name = name?.trim()
}
}
A custom getter, which will give you a trimmed value but not store it in the database
class Book {
String name
String getName() {
this.#name?.trim()
}
}
A hibernate event, like beforeSave() as you mentioned, which will only trim it before the object is persisted.
Well, you can enable automatic trimming of string in Grails (version 2.3+) by setting below property in Config.groovy file:
grails.databinding.trimStrings = true
This will automatic trim the string before save or update.
I have have noticed that Grails automatically does a .trim() on fields before persisting them. For example:
null
""
" "
All gets stored as null in Grails 2.3.7 for a nullable string. In addition:
" foobar "
gets stored as "foobar"
These results are using the default h2 database. So you might let Grails do the heavy lifting in this case.
Here is my hack for quickly trimming all fields in a domain object. I often receive JSON data that is not formatted in a way that would allow me to use data-binding techniques. This method can be called after updating or assigning all values in the domain instance.
class Book {
def trimFields() {
this.properties = this.properties
}
}
Requires this configuration which is set by default in Grails
grails.databinding.trimStrings = true
I know this is overkill but it's quick and easy to add to a domain class.

grails validation when fetching rows

Is it possible to fetch a default value in grails if a column is null? If I were to represent following query via grails domain object then how could I achieve it:
SELECT IFNULL(empsalary,0.00) from Employee;
Domain object:
class Employee{
Integer id,
Float empsalary
static constraints = {
id unique: true, blank:false
empsalary nullable:true
}
}
making empsalary nullable false isn't an option due to existing data
validator on empsalary seems to work when inserting rows but not while data fetch
we can consider writing say getEmpSalary() method on domain and perform check there but there are several other fields we need to do this so trying to avoid massive code changes
If you want a default value to come out of the database without having to code anything into your classes, I suggest you update every row where it is null and set it to 0 in the database. If data is getting inserted from another application and that application is allowing a null value, put a 'DEFAULT 0' on your database column.
Grails also offers an "afterLoad" event which is run when a domain object gets loaded from the database. See the documentation here: http://grails.org/doc/2.3.7/guide/GORM.html.
I think you can do this with HQL:
def salary = Employee.executeQuery('SELECT COALESCE(empsalary, 0.0) FROM Employee')[0]
See this SO Question.
Please try setting Float empsalary = 0.0 in your domain object.

Property [] of class [] can not be null error in Grails

I am new to Grails and getting this error on two out of my three domains when I run the project on all the domains content. The domain the works is
class Location {
def scaffold = true
String company
String name
String address
static belongsTo=[company:Company]
static constraints = {
}
}
The domain that does not work is
class Report {
def scaffold = true
String title
String location
Date published
static belongsTo=[location:Location]
static constraints = {
}
}
I can not see the structural or syntax issue that is trowing the errors. I have been trying a variety of adds and subtracts and can not seem to find anything that address this error at a basic level. Again I have just started using Grails and Groovy
After doing the changes told by #araxn1d, you should also check the constraints. By default all properties are not nullable (that's why you're getting for example the error for the title property)
If you already have data in your database you have two options:
Update your database and set the correct values in each table or row
Set each property in the domain as nullable. For example
static constraints = {
title nullable:true
}
Are you creating a Report with no properties set? By default, Grails will check that all properties are not null. If you want to allow the user to leave a certain field undefined (null), then you have to explicitly tell Grails in the constraints map:
static constraints = {
propertyName nullable: true
}
Seems like error is in this line:
String location
location is String type, but should be Locationtype. The same as String company in Location domain should be Company company.
I think the problem is that you've changed the structure of the domain class after you generated the automatically created views/controller for the domain.
I fixed it by just deleting the offending domain along with the controller/views file and recreating them. I'm sure you could root through and find the offending code though.

constraints in grails

Hi I am having some trouble getting my constraints to work in my grails project. I am trying to just make sure that the field for Site_ID is not left blank but it still accepts an blank input. Also I am trying to set the order in which the fields appear but even that is not reflecting on the page when I try it out. Here is the code:
package translation
class J2_Translations {
String Site_ID
String I18NKey
static constraints = {
Site_ID(blank:false)
I18NKey()
}
}
and here is my code for the controller, I am not doing anything special I just want the constraints to work
package translation
class J2_TranslationsController {
def scaffold = J2_Translations
}
thanks,
Ameya
Grails is a convention-over-configuration framework. Make sure you follow the standard Java naming conventions. Properties should be named with camel-case identifiers with the leading character in lowercase. For example:
String siteId
String i18nKey

How can fields in Grails represented by a combobox be made optional?

I'm doing my first experiments with Grails and am looking for a way to have fields represented by a combobox (such as one-to-one domain associations and numbers with a narrow range constraint) to be optional, i.e. there should be an empty entry in the combobox.
How can this be achieved? I've tried both adding a nullable:true constraint and listing the fields in the optionals static property, but neither produces the desired result.
These are my domain classes:
class Customer {
String name
}
class Book {
static optionals = ['year','loanedTo','loanedSince']
static constraints = {
title(blank:false)
author(blank:false)
year(range:1900..new Date().getAt(Calendar.YEAR), nullable:true)
loanedTo(nullable:true)
loanedSince(min:new Date())
}
String title;
String author;
Integer year;
Customer loanedTo;
Date loanedSince;
}
I've found that the nullable:true constraint actually does have the desired effect - however, it does not take effect immediately; you have to restart Grails to see it.
If you've generated your scaffolding code, you'll also have to regenerate it so that the option is present.
I don't think optionals is still supported: http://jira.codehaus.org/browse/GRAILS-472
The tag also has an attribute for a default, "not selected" value: noSelection. You can use it like this to have the drop-down default to "---" instead of your regular values:
noSelection="${['':'---']}"
In the controller, the default value shows up as an empty string, as specified in the first part of the value.

Resources