I get the following error when I try to save a domain class, in grails:
No signature of method: java.lang.String.save() is applicable for argument types: () values: []
Possible solutions: size(), size(), take(int), wait(), any(), wait(long). Stacktrace follows:
I have a service that pareses an XML string into domain objects. I then try to save the domain and get that error. I've debugged and know that all the data is valid. Here is my code:
def newProfile="";
newProfile = new LinkedinProfile(
firstName : "${linkedinProfileFeed.'first-name'}",
lastName : "${linkedinProfileFeed.'last-name'}",
dobYear : "${linkedinProfileFeed.'date-of-birth'.'year'}",
dobMonth : "${linkedinProfileFeed.'date-of-birth'.'month'}",
dobDay : "${linkedinProfileFeed.'date-of-birth'.'day'}" ,
imgUrl : "${linkedinProfileFeed.'picture-url'}",
siteStandardAddress : "${linkedinProfileFeed.'site-standard-profile-request'}",
oAuthToken : accessTokenKey.toString(),
secretKey : accessTokenSecret.toString()
)
.id="${linkedinProfileFeed.id}".toString()
log.debug("${linkedinProfileFeed.id}".toString())
log.debug("${linkedinProfileFeed.'first-name'}")
log.debug("${linkedinProfileFeed.'last-name'}")
log.debug("${linkedinProfileFeed.'date-of-birth'.'year'}")
log.debug("${linkedinProfileFeed.'date-of-birth'.'month'}")
log.debug("${linkedinProfileFeed.'date-of-birth'.'day'}")
log.debug("${linkedinProfileFeed.'picture-url'}")
log.debug("${linkedinProfileFeed.'site-standard-profile-request'}")
log.debug(accessTokenKey.toString())
log.debug(accessTokenSecret.toString())
log.debug("end debug")
newProfile.save();
Also, I'm not to familiar with grails and springsource, but in .Net, I can access an objects properties using the dot operator. For example, if I had an object as described above, I could just type newProfile. and would have access to all the properties. In grails this doesnt happen. is this by design or an error in my code?
below is my domain class, as well.
class LinkedinProfile {
String firstName
String lastName
String dobYear
String dobMonth
String dobDay
String oAuthToken
String secretKey
String id
String imgUrl
String siteStandardAddress
Date dateCreated
Date lastUpdated
long version
static hasMany = [
linkedinLocation : LinkedinLocation,
linkedinSkill : LinkedinSkill
]
static mapping = {
cache true
id generator: 'assigned'
columns {
firstName type:'text'
lastName type:'text'
oAuthToken type:'text'
secretKey type:'text'
dobYear type:'text'
dobMonth type:'text'
dobDay type:'text'
imgUrl type:'text'
siteStandardAddress type:'text'
}
}
static constraints = {
firstName (nullable:true)
lastName (nullable:true)
oAuthToken (nullable:false)
secretKey (nullable:false)
dobYear (nullable:true)
dobMonth (nullable:true)
dobDay (nullable:true)
id (nullable:false)
imgUrl (nullable:true)
siteStandardAddress (nullable:true)
}
def beforeInsert = {
//to do: before insert, capture current email that is stored in the db
}
def afterInsert={
//resave email
}
}
The error indicates you are calling save() on a String. If we investigate, we see that you are. This is because you are assigning
newProfile = new LinkedinProfile().id="${linkedinProfileFeed.id}".toString()
and so newProfile is actually the String linkedinProfileFeed.id, not a new LinkedinProfile() as one might expect.
Compare
groovy> def foo = new Post().id="1"
groovy> foo.class
Result: class java.lang.String
with
groovy> def foo = new Post(id: "1")
groovy> foo.class
Result: class test.Post
You probably want to put the id into the constructor arguments. Regardless, you need newProfile to end up as a LinkedinProfile instance. Then you can call save() on it.
Also yes, you can use the dot operator in Groovy.
Related
Is there a way to set a constructor optional param?
I mean something like:
User.fromData(this._name,
this._email,
this._token,
this._refreshToken,
this._createdAt,
this._expiresAt,
this._isValid,
{this.id});
It indicates that
Named option parameters can't start with an underscore.
But I need this field as private, so, I'm lost now.
This is a more general answer for future viewers.
Positional optional parameters
Wrap the optional parameter with [ ] square brackets.
class User {
String name;
int age;
String home;
User(this.name, this.age, [this.home = 'Earth']);
}
User user1 = User('Bob', 34);
User user2 = User('Bob', 34, 'Mars');
Optional parameters need to be nullable if you don't provide a default value:
class User {
String name;
int age;
String? home; // <-- Nullable
User(this.name, this.age, [this.home]);
}
Named optional parameters
Wrap the optional parameter with { } curly braces.
class User {
String name;
int age;
String home;
User(this.name, this.age, {this.home = 'Earth'});
}
User user1 = User('Bob', 34);
User user2 = User('Bob', 34, home: 'Mars');
The default for home is "Earth", but like before, if you don't provide a default then you need to change String home to String? home.
Private fields
If you need private fields then you can use [] square brackets:
class User {
int? _id;
User([this._id]);
}
User user = User(3);
or do as the accepted answer says and use an initializer list:
class User {
int? _id;
User({int? id})
: _id = id;
}
User user = User(id: 3);
Named required parameters
Named parameters are optional by default, but if you want to make them required, then you can use the required keyword:
class User {
final String name;
final int age;
final String home;
User({
required this.name,
required this.age,
this.home = 'Earth',
});
}
User user1 = User(name: 'Bob', age: 34);
User user2 = User(name: 'Bob', age: 34, home: 'Mars');
You need to use a simple parameter and initialize your private field in initializer list.
class User {
final String _id;
final String _name;
User.fromData(this._name, {required String id})
: _id = id;
}
In addition to great Suragch's answer I wanted to mention required word. You can use it for multiple constructor or function named parameters to specify required ones.
class User {
int _id;
String _firstName;
String _lastName;
User({required int id, String firstName = "", String lastName})
: _id = id, // required parameter
_firstName = firstName, // optional parameter with default value ""
_lastName = lastName; // optional parameter without default value
}
User user1 = User(id: 1);
User user2 = User(id: 2, firstName: "John");
User user3 = User(id: 3, lastName: "Snow");
Related Dart docs here.
For Dart version <= 2.10 #required is an annotation and used with the # prefix.
How to use a String value as a parameter in findById(), It always expecting a Long value. Iam using a domain class named Employee and I configured its id key as string. But still Employee.findById() is expecting a long value as parameter.
Please help me
My Employee.groovy
class Employee {
static hasOne = [user:User, vpn:Vpn, tenrox:Tenrox, machine: Machine, dbuser:DbUser];
static mapping = {
version false
id generator: 'assigned',type: 'string'
}
String name
String designation
String team
Long contact_no
static constraints = {
name(nullable: false,maxSize:100)
designation(nullable: true,maxSize:40)
team(nullable: true,maxSize:40)
contact_no(nullable: true,maxSize:20)
}
}
Declare your id field in the domainclass as String.
class Employee {
static hasOne = [user:User, vpn:Vpn, tenrox:Tenrox, machine: Machine, dbuser:DbUser];
static mapping = {
version false
id generator: 'assigned',type: 'string'
}
String id // Declares id as String
String name
String designation
String team
Long contact_no
static constraints = {
name(nullable: false,maxSize:100)
designation(nullable: true,maxSize:40)
team(nullable: true,maxSize:40)
contact_no(nullable: true,maxSize:20)
}
}
I am very new to json
Am having a json file in URL which is,
and am getting all the data into a list as below
System.Net.WebClient wc = new System.Net.WebClient();
string json = wc.DownloadString("http://192.168.1.7:90/eawebportal/poc/elements/index");
List<JsonFormat> myDeserializedObjList = (List<JsonFormat>)Newtonsoft.Json.JsonConvert.DeserializeObject(json, typeof(List<JsonFormat>));
and am getting the list in myDeserializedObjList .Where JsonFormat is a class as below
public class JsonFormat
{
public string guid;
public string type;
public string name;
}
My expected OUTPUT is:
guid= 1-1-1-1-1-1-1 , type= Requirement , name = element name
guid= 2-2-2-2-2-2-2 , type= Requirement , name = element name
but it give output as
guid= 539fe407-b5c8-4e02-ba7a-1410c0a80107 , type= Requirement , name = element name
guid= 539fe407-c0b8-4301-bf22-1410c0a80107 , type= Requirement , name = element name
Why its comin so..??
If I use completely hardcoded data in a console application, it works as expected (see below). So, either the downloaded data file is different than you're showing, or else you have something else in your code that is changing it.
class Program
{
{
string json = #"
[
{ ""guid"" : ""1-1-1-1-1-1-1"", ""type"" : ""Requirement"", ""name"" : ""element name"" },
{ ""guid"" : ""2-2-2-2-2-2-2"", ""type"" : ""Requirement"", ""name"" : ""element name"" },
{ ""guid"" : ""3-3-3-3-3-3-3"", ""type"" : ""Requirement"", ""name"" : ""element name"" },
{ ""guid"" : ""4-4-4-4-4-4-4"", ""type"" : ""Requirement"", ""name"" : ""element name"" }
]";
List<JsonFormat> list = JsonConvert.DeserializeObject<List<JsonFormat>>(json);
foreach (JsonFormat jf in list)
{
Console.WriteLine("guid: " + jf.guid);
Console.WriteLine("type: " + jf.type);
Console.WriteLine("name: " + jf.name);
Console.WriteLine();
}
}
public class JsonFormat
{
public string guid;
public string type;
public string name;
}
}
Output:
guid: 1-1-1-1-1-1-1
type: Requirement
name: element name
guid: 2-2-2-2-2-2-2
type: Requirement
name: element name
guid: 3-3-3-3-3-3-3
type: Requirement
name: element name
guid: 4-4-4-4-4-4-4
type: Requirement
name: element name
I am currently working on a grails application. I have two command objects (AccountInfoCommand and EducInfoCommand) in a controller. On my EducInfoCommand, I wanted to check if the yearGraduated property is earlier than the set birthDate(a property of AccountInfoCommand) on its validator constraints. How will I do that?
This is my code for my AccountInfoCommand:
class AccountDetailsCommand implements java.io.Serializable {
String username
String password
String confirmPassword
String emailAddress
Date birthDate
}
This is my code for EducInfoCommand:
class EducInfoCommand implements java.io.Serializable {
Integer graduated
EducationLevel educationLevel
String schoolName
String yearGraduated
String honorsReceived
}
static constraints = {
yearGraduated nullable: false, maxSize:4, blank: false, matches: /([0-9]*)/,
validator: {
Date.parse('yyyy',it) <= new Date() ? true : false
}
}
Please help!
Thanks!
You need some reference to which AccountDetails the EducInfo is for. For example, if you added a username field to the EducInfoCommand you could look up the account details from that (assuming there is an AccountDetails gorm object which is similar to the command object):
class EducInfoCommand implements java.io.Serializable {
String yearGraduated
String username
// ...
}
static constraints = {
yearGraduated nullable: false, maxSize:4, blank: false, matches: /([0-9]*)/,
validator: { val, obj ->
Date.parse('yyyy',val) > AccountDetails.findByUsername(obj.username).birthDate
}
}
I have a grails unit test that has code similar to below and is appears that setting fields via getter/setter methods doesn't work with constructors (even though it actually works with non-domain classes).
I understand that the following works with properties:
class Person {
def firstName
def lastName
def getFullName() {
return "$firstName $lastName"
}
def setFullName(name) {
firstName = name.split(" ")[0]
lastName = name.split(" ")[1]
}
}
def = new Person(fisrtName: "Joe", lastName: "Bloggs")
But when I do the following the first and last name fields don't get set:
def = new Person(fullName: "Joe Bloggs")
Is there a way to set fields via methods in a groovy contstructor?
What version of groovy are you using? This works fine for me with groovy 1.8.6 and I think it's worked for that way for a very long time:
class Person {
def firstName
def lastName
def getFullName() {
return "$firstName $lastName"
}
def setFullName(name) {
firstName = name.split(" ")[0]
lastName = name.split(" ")[1]
}
}
def p1 = new Person(firstName: "Joe", lastName: "Bloggs")
def p2 = new Person(fullName: "Joe Bloggs")
assert p1.firstName == p2.firstName
assert p1.lastName == p2.lastName
Updated:
Just tried this on grails 2.0.3. You need to be more explicit in your method signatures for grails to work. I changed the method signature for the getter to be String and the setter to be void and it worked. It did not work with just def. Grails 2 is much more strict about matching signatures than previous versions of grails were and I'm betting that this is part of it.
Also, you should specify that the fullName "property" is transient as it isn't a real property that should get persisted in the database. Here's the domain and test class that work for me in grails 2.0.3:
Person.groovy:
package com.example
class Person {
String firstName
String lastName
static transients = ["fullName"]
String getFullName() {
return "$firstName $lastName"
}
void setFullName(String name) {
firstName = name.split(" ")[0]
lastName = name.split(" ")[1]
}
}
PersonTests.groovy:
package com.example
import grails.test.mixin.*
import org.junit.*
/**
* See the API for {#link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions
*/
#TestFor(Person)
#Mock([Person])
class PersonTests {
void testFullName() {
Person p1 = new Person(firstName: "Joe", lastName: "Bloggs").save(failOnError: true)
Person p2 = new Person(fullName: "Joe Bloggs").save(failOnError: true)
assert p1.firstName == p2.firstName
assert p1.lastName == p2.lastName
assert p1.fullName == p2.fullName
}
}
This is caused by because
See 'bindable' here