Angular JS and Grails REST Service - grails

I am creating a simple web app using groovy-grails and angular JS. I have 4 domain objects (Developer, Tester, Programmer) that all extend Person. In my bootstrap.groovy file, I have created new Developers, Testers, and Programmers, but when I run my app, it doesn't populate the table with whats in the Bootstrap.Groovy file. Whenever I take (extends Person) off of the class header, and add String firstName, then it finds the name of the Developer, Tester and Programmer. I also tried extending an abstract Person class (not a domain object), and that failed as well. See Below:
//domain object
class Person{
int id;
String firstName;
String lastName;
}
//domain object, non working copy
class Developer extends Person{
}
//domain object, working copy
class Developer{
int id;
String firstName;
String lastName;
}
//Boostrap.groovy
new Developer(id: 2, firstName: 'Foo', lastName: 'Ninja');
Thanks,
Butler_Alfred

Try removing the id from your domain classes. Grails adds this field for you implicitly.
Also, when you create a new Developer instance in Bootstrap.groovy, don't pass in your own id. One will be automatically set when the developer instance is persisted.
Developer developer = new Developer(firstName: 'Foo', lastName: 'Ninja')
assert developer.id == null // id is null before save
developer.save()
assert developer.id != null // id is assigned after save

Related

Grails application design

In Grails application i have EmploymentSeeker domain as below :
class EmploymentSeeker {
String fullName
String expYears
Boolean haveDrivingLic
String gender
String eduQualification
String courses
String currentTitle
int age
}
I want to make the user in the create view to add previous references. user may add up to 4 references , but I don't know how to do it - shall I create Emp references domain and link it to employment seeker domain static belongsTo?

Why do scope modifiers on fields in domain classes prevent validation?

