Grails: No signature of method findAll() is applicable for argument types: String, ArrayList - grails

I'm new to grails and receive the following error:
No signature of method: Something.findAll() is applicable for argument types: (java.lang.String, java.util.ArrayList) values: [from Something AS s WHERE s.some_number LIKE ?, [%asdf%]]"
The error occurs when I run test-app. It occurs in the following place:
SomethingVO[] findBySomeNumber(String searchString) {
searchString = "%"+searchString+"%"
return Something.findAll("from Something AS s WHERE s.some_number LIKE ?",[searchString]).collect {
new SomethingVO(it);
}
}
The class Something is a domain object:
package some.project.domain
class Something{
static belongsTo = [product:Product, productVersion:ProductVersion]
Long id
String name
String someNumber
static constraints = {
product (nullable:true)
productVersion (nullable:true)
}
}
Where is the mistake?
(I use Grails 1.2.4)

findAll is not mocked during unit testing and that's why your code isn't working. You need to manually add a mock for the call before running your test (mockFor could help you with that). This applies if your use HQL or Criterias (which I would recommend over pure HQL).
Alternatively it's possible that you could solve your problems using dynamic finders. Dynamic finders and the other dynamic ORM methods (save, get, count, ..) are in most(?) cases mocked when you call mockDomain(Something) in your unit test. They are also generally easier to use than HQL (imho).
Update:
Thanks to Fletch for pointing out that not all dynamic finders are mocked. An example of a dynamic finder that won't be mocked is this: Something.findAllWhereSomeNumberInList([1, 2, 3]).
The HQL you use in your code could be rewritten like this using dynamic finders:
Something.findBySomeNumberLike(searchString)

Xlson's answer is correct, however there is an alternative "cutting edge" solution you can try, which is currently in testing status. See http://grails.1312388.n4.nabble.com/New-approach-to-mocking-domain-classes-in-Grails-unit-tests-td2529895.html

Related

Grails GORM find by object property's property

I am looking for an easier grails way(if it exists) to achieve below:
My UserIntegration.groovy domain class:
class UserIntegration {
User user
Integration integration
// rest of code
}
My Integration.groovy domain:
class Integration {
SomeType type
// rest of code
}
My SomeType.groovy domain:
class SomeType {
String name
// rest of code
}
So basically what I need is a way so that I can find a UserIntegration which has Integration with type.name = "someTypeName"
In other words, I am looking for UserIntegration.findByIntegrationTypeName("someTypeName");
Obviously such a dynamic finder does not exist, but is there any easier groovier way to do it? I can currently find out all Integration objects with type = "someTypeName" and then use this integration in findAllByIntegration but looking for an easier solution if it exists, preferably a dynamic finder.
You can also use HQL to do same
def list = UserIntegration.executeQuery(from UserIntegration userInt
inner join fetch userint.integration integration
inner join fetch integration.type sometype
where sometype.name =:name,[name:'someTypeName'] )
UserIntegration.createCriteria().list(max:1){
'integration'{
'type'{
eq('name',"someTypeName")
}
}
}
Hope it works

Grails Criteria Projection - No signature of method projections() is applicable for argument types

As per Grails documentation
Grails also lets you write your domain model in Java or reuse an existing one that already has Hibernate mapping files. Simply place the mapping files into grails-app/conf/hibernate and either put the Java files in src/java or the classes in the project's lib directory if the domain model is packaged as a JAR. You still need the hibernate.cfg.xml though!
So This is exactley what i did.
I have used java domain model and hibernate.cfg.xml file for mapping. I also use
{DomainName}Constraints.groovy for adding Grails constraints. I also used to add functions to {DomainName}Constraints. For example, below is the content of my EmployeeConstraints.groovy
Employee.metaClass.static.findByDepartment = {depCode ->
createCriteria().list {
department{
inList ('code', depCode)
}
}
}
Now this works fine. But, when i add projection to it(code below), just to get the employee code.
Employee.metaClass.static.findByDepartment = {depCode ->
createCriteria().list {
projections { property('empCode', 'empCode') }
department { inList ('code', depCode) }
}
}
I get the below error..
" No signature of method: com.package.script142113.projections() is applicable for argument types.. "
Can someone point me to whats wrong with the code?
Thanks!
The property projection is used to return a subset of an object's properties. For example, to return just the foo and bar properties use:
projections {
property('foo')
property('bar')
}
You're getting an error because you've called the property method with 2 arguments instead of one.
By the way, I see another potential with your code. Grails will automatically create a dynamic finder findByDepartment that has the same name as the method your trying to add via the meta-class. I have no idea which one will take precendence, but I would suggest you avoid this potential problem and simplify your code, by adding this query using Grails' named query support, and call it something like getByDepartment so that the name doesn't class with a dynamic finder.
The answer by Dónal should be the correct one, but I found a strange behavior with grails 3.1. I got the same message using this call:
Announcement.createCriteria().list {
projections {
property('id')
property('title')
}
} .collect { [id: it['id'], title: it['title']] } // it['id'] not found
I fixed it by removing projections closure:
Announcement.createCriteria().list {
property('id')
property('title')
} .collect { [id: it['id'], title: it['title']] } // got the it['id']
Hope this help.

