How to get the value from sum() in a Grails criteria - grails

I can't use the + operator with resultado[0] + obj.nopersonas, nopersonas is an Integer.
fhinicio(blank:false, validator : { val, obj ->
def diff = groovy.time.TimeCategory.minus(obj.fhfinal, val)
def total = diff.hours*60 + diff.minutes
if (total < 15){
return "reserva.fhfinal.tiempo.min.label"
} else {
if (total > 60) {
return "reserva.fhfinal.tiempo.max.label"
} else {
def reserva = Reserva.createCriteria()
def resultado = reserva.list() {
or {
and {
ge('fhinicio', val)
le('fhinicio', obj.fhfinal)
}
and {
ge('fhfinal', val)
le('fhfinal', obj.fhfinal)
}
}
projections {
sum('nopersonas')
}
}
//this is not working
def aff = resultado[0] + obj.nopersonas
Cannot execute null+null. Stacktrace follows: Message: Cannot execute null+null

You've got a couple of problems to resolve:
The criteria query is returning null
obj.nopersonas is null
The criteria query
To fix the criteria query, start without the projection:
def reserva = Reserva.createCriteria()
def resultado = reserva.list {
or {
and {
ge('fhinicio', val)
le('fhinicio', obj.fhfinal)
}
and {
ge('fhfinal', val)
le('fhfinal', obj.fhfinal)
}
}
}
Make sure you're getting the appropriate instances of Reserva. Then, add the projection and since you're expecting a single value, use the get() method instead of list().
def reserva = Reserva.createCriteria()
def resultado = reserva.get {
or {
and {
ge('fhinicio', val)
le('fhinicio', obj.fhfinal)
}
and {
ge('fhfinal', val)
le('fhfinal', obj.fhfinal)
}
}
projections {
sum('nopersonas')
}
}
def aff = resultado + obj.nopersonas
obj.nopersonas
Since obj.nopersonas is null, I'm assuming the property is nullable. If the property is supposed to be nullable, then you'll need to account for that in your validator.

It is working.
Integer variable_name = Integer.valueOf(resultado[0].toString())

You can simply handle the null condition:
def aff = (resultado[0] ?: 0) + (obj.nopersonas ?: 0)

Related

grails object references an unsaved transient instance - save the transient instance before flushing

I know that this question has many questions around in Stackoverflow but even though it has many answers about it, thoses answers couldn't help me at all and either figured it out yet.
In my WebAPP it works normal, but when I transform it to an API it fails(topic title error)... I have tried following:
save first Test(flush:true) // error the C must be NOT NULL
save testInstance.addToAs(a).save() //b and c
Why I can't save the whole object?
Domain Water
static hasMany = [personWaters : Person,
equipmentWaters: Equipment,
sampleWaters : WaterSample]
Domain WaterSample
static belongsTo = [water: Water]
Controller refactored some parts
def save() {
def waterParams = request.JSON
def sampleList = [] as Set
def equipmentList = [] as Set
def personList = [] as Set
waterAPIService.personPopulate(waterParams.personWaters, personList)
waterAPIService.equipmentPopulate(waterParams.equipmentWaters, equipmentList)
waterAPIService.samplePopulate(waterParams.sampleWaters, sampleList)
Date validity = Date.parse("yyyy-MM-dd'T'HH:mm:ss'Z'", waterParams.validity)
Date sample = Date.parse("yyyy-MM-dd'T'HH:mm:ss'Z'", waterParams.sampleDate)
waterParams.remove('personWaters')
waterParams.remove('equipmentWaters')
waterParams.remove('sampleWaters')
waterParams.remove('validity')
waterParams.remove('sampleDate')
waterParams.put('personWaters', personList)
waterParams.put('equipmentWaters', equipmentList)
waterParams.put('sampleWaters', sampleList)
waterParams.put('validity', validity)
waterParams.put('sampleDate', sample)
def waterInstance = new Water(waterParams)
//def test = waterAPIService.sampleValidated(sampleList ? sampleList.size() : 0, sampleList)
def test = 99
if (test == 99) {
if (saveTest(waterInstance)) {
render([message: ['ok']] as JSON)
} else {
def errors = []
errors.add('Erro ao salvar')
errors = waterInstance.errors.allErrors.collect { g.message([error: it]) }
render([message: errors] as JSON)
}
} else {
render render([message: ["Critério de estabilização não atendido para o parâmetro " + waterAPIService.messageSampleValidated(test)]] as JSON)
}
}
def saveTest(Water waterInstance) {
try {
println waterInstance.validate()
if (!waterInstance.hasErrors() && waterInstance.save() && waterInstance.validate()) {
return true
} else {
log.info("error", waterInstance.errors)
return false
}
} catch (e) {
log.info("exception error", e)
}
}
Service
def personPopulate(personWaters, personList) {
personWaters.each {
personList << Person.get(it.id)
}
return personList
}
def equipmentPopulate(equipmentWaters, equipmentList) {
equipmentWaters.each {
equipmentList << Equipment.get(it.id)
}
return equipmentList
}
def samplePopulate(sampleWaters, sampleList) {
sampleWaters.each {
def sample = new WaterSample()
sample.dateTime = Date.parse("yyyy-MM-dd'T'HH:mm:ss", it.dateTime)
sample.levelWater = it.levelWater
sample.conductivity = it.conductivity
sample.dissolvedOxygen = it.dissolvedOxygen
sample.redoxPotential = it.redoxPotential
sample.ph = it.ph
sample.temperature = it.temperature
sampleList << sample
}
return sampleList
}
waterParam JSON
{
"climateCondition":"SUNNY",
"equipmentWaters":[
{
"id":2
},
{
"id":4
}
],
"personWaters":[
{
"id":86
},
{
"id":143
}
],
"sampleWaters":[
{
"ReportId":2,
"conductivity":0,
"IDWeb":0,
"dissolvedOxygen":0,
"dateTime":"2015-12-07T17:08:00Z",
"levelWater":0,
"ID":4,
"UpdateDate":"0001-01-01T00:00:00Z",
"ph":0,
"redoxPotential":0,
"temperature":0
},
{
"ReportId":2,
"conductivity":0,
"IDWeb":0,
"dissolvedOxygen":0,
"dateTime":"2015-12-07T17:09:00Z",
"levelWater":0,
"ID":5,
"UpdateDate":"0001-01-01T00:00:00Z",
"ph":0,
"redoxPotential":0,
"temperature":0
},
{
"ReportId":2,
"conductivity":0,
"IDWeb":0,
"dissolvedOxygen":0,
"dateTime":"2015-12-07T18:13:00Z",
"levelWater":0,
"ID":6,
"UpdateDate":"0001-01-01T00:00:00Z",
"ph":0,
"redoxPotential":0,
"temperature":0
}
]
}
Ok, this was a headache to find one of the solution:
If you trying to save an object, debug your it and inspect any of nested objects, for example: I'm sending approval.id: null, the object will give me below:
"approval":{
"class":"User",
"id":null
},
Which is trying to add a user with id null, whick wont find and wont save. So remove it from your json request.

ERROR : column "this_.date" must appear in the GROUP BY clause or be used in an aggregate function

ERROR: column "this_.date" must appear in the GROUP BY clause or be used in an aggregate function
Position: 296. Stacktrace follows:
org.postgresql.util.PSQLException: ERROR: column "this_.date" must appear in the GROUP BY clause or be used in an aggregate function
Position: 296
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2161)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1890)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:559)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:302)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
at grails.orm.PagedResultList.<init>(PagedResultList.java:53)
at grails.orm.HibernateCriteriaBuilder.invokeMethod(HibernateCriteriaBuilder.java:1511)
at com.rsa.ci.TestResultsService.getProductVersionsWithCriteria(TestResultsService.groovy:501)
at com.rsa.ci.TestResultsService.getBuildStatusHomePageResults(TestResultsService.groovy:568)
at com.rsa.ci.BuildStatusController$_closure11.doCall(BuildStatusController.groovy:219)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
code from line No. 501 where the error is pointing the line number
from -->
def reqProductVersions = TestRuns.createCriteria().list(max: reqNumberOfRecords, offset: startIndex) {
projections {
groupProperty "productVersion"
}
'in'("testType",filters.testTypes)
'in'("testSuiteName",suites)
eq("product",filters.product)
like("branch",filters.branch)
like("deploymentMode",filters.deploymentMode)
if(filters.tag){
isNotNull("tag")
ne("tag","")
}
if(!filters.jenkinsInstance.equals("%%")){
processedJenkinsRuns{
like("jenkinsServer",filters.jenkinsInstance)
}
}
cache true
order("date","desc")
}
// we need total count. createcriteria has issue when we ask total count with group property combined
def totalCount = TestRuns.createCriteria().get {
projections {
countDistinct "productVersion"
}
'in'("testType",filters.testTypes)
'in'("testSuiteName",suites)
eq("product",filters.product)
like("branch",filters.branch)
like("deploymentMode",filters.deploymentMode)
if(filters.tag){
isNotNull("tag")
ne("tag","")
}
if(!filters.jenkinsInstance.equals("%%")){
processedJenkinsRuns{
like("jenkinsServer",filters.jenkinsInstance)
}
}
cache true
}
def productVersionAndCount = [:];
productVersionAndCount.put("total",totalCount);
productVersionAndCount.put("productVersions",reqProductVersions);
return productVersionAndCount;
}
def getAllTemplateNames(def productVersions){
def templatesResults = ArtifactsInformation.findAllByP4ChangeListNumInList(productVersions);
Map<String, List<String>> templates = new HashMap<String, List<String>>();
templatesResults.each{ tmp ->
List<String> tempList = templates.get(tmp.p4ChangeListNum);
if(tempList == null){
tempList = new ArrayList<String>();
templates.put(tmp.p4ChangeListNum, tempList)
}
tempList.add(tmp.templateName);
}
return templates;
}
def getBuildStatusHomePageResults(int startIndex,int reqNumberOfRecords,BuildParamsDTO filters, def isCompareChecked){
**568 ->** def productVersionsAndCount = filters.junitAndSeleniumFilter?getProductVersionWithJunitAndSeleniumAndCriteria(filters,startIndex,reqNumberOfRecords):getProductVersionsWithCriteria(filters,startIndex,reqNumberOfRecords);
def productVersions = productVersionsAndCount.get("productVersions");
int totalRecords = productVersionsAndCount.get("total");
log.debug productVersions.toString()+" are selected as required product versions in getData"
Collections.sort(productVersions,Collections.reverseOrder());
Map<String, VersionDto> buildResults = new LinkedHashMap<String, VersionDto>();
productVersions.each{changeList ->
buildResults.put(changeList, new VersionDto(changeList))
}
if(productVersions.size() > 0){
getTestResults(productVersions, filters, buildResults);
}
def reqGroups = filters.testTypes;
def reqSuites =filters.testSuites ;
def dataToRender = [:]
dataToRender = buildDataTableObject(buildResults, reqGroups, reqSuites, filters, totalRecords, isCompareChecked);
return dataToRender;
}
Can anybody tell me what it actually means and why I'm getting this error.Pls
your criteria seems to be having common aggregation problem, your selected fields must appear in group by clause.
You can try defining 'date' in groupProperty otherwise you can make a sub-query to aggregate and then join with additional columns you want to show.
Take help from this answer
Hope this helps. Thanks
Could not find matching constructor for: com.rsa.ci.jsonDto.VersionDto(java.sql.Timestamp). Stacktrace follows:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.rsa.ci.jsonDto.VersionDto(java.sql.Timestamp)
at com.rsa.ci.TestResultsService$_getBuildStatusHomePageResults_closure27$$EPSZjAGS.doCall(TestResultsService.groovy:583)
at com.rsa.ci.TestResultsService$$EPSZjAAp.getBuildStatusHomePageResults(TestResultsService.groovy:582)
at com.rsa.ci.BuildStatusController$_closure11.doCall(BuildStatusController.groovy:219)
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:744)
TestResultService from Line 502
def reqProductVersions = TestRuns.createCriteria().list(max: reqNumberOfRecords, offset: startIndex) {
projections {
groupProperty "productVersion"
groupProperty "date"
}
'in'("testType",filters.testTypes)
'in'("testSuiteName",suites)
eq("product",filters.product)
like("branch",filters.branch)
like("deploymentMode",filters.deploymentMode)
if(filters.tag){
isNotNull("tag")
ne("tag","")
}
if(!filters.jenkinsInstance.equals("%%")){
processedJenkinsRuns{
like("jenkinsServer",filters.jenkinsInstance)
}
}
cache true
order("date","desc")
}
// we need total count. createcriteria has issue when we ask total count with group property combined
def totalCount = TestRuns.createCriteria().get {
projections {
countDistinct "productVersion"
}
'in'("testType",filters.testTypes)
'in'("testSuiteName",suites)
eq("product",filters.product)
like("branch",filters.branch)
like("deploymentMode",filters.deploymentMode)
if(filters.tag){
isNotNull("tag")
ne("tag","")
}
if(!filters.jenkinsInstance.equals("%%")){
processedJenkinsRuns{
like("jenkinsServer",filters.jenkinsInstance)
}
}
cache true
}
def productVersionAndCount = [:];
productVersionAndCount.put("total",totalCount);
productVersionAndCount.put("productVersions",reqProductVersions);
return productVersionAndCount;
}
def getAllTemplateNames(def productVersions){
def templatesResults = ArtifactsInformation.findAllByP4ChangeListNumInList(productVersions);
Map<String, List<String>> templates = new HashMap<String, List<String>>();
templatesResults.each{ tmp ->
List<String> tempList = templates.get(tmp.p4ChangeListNum);
if(tempList == null){
tempList = new ArrayList<String>();
templates.put(tmp.p4ChangeListNum, tempList)
}
tempList.add(tmp.templateName);
}
return templates;
}
def getBuildStatusHomePageResults(int startIndex,int reqNumberOfRecords,BuildParamsDTO filters, def isCompareChecked){
def productVersionsAndCount = filters.junitAndSeleniumFilter?getProductVersionWithJunitAndSeleniumAndCriteria(filters,startIndex,reqNumberOfRecords):getProductVersionsWithCriteria(filters,startIndex,reqNumberOfRecords);
def productVersions = productVersionsAndCount.get("productVersions");
int totalRecords = productVersionsAndCount.get("total");
log.debug productVersions.toString()+" are selected as required product versions in getData"
Collections.sort(productVersions,Collections.reverseOrder());
Map<String, VersionDto> buildResults = new LinkedHashMap<String, VersionDto>();
productVersions.each{changeList ->
buildResults.put(changeList, new VersionDto(changeList))
}
if(productVersions.size() > 0){
getTestResults(productVersions, filters, buildResults);
}
def reqGroups = filters.testTypes;
def reqSuites =filters.testSuites ;
def dataToRender = [:]
dataToRender = buildDataTableObject(buildResults, reqGroups, reqSuites, filters, totalRecords, isCompareChecked);
return dataToRender;
}
def getProductVersions(BuildParamsDTO filters){
def allProductVersions = TestRuns.createCriteria().list {
projections{ distinct "productVersion"}
eq("product",filters.product)
like("branch",filters.branch)
like("deploymentMode",filters.deploymentMode)
like("repo",filters.repo)
between("date", filters.firstDate,filters.lastDate)
processedJenkinsRuns{
like("jenkinsServer",filters.jenkinsInstance)
}
order("date","desc")
}
def returnArr=[];
allProductVersions.each{prodVersion ->
def insideArr=[];
insideArr.push(prodVersion)
returnArr.push(insideArr)
}
return returnArr;
}