I'm just starting with Grails (coming from Rails) and I noticed that Grails really doesn't seem to like scope modifiers on fields in domain classes.
I had understood that all unscoped fields in a domain class were by default public, but if you actually declare it public, Grails won't validate it.
class Person {
public String firstName
public String middleName
public String lastName
}
If you add a constraint, Grails will throw a NotReadablePropertyException exception when you call validate()
class Person {
public String firstName
public String middleName
public String lastName
static constraints = {
middleName nullable: true
}
}
However if you take out the public declaration, everything works normally.
Can someone explain what's going on behind the scenes with the scoping in domain classes? Hard to understand why explicitly declaring something public which is already public would break the framework. I'm guessing you wouldn't want to declare anything 'private' either, although it would be nice if there was away that a fields which shouldn't be manipulated directly could be hidden from consumers of the domain class.
When you add a field to a Groovy class without a scope modifier, it's more that it's inferred to be public than being actually public. The compiler converts the field to a private field and generates a public getter and a setter for it, although it won't overwrite a getter or setter that you wrote. This is convenient because you can later write getters and/or setters to implement business logic and not affect the callers.
But a public field (declared as 'public') is just that - a public field. There's no generated getter or setter. I recommend using a decompiler to see this in action - create a simple POGO in src/groovy, e.g.
class Thing {
String realProperty
public String fieldButNotProperty
}
and open up the .class file with http://jd.benow.ca/ or another decompiler.
GORM automatically assumes that typed properties are persistent unless you exclude some with the transients list. The type is required so it knows how to persist the data, and properties like def name will be ignored. Properties in this sense are similar to JavaBean properties - a matched getter/setter pair.
Hibernate has no support for Groovy and doesn't know what's going on under the hood - it just calls your getters and setters to set and access field data during persistence. So the Groovy compiler adding those in makes it easy for POGOs in Grails to be persisted by Hibernate. And you could do this yourself - add in a getter and setter with correct names and data type (e.g. String getName() and void setName(String name) and it will be treated as a persistent property, even if you do nothing with the values.
The reason for the NotReadablePropertyException is that there's no getter to call for your 'property'. Even though your fields are perfectly accessible, you've effectively hidden them from GORM and Hibernate.
If you add a constraint, Grails will throw a NotReadablePropertyException exception when you call validate()
Never noticed this before, sounds like a bug
it would be nice if there was away that a fields which shouldn't be manipulated directly could be hidden from consumers of the domain class.
If you want to prevent direct access to a property, simply add a getter and setter. In the (contrived) example below, I ensure that name is always read/written as an upper case string.
class Person {
public String firstName
public String middleName
public String lastName
public void setFirstName(String name) {
this.firstName = name.toUpperCase()
}
public String getFirstName() {
return this.firstName.toUpperCase()
}
}

Unique key parts not showing in Create Form Grails

I have following Domain Class -
class xyz {
String name
String version
String vclass
Date dateCreated
static constraints = {
version(blank:false)
name (unique: ['version'])
}
static hasMany = [ yz: Yz ]
}"
when i create a record for it, i don't see an option to enter version, only name and vclass. Why?
In Grails, version is a special property of Domain classes used for optimistic locking. Rename your property to something other than version. You can read more about this in the user guide.

Grails SpringSecurity User Object

I have a basic Grails 2 application which I setup along with the SpringSecurityCore plugin. This seems to be working fine. However, when I try to add additional properties to my User.groovy file by way of an extended class, I cannot seem to reference those properties in my controllers.
To better illustrate this problem, please take a look at my basic class which extends the User.groovy:
UserInfo.groovy:
class UserInfo extends User {
String firstname
String lastname
}
On my page where I want to reference the current user's firstname, I am simply writing a method as follows:
def index() {
def uname = springSecurityService.currentUser.username
def firstname = springSecurityService.currentUser.firstname
render uname
}
This works fine for rendering the username, and I believe that this is because the username is referenced in the base User.groovy file:
class User {
transient springSecurityService
String username
String password
However, the above "def index()" method fails when I try to define the firstname as part of the springSecurityService.currentUser.firstname.
If I inject extra properties into the base User.groovy class, then I can reference them by way of springSecurityService.currentUser.[property]
To illustrate this:
class User {
transient springSecurityService
String username
String password
String firstname
...
I am then able to reference the firstname property of my user in the aforementioned index method.
Is it possible to reference the extended properties of my User without injecting values in the base User class? My goal here is to try and keep the User class as clean as possible while still being able to call upon the values referenced in the UserInfo.groovy file.
Thank you in advance for your time.
If you really need to put some properties of your User information into another domain and want those properties could still be accessed from springSecurityService.currentUser, you have to implement your own UserDetailsService to package the UserInfo properties with User.
If you extend the User class, the SpringSecurity plugin does not know anything about your extended class UserInfo.
If you call springSecurityService.currentUser you get an instance of User not of UserInfo - so you don't have the property firstname.
If you don't like to add several new properties to User you could add a reference to the UserInfo class.
class UserInfo {
static belongsTo = [user: User]
String firstname
String lastname
...
}
class User {
...
UserInfo userInfo
...
}
You should remember that this reference adds an extra table to your database, which causes an additional join operation if you want to access your user instance.
When you initially install the Spring Security plugin and created your User class, it should have added some properties in Config.groovy that tells it which class to use as the default user class. When extending the default User class, you should update the property in Config.groovy to reflect this. The property you are looking for to update (or add if it's not there) is the following:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'your.package.UserInfo'
There are about a handful of properties in this page that relate to User and Role/Authorities that you may want to update if you extend/update any of the defaults.

EntityFramework 4.3 Supertype Late Initialization

I'm using EF 4.3 with CodeFirst and I have a supertype/subtype model similar to this one:
public Person {
long Id { get; set; }
[Required]
string Name { get; set; }
}
public Costumer : Person {
string SomeData { get; set; }
[Required]
string SomeRequiredData { get; set; }
}
This is a simplified version of the problem. The tables have several fields.
A person can be a "promoted" to Costumer later in the application. So Person is created first and then transformed to Customer.
The question is: After I create Person how can I "promote" it to Vendor without creating (or recreating) a new Person record?
If I do:
var costumer = new Costumer {
Id = [same id used before when Person was created],
SomeRequiredData = "Data"
};
The model gives an error saying that Name is required. I should not be required to repeat all required info from Person in the new Vendor instance since it's already there in the original Person record.
Can anybody help?
P.S. The model is configured to create 2 separate tables, one for each class...
After I create Person how can I "promote" it to Vendor without
creating (or recreating) a new Person record?
You most can't with EF because you cannot change the type of existing instance (you cannot cast Person to Customer). Because you cannot cast the entity you also cannot update its type in the database with EF. In the same time you cannot insert Customer instance with existing Id because this operation expect inserting both parent and child type (remember Customer is a Person in your model and because of that inserting Customer means inserting Person as well).
The reason why it doesn't work is that your domain model is wrong. You should not have Customer as subtype of the Person because in OOP it means exactly what happened now - you cannot change person to customer without creating a new person instance (because customer is a person). To support this scenario you must have only Person entity and this entity must have property describing its type.

Resources