GORM mapping causes unit test to fail

I get a MissingMethodException when running a unit test due to the following line of code
class SystemNotification {
static mapping = {
read column: 'rd'
}
.
.
}
This is the relevant bit of the resulting stacktrace.
groovy.lang.MissingMethodException: No signature of method:
frontlinesms2.SystemNotification.read() is applicable for argument types: () values: []
Possible solutions: read(java.io.Serializable), load(java.io.Serializable), isRead(), create(), getId(), grep()
at frontlinesms2.SystemNotification._clinit__closure1(SystemNotification.groovy:6)
Removing the read->rd mapping allows the test to pass. Any thoughts on a way around this issue that does not necessitate removing the code? The domain class is from a plugin, if that's relevant. The plugin runs as a standalone app using h2, but the host application uses MySQL, where "read" is a reserved keyword, which is why we do the mapping to begin with.
Hmm so if you want column name change then you have to do following, currently you use read('x') as method:
class SystemNotification {
String read
static mapping = {
read column: 'rd'
}
}
And it is correct that test fails.

Strange behavior of gorm finder

In a controller I have this finder
User.findByEmail('test#test.com')
And works.
Works even if I write
User.findByEmail(null)
But if i write
User.findByEmail(session.email)
and session.email is not defined (ergo is null) it throw exception
groovy.lang.MissingMethodException: No signature of method: myapp.User.findByEmail() is applicable for argument types: () values: []
Is this behavior right?
If i evaluate "session.email" it give me null so I think it must work as it do when I write
User.findByEmail(null)
Even more strange....
If I run this code in groovy console:
import myapp.User
User.findByEmail(null)
It return a user that has null email but if I run the same code a second time it return
groovy.lang.MissingMethodException: No signature of method: myapp.User.findByEmail() is applicable for argument types: () values: []
You can't use standard findBySomething dynamic finders to search for null values, you need to use the findBySomethingIsNull version instead. Try
def user = (session.email ? User.findByEmail(session.email)
: User.findByEmailIsNull())
Note that even if User.findByEmail(null) worked correctly every time, it would not necessarily give you the correct results on all databases as a findBySomething(null) would translate to
WHERE something = null
in the underlying SQL query, and according to the SQL spec null is not equal to anything else (not even to null). You have to use something is null in SQL to match null values, which is what findBySomethingIsNull() translates to.
You could write a static utility method in the User class to gather this check into one place
public static User byOptEmail(val) {
if(val == null) {
return User.findByEmailIsNull()
}
User.findByEmail(val)
}
and then use User.byOptEmail(session.email) in your controllers.
Jeff Brown from grails nabble forum has identified my problem. It's a GORM bug. see jira
More info on this thread
This jira too
I tried with debugger and it looks it should be working, as you write. Maybe the groovy itself is a little bit confused here, try to help it this way:
User.findByEmail( session['email'] )

Grails GORM MissingMethodException with 1:N relationship

I have such domain classes:
class ServicesGroup {
Long id
String name
String description
String toString(){
return name
}
static mapping = {
version false
table 'root.services_groups'
id column:'group_id'
name column:'group_name'
description column:'group_desc'
}
}
and
class Step {
Long id
ServicesGroup service
String stepType
Integer stepFrom
Integer stepTo
static constraints = {
stepType(inList:['operator', 'client'])
}
static mapping = {
version false
table 'bill.steps'
service column:'service_group_id'
}
}
The relationship is - one ServicesGroup entry can have multiple Step instances.
However, when in my controller I try to
Step.findByService(3)
I get:
"org.codehaus.groovy.runtime.InvokerInvocationException: groovy.lang.MissingMethodException: No signature of method: Step.findByService() is applicable for argument types: (java.lang.Integer) values: {3}"
However, when I change Step domain class field
ServicesGroup service
to simply
Long service
it works.
What's going on here?
Try it that way:
Step.findByService(ServicesGroup.get(3))
Try
grails clean
grails run-app
Then try again.
Something like Step.findByService([id: 3]) may work. It only cares about the ID anyway for the purposes of the SQL generation. In a lot of cases like this you can toss a fake map into there rather than the real thing, and save yourself some performance.
On the other hand, the abstraction breaks down a bit when you do this.

Resources