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

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()
}
}

Related

Spring Data Rest Binding

I am trying to work with Spring-Data-Rest, but I am hanging that Spring is not binding my body object given via Post.
My domain class looks like:
#Entity
#EqualsAndHashCode
#ToString
public class Rendite{
#Id #GeneratedValue Long id;
double jahresNettoMiete;
public Rendite(){}
}
#RepositoryRestResource(collectionResourceRel = "renditen", path = "renditen")
public interface RenditeRepositoryextends CrudRepository<Rendite, Long> {}
Calling the via Get works fine:
Calling the POST to save an entity calls the Application, too, but it doesnt bind the value to the property:
You appear to be missing getters (and optionally) setters on your entity.
Adding a public getter for the relevant field(s) should allow for both serlialization and deserialization.
See further on this here:
http://www.baeldung.com/jackson-field-serializable-deserializable-or-not
Unintuitively, the getter also makes the private field deserializable
as well – because once it has a getter, the field is considered a
property.
You can control serialization/deserialization in various ways as outlined in the article.
Another approach rather than adding getters would be to use:
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
as outlined in example 4.5 at the below:
http://www.baeldung.com/jackson-annotations

Grails 2.0 CreateCriteria private attribute cannot be queried

I'm trying to upgrade my app to Grails 2.0 and I face following problem. I have a private domain attribute with public getter. I'd like to query this attribute in createCriteria and it returns me: "Could not resolve property ..." exception even if the getter is public. I've seen a Jira bug http://jira.grails.org/browse/GRAILS-8498?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
but it's still not workin. Grails 1.3.7 worked fine.
My code is like:
Domain class
class MyClass {
protected boolean reserved = false
protected void setReserved(boolean reserved) {
this.reserved = reserved
}
public boolean getReserved() {
return this.reserved
}
}
Query
def c = MyClass.createCriteria()
def results = c.list {
eq('reserved', true)
}
May be the problem is that 'reserved' attribute name became a reserved keyword in grails because it seems that for other attributes of different names it works...
The problem here is that to enable domain class properties being automatically persistent without having to configure them, fields must be properties, i.e. they have to have a public getter/setter pair of the same type.
Groovy does this for you when you add a public field - it makes the field private and creates a public getter and setter. But if you have a getter or setter already it doesn't do that, and if they're not both public then they're not considered a property (in the JavaBean sense) so the field isn't persistent. So it's more than that the field isn't queryable - it's not even being stored or updated in the database.
After a few minutes of examination, I've realized that the problem is in the protected setter. If I set the setter to public, it works. It seems to be a Grails bug, and therefore I've risen grails bug, see:http://jira.grails.org/browse/GRAILS-8637

Action property of interface type