Grails 3 "MissingMethodException" error on domain class save() method (and other methods)

Domain Class:
package com.myapp.gorm.log
import com.myapp.gorm.security.User
import com.myapp.gorm.system.TransactionJournal
class LogJournal {
static constraints = {
message nullable: false
category nullable: false
user1 nullable: false
}
static mapping = {
dateCreated column: "ts"
lastUpdated column: "ts_update"
}
LogMessage message
LogCategory category
User user1
User user2
String value
TransactionJournal transaction
Date dateCreated
Date lastUpdated
boolean equals(o) {
if (this.is(o)) return true
if (getClass() != o.class) return false
LogJournal that = (LogJournal) o
if (category != that.category) return false
if (dateCreated != that.dateCreated) return false
if (id != that.id) return false
if (lastUpdated != that.lastUpdated) return false
if (message != that.message) return false
if (transaction != that.transaction) return false
if (user1 != that.user1) return false
if (user2 != that.user2) return false
if (value != that.value) return false
return true
}
int hashCode() {
int result
result = message.hashCode()
result = 31 * result + category.hashCode()
result = 31 * result + user1.hashCode()
result = 31 * result + (user2 != null ? user2.hashCode() : 0)
result = 31 * result + (value != null ? value.hashCode() : 0)
result = 31 * result + (transaction != null ? transaction.hashCode() : 0)
result = 31 * result + dateCreated.hashCode()
result = 31 * result + (lastUpdated != null ? lastUpdated.hashCode() : 0)
result = 31 * result + id.hashCode()
return result
}
}
Error:
groovy.lang.MissingMethodException: No signature of method: c com.domainboost.gorm.log.LogJournal.save() is applicable for argument types: () values: []
Possible solutions: save(), save(boolean), save(java.util.Map), wait(), last(), any()
Or other domain classes work normally, only this one has a problem. I see grails cannot perform any method on this class instance.
There are no any validation errors.
Where I call this domain class (it's logback: appender):
class SystemAppender extends AppenderBase<ILoggingEvent> {
static appInitialized = false
#Override
public void append(ILoggingEvent event) {
if (appInitialized) {
LogMessage logMessage = LogMessage.findByMessage(event.getMessage())
if (!logMessage) {
logMessage = new LogMessage()
logMessage.message = event.getMessage()
logMessage.save(flash: true)
}
String categoryStr = event.argumentArray[0]
LogCategory logCategory = LogCategory.findByCategory(categoryStr)
if (!logCategory) {
logCategory = new LogCategory()
logCategory.category = categoryStr
logCategory.save(flash: true)
}
User user1 = null
if (event.argumentArray.contains(1)) {
user1 = event.argumentArray[1]
}
User user2 = null
if (event.argumentArray.contains(2)) {
user1 = event.argumentArray[2]
}
TransactionJournal tj = null
if (event.argumentArray.contains(3)) {
tj = event.argumentArray[3]
}
LogJournal logJournal = new LogJournal()
logJournal.category = logCategory
logJournal.message = logMessage
logJournal.user1 = user1
logJournal.user2 = user2
logJournal.transaction = tj
LogJournal.save()
}
}
}
And how I test this in grails console
import org.slf4j.Logger
import org.slf4j.LoggerFactory
def Logger logger = LoggerFactory.getLogger("sysLog")
logger.info("message", "category")
Error is on
LogJournal.save()
The code which ended with an error is in GormStaticApi.groovy
#CompileStatic(TypeCheckingMode.SKIP)
def methodMissing(String methodName, Object args) {
FinderMethod method = gormDynamicFinders.find { FinderMethod f -> f.isMethodMatch(methodName) }
if (!method) {
throw new MissingMethodException(methodName, persistentClass, args)
}
So it seems that method "save" is not found..
WTF ?
This
LogJournal.save()
Is looking for a static method on the class. You want a lower case initial letter to call save on the instance variable:
logJournal.save()

Clob field not populated in object in grailsChange changeset using grails DSL

I am making my first migration script that involves the use of the Groovy/Grails DSL. It looks like this:
import my.package.MyObject
import my.package.MyObjectUtil
import javax.xml.bind.DatatypeConverter
databaseChangeLog = {
changeSet(author: 'wheresjim', id: '1387238199-1') {
comment {'Sets the timestamp in each MyObject where null using the message text'}
grailsChange {
change {
MyObjectUtil myObjectUtil = new MyObjectUtil()
def criteria = MyObject.where {
isNull("timestamp")
}
def PAGESIZE = 10
int numRows = criteria.count()
int pages = Math.ceil(numRows / PAGESIZE)
(pages..0).each { page ->
int offset = PAGESIZE * page + PAGESIZE
def data = criteria.list(offset: offset, max: PAGESIZE, sort: 'id', order: 'asc')
data.each { MyObject myObject ->
Date timestamp = new Date(0L)
try {
def thisMessage = myObjectUtil.createMyObjectFromMessage(myObject.messageText)
String dateStr = thisMessage.messageIdentification?.timestamp
timestamp = dateStr ? DatatypeConverter.parseDateTime(dateStr).getTime() : timestamp
} catch (Exception e) {
// Do nothing, this will be logged in the finally which catches another error condition
} finally {
if (timestamp == new Date(0L)) {
log.warn "Error attempting to set timestamp in MyObject ${myObject.id}, setting to $eventDateTime"
}
}
myObject.timestamp = timestamp
myObject.save(flush: true)
}
log.warn "Updated ${myObject.id}"
}
}
}
}
}
The MyObject.messageText is a clob in the database, and to my knowledge, there has been no effort to lazily load it.
I should note that this exact script works (it can find the clob text) using the grails console plugin on the app.
In MyObject make sure your have the following lines:
static mapping = {
messageText type: 'text'
}

Criteria building in GORM

if (params.filters) {
def o = JSON.parse(params.filters);
def groupOp = o.groupOp
def fields = o.rules.field
def values = o.rules.data
def op = o.rules.op
println fields
println values
if(groupOp == "AND") {
fields.eachWithIndex {a, i ->
println op[i]
if(op[i].equals( "eq")) {
and{ eq(fields[i], values[i])}
}
if(op[i].equals("ne")) {
and{ ne(fields[i], values[i])}
}
if(op[i].equals("ge")) {
def valu = Double.valueOf( values[i]);
and{ ge(fields[i], valu)}
}
}
}
if(groupOp == "OR") {
fields.eachWithIndex {a, i ->
println op[i]
if(op[i].equals( "eq")) {
println 'eq';
or{ eq(fields[i], values[i])}
}
if(op[i].equals("ne")) {
println 'ne';
or{ ne(fields[i], values[i])}
}
if(op[i].equals("ge")) {
def valu = Double.valueOf( values[i]);
or{ ge(fields[i], valu)}
}
}
}
}
where params.filters is following JSON text.
{
"groupOp":"OR",
"rules":[
{
"field":"foo1",
"op":"le",
"data":"9.5"
},
{
"field":"foo2",
"op":"eq",
"data":"12345-123"
},
{
"field":"foo3",
"op":"cn",
"data":"IDM"
}
]
}
This data is coming from JQuery data grid.
Is there a better way of doing this?
In the code I have just listed only 3 operators, but in real I have 14 operations.
You can use String as Criteria operation, like:
A.withCriteria {
'eq' (id, 1)
}
so you might come to something like
A.withCriteria {
(groupOp) {
for (???) {
(op[i]) (fields[i], parsedVals[i])
}
}
}
Anyway you'll need to sanitize the web-submitted query for only allowed subset of operations. You don't want to receive end execute arbitrary sqlRestriction, right? :D So the code is going to be more complex then this anyway.
Note: wrapping and{} or or {} around single statement has no point, you need to put it around whole block of if-s.
I suggest that you have a look at the source code of the FilterPane plugin. Its service does essentially what you are doing and may give you some ideas for enhancements.

Resources