With my understading, the nature of a Action is that properties can be pushed w/ request parameter values. And, one wonderful feature is that Struts2 allows you to directly populate parameter values against Class type property ;)
Assuming there exists a Action and property class as below,
class Action extends ActionSupport {
User user;
#Action(value="hello" {#result=(.......)})
public void execute() {
........
}
.....
public void setUser(User user) {
this.user = user;
}
public User getUser() {
return this.user;
}
}
class User {
String name;
.....
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
you could populate User class property by doing like this.
http://...../hello.action?user.name=John or via jsp page
Then, I realize that there are actually people make an Action property as a Interface type. My question is what is the reason behind this. If there is a sample code demonstrating it will be great.
Thanks in advance!
Sorry, but your question does not make much sense.
To clarify:
"Properties": in Java a "property" of a class is something that is accesible via getter/setters method (setXXX() / getXXX() => property XXX), tipically (but not necessarily) corresponds to a private field.
In Struts2 you have an Action object and typically (not necessarily, not always) the properties are populated (set) from the request (via the "Parameters" interceptor), and later in the view stage read from the JSP (or whatever) page.
So, in your example, for the request http://...../hello.action?user.name=John , Struts2 would try to find in your action (...actually in your value stack) a property "user" which has a property "name", and try to set it (if the types are convertible). That is, he would try to call something like yourAction.getUser().setName("John") . Struts2 does not know -does not care- what type are the properties "User" or "Name", even if they are real fields or not. (They are expected to behaviour as "beans", though: i.e. they should have a default constructor).
Why and when you should code interfaces instead of concrete classes is something that is explained in any Java book, it's just a standard good practice and there are tons of pages about it. It has nothing to do with Struts2. In this context, for an Action, one is tipically only interested in doing so for some "service" fields, objects that are typically long-lived (perhaps singletons), are not instantiated by the action itself (nor by the request!). So, those interfaces are NOT the properties we are considering here, they ( usually ) are not exposed publically and usually are not populated nor read from the client.

ASP.NET MVC UpdateModel - fields vs properties?

I refactored some common properties into a base class and immediately my model updates started failing. UpdateModel() and TryUpdateModel() did not seem to update inherited public properties.
I cannot find detailed info on MSDN nor Google as to the rules or semantics of these methods. The docs are terse (http://msdn.microsoft.com/en-us/library/dd470933.aspx), simply stating:
Updates the specified model instance using values from the controller's current value provider.
SOLVED: MVC.NET does indeed handle inherited properties just fine. This turned out to have nothing to do with inheritance. My base class was implemented with public fields, not properties. Switching them to formal properties (adding {get; set; }) was all I needed. This has bitten me before, I keep wanting to use simple, public fields. I would argue that fields and properties are syntactically identical, and could be argued to be semantically equivalent, for the user of the class.
MVC will bind to properties of the inherited class. The model binder calls something like typeof(yourtype).GetProperties() which returns all the inherited members just fine.
Just tested it out with:
public class PersonBase
{
public string Name { get; set; }
}
public class User : PersonBase
{
public string FavoriteFood { get; set; }
}
"My assumption is the methods are reflecting on the top class only,"
How would that work? The "top" class IS the base class too.
this one made me curious too.
i made a edit form for a class Manager who derives from a Person
(after all, managers are persons too :-))
then in this action method
public ActionResult Edit(Manager manager )
{
return View(manager);
}
which wass called from a view with the Manager (derived type) as strong typed Model variable, when hovering the manager variable, it shows me the base class (it actually said: base: Person ) AND the one extra property for the manager
tried the formcollection too, and that also works:
public ActionResult Edit(FormCollection formCollection )
{
Manager manager = new Manager();
UpdateModel(manager );
return View(manager);
}

How can I exclude some public properties from being serialized into a JsonResult?

I have a custom viewmodel which serialized using a JsonResult. The ViewModel has some properties which have to be public, but at the same time these properties should not be visible in the resulting Json output.
I've already tried using the [NonSerialized] attribute, but that did not seem to have any effect.
Is there any simple way to do this? Or would I have to code my own result type (in which case I probably won't bother)?
You can put a [ScriptIgnore] attribute on the members that shouldn't be serialized. See ScriptIgnoreAttribute Class in MSDN for an example.
Just create an interface to return instead of a class.
public interface IMyViewModel {
string MyPublicProperty { get; set; }
}
Then create a class that inherits the interface
public class MyViewModel : IMyViewModel {
public string MyPublicProperty { get; set; }
public string MyNotSoPublicProperty { get; set; }
}
And return the interface, not the class, in the Controller Action
public JsonResult MyJson(){
IMyViewModel model = new MyViewModel();
return Json(model);
}
And the resulting JSON will be
{
'MyPublicProperty': ''
}
One of the challenges in client-side scripting is, that if you're changing your classes, you have no idea whether you're destroying the client-side implementation or not. If you use interface types in your JSON, you understand that if you change the interface, you're doing something that potentially may be killing the client side implementation. And it also saves you from double-checking the client side in vain if you're changing something that is NOT in the inteface (thus not being serialized).
Also, many times, your ViewModels might have large collections or complex types in them that you don't necessarily want to output to the client. These might take a long time to serialize or expose information that simply does not belong into the client code. Using interfaces will make it more transparent to know what is being in the output.
Also, using attributes such as [ScriptIgnore] on a property only applies to a specific scenario (JavaScript Serialization) forcing you to face the exact same problem if you're later serializing to XML for example. This would unnecessarily litter your viewmodels with tons of attributes. How many of them you really want in there? Using intefaces applies anywhere and no viewmodel needs to be littered with extra attributes.
Have a look at JSON.NET from James Newton-King. It'll do what you're looking for.
Extend the JavaScriptConverter class to not include properties with the NonSerializedAttribute. Then you can create a custom ActionResult that uses your JavaScriptConverter to serialize the object.
This creates a solid and testable class without having to (re)generate wrapper classes or using anonymous objects.
You can create a wrapper class that exposes only those properties that you want in the JsonResult. In the example below, Cow has 2 properties - "Leg" and "Moo". Suppose you want to only expose "Leg" as a property. Then
Dim cw as CowWrapper = New CowWrapper(c)
will return a wrapper class that only exposes "Leg". This is also useful for things like DataGridView if you only want to display some subset of the properties.
Public Class Cow
Public ReadOnly Property Leg() as String
get
return "leg"
end get
end Property
Public ReadOnly Property Moo() as String
get
return "moo"
end get
end Property
end class
Public Class CowWrapper
Private m_cow as Cow = Nothing
Public Sub New(ByVal cow as Cow)
m_cow = cow
end Sub
m_cow = cow
Public ReadOnly Property Leg() as String
get
return m_cow.Leg()
end get
end Property
end Class
Not exactly the answer you're looking for, but you can cheat Json() using the following code and anonymous classes:
MyModel model = ...;
return Json(new MyModel {model.Prop1, model.Prop2});
I needed the answer to this for ASP.NET Core 6.x and couldn't find it.
I finally found the answer and it is :
[System.Text.Json.Serialization.JsonIgnore]
Here's an example in a class
class Sample{
// Item will not be serialized
[System.Text.Json.Serialization.JsonIgnore]
String Item{get;set;}
// Count will be serialized
int Count{get;set;}
}

Resources