Check property is present by property name - grails

I want to check is a string contains the name of a valid property of one of my entity class.
I've figured several keys but at the end i've been unable to make them work and even not sure what it the best practice to do this.
Thanks in advance

Every Grails domain object has an injected domainClass property which exposes a persistentProperties list. You can access the list of properties in this way:
def o = new MyDomain()
o.domainClass.persistentProperties
You can also retrieve this list from the Spring application context, which avoids the need for a domain class instance. Among the Spring beans created for each domain class (four beans for each domain) there is one that has the full name of your domain class with the suffix {{DomainClass}}. Assuming grailsApplication has been injected:
grailsApplication.mainContext.getBean("MyDomainDomainClass").persistentProperties
Within the persistentProperties list, you can search for a property with a given name as follows:
persistentProperties.find { it.name == nameToSearchFor }

Finally i decided to go with
MyClass.metaClass.properties.find { it.name == params.searchedColName }
I think is little better solution than #Andrew von Dollen proposal since i avoid playing with the spring context ... feel that is more groovier this way.

Related

Grails new Domain object with property map not setting property

EDIT: Per my answer below, this seems fixed by a "grails clean". You bang your head in frustration and you overlook the obvious sometimes.
For some time we've had the following structure of domain objects:
abstract class Company {
String name
...
}
and multiple children similar to the following all with different "owner" objects. Each concrete class has it's own table in the DB.
class CompanyChild extends Company {
static belongsTo = [owner:SomeDomain]
...
}
I'm adding another property to the abstract parent for various reasons, so the parent now looks more like the following (CompanyType is an enum):
abstract class Company {
String name
CompanyType companyType
...
}
This all seems pretty straightforward. Now in company service, somewhere I'm doing this:
log.debug("Saving new company type=$companyType")
def company= new Company(name: 'Acme', companyType: companyType, <other properties here>)
log.debug("company object has type=${company.companyType}")
The log shows...
CompanyService Saving new company type=NONPROFIT
CompanyService company object has type=null
What the heck is happening here? It really seems like ${company.companyType} should not be null.
If I add
company.companyType = companyType
after the object is created it works, but there's something I'm failing to understand.
Edit: grails version is 2.3.11
Sometimes you focus so much on a problem that you don't step back and thing... maybe I need to do a full "grails clean"...
Clean and recompile seems to have been my answer.

can we have multiple aliases for a Domain Class Attribute in grails

I have many domain classes in my application an for Audit logging I need the name attribute of each Domain class. unfortunately the name attribute is not generic in all Domains.
In my Audt log class I get the type of object modified/created/deleted and then save the id right now (which is common code since all domains have 'id' attribute) but now if I want to get the name attribute out of the domain from the ID, each domain has a different name attribute, like Resource Domain has resourceName, User domain has userName and so on... soI will have to handle each domain seperately (like have a map or bunch of switch statements for getting the name attribute from the Domain class name).
Is there a way I can have an alias mapping for each domain class's name field to be called 'name' . there should not be any change to the actual attributes in the Domains in whatever changes I do, I can add a column to Audit Domain but not other table changes.
Thanks in Advance
I don't think that there's any way to do this automatically.
As you guessed, you're going to either have to change all of the domain objects so that they have a 'name' attribute, or somehow maintain a map of which attribute in each class is to be considered the 'name'.
I suppose that one answer might be to add a getName() method to each of the domain classes, and return the appropriate value from that method.
If you really don't want to modify the domain objects at all, you can use groovy meta-object programming (MOP) to inject this method into each domain class from the BootStrap class.

ASP.NET MVC Global.asax Shared Property

Is it alright to hang a shared property off of the global.asax (MvcApplication class)?
And then access it like so in other area:
MvcApplication.[SharedPropertyName]
Edit
What I am trying to do is have a globally accessible property that is my application settings.
I am using an XmlSerializer to serialize/deserialize an object that holds all of these properties. It works great, but the Load method on the ApplicationSettings is shared and returns an instance of the ApplicationSettings, so some of the other ideas people have suggested around singelton is not going to work. Here is the ApplicationSettings class:
Public Class ApplicationSettings
#Region "Members/Properties"
Public Property Property1 As String
Public Property Property2 As String
...
#End Region
#Region "Methods"
Public Shared Function GetFilePath() As String
Return HttpContext.Current.Server.MapPath("/Bin/Settings.config")
End Function
Public Shared Function Load() As ApplicationSettings
Try
Dim Serializer As XmlSerializer
Dim Settings As ApplicationSettings
Using Reader As New StreamReader(GetFilePath)
Serializer = New XmlSerializer(GetType(ApplicationSettings))
Settings = CType(Serializer.Deserialize(Reader), ApplicationSettings)
Reader.Close()
End Using
Return Settings
Catch ex As Exception
'Return New ApplicationSettings
Return Nothing
End Try
End Function
Public Sub Save()
Dim Serializer As XmlSerializer
Using Writer As New StreamWriter(GetFilePath, False)
Serializer = New XmlSerializer(GetType(ApplicationSettings))
Serializer.Serialize(Writer, Me)
Writer.Flush()
Writer.Close()
End Using
End Sub
#End Region
End Class
Not recommended. If you need a globally accessible variable or property, that's more suited to a base class that your classes inherit from.
This link gives an example of a controller base class.
EDIT:
Based off your edit, it's tough to recommend something specific because how those settings are used can drive your approach. Here's some general tips:
I'd split out your settings into a series of base classes that are distinct in their area of concern. So settings regarding FunctionalityX lives within the class dealing with FunctionalityX.
I'd leverage your web.config. I'm sure you're already doing this, but just make sure that you're not duplicating configuration efforts. The Web.Config is the right place for most of it and you can add more. Classes already exist for pulling configuration information out of the web config.
Alright, with that having been said, barring those two paths:
I'd set your class to static so you can just reference your class from anywhere without instantiation like this: ApplicationSettings.SettingValue.
I'd have explicit settings properties on your ApplicationSettings class and reference them directly that way. If they aren't instantiated, you can lazy load them from the XML as they are needed.
I'd cache your settings if they aren't dynamic.
So there's some general tips that might yield a better solution. It's hard to recommend something concrete without further information on how it'll be used.
FINAL EDIT:
After some discussion in the comments below, we found that this resource here fixed the OP's issue:
http://haacked.com/archive/2007/03/12/custom-configuration-sections-in-3-easy-steps.aspx
I would say no. There likely is a better way to do what you are attempting to do.

Grails Plugins Requiring External Relationships

I posted this on the Grails mailing list yesterday and haven't had any hits. Figured I'd try here as well today.
I'm considering writing a grails plugin but this plugin would require some sort of relationship to an account / user object. However, I don't want to force a particular security model on the plugin. For example, say was writing a comment system plugin (I'm not). I'd have a comment object...
class Comment {
String comment
Date dateCreated
// etc etc
}
The comment is missing a couple of things:
Who added the comment
What the comment was added to.
I'd like to first focus on #1. So someone might be using the Spring security plugin and use the default Person object, or maybe they changed that to User. Who knows. Is there any way that anyone can think of to configure that relationship without hard coding it in the plugin?
One thing I've thought about was to have the grails app extend the plugin's domain classes to add this relationship. so I might do something like...
class ArticleComment extends Comment {
static belongsTo = [user:User]
}
But in a larger plugin, that might be a lot of inheritance requirements. Not the end of the world, but just looking for other possible options.
You can use the same technique employed by the Commentable plugin:
The user of your plugin will need to declare a closure in Config.groovy to evaluate the logged user:
grails.myplugin.user.evaluator = { session.user }
And you can use something like this in your plugin's code to call the user configured closure:
def evaluateUser() {
def evaluator = grailsApplication.config.grails.myplugin.user.evaluator
def user
if(evaluator instanceof Closure) {
evaluator.delegate = this
evaluator.resolveStrategy = Closure.DELEGATE_ONLY
user = evaluator.call()
}
if(!user) {
throw new Exception("No [grails.myplugin.user.evaluator] setting defined or the evaluator doesn't evaluate to an entity. Please define the evaluator correctly in grails-app/conf/Config.groovy")
}
if(!user.id) {
throw new Exception("The evaluated user is not a persistent instance.")
}
return user
}
I think you can do it like SpringSecurity do. Instead of let people extend your Comment class, You can write 2 class CommentUser & CommentPlace; then let others extends them. I think it's more simple.

Retrieving a list of GORM persistent properties for a domain

What's the best/easiest way to get a list of the persistent properties associated with a given GORM domain object? I can get the list of all properties, but this list contains non-persistent fields such as class and constraints.
Currently I'm using this and filtering out the list of nonPersistent properties using a list I created:
def nonPersistent = ["log", "class", "constraints", "properties", "errors", "mapping", "metaClass"]
def newMap = [:]
domainObject.getProperties().each { property ->
if (!nonPersistent.contains(property.key)) {
newMap.put property.key, property.value
}
}
There seems like there must be a better way of getting just the persistent properties.
Try this:
import org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass
...
def d = new DefaultGrailsDomainClass(YourDomain.class)
d.persistentProperties
Here's a link to the Grails API for GrailsDomainClass (it's a link to an older version; I couldn't find a newer one after some quick searches). It's got a getPersistentProperties() (used in the code snippet above). You can traverse the API documentation to see what other methods might be useful to you.
If you want an example, do a grails install-templates and then look at src/templates/scaffolding/create.gsp. There's a block in there where it iterates over the persistent domain properties.
Now (strarting Grails 2.x) you don't even have to instantiate new DefaultGrailsDomainClass(...) and avoid unnecessary code executions. All domain class objects have injected property domainClass:
def domainObject = new YourDomain()
domainObject.domainClass.persistentProperties
Or, if you haven't domain class object, you can get DefaultGrailsDomainClass from application context by domain class name - each domain class has a DefaultGrailsDomainClass registered as a Spring bean. So you can use, for example, Holders (assuming your domain class name is 'Foo'):
def defaultGrailsDomainClass = Holders.applicationContext.getBean("FooDomainClass")
defaultGrailsDomainClass.persistentProperties
As of grails 3.3.0
All code that uses the GrailsDomainClass or GrailsDomainClassProperty classes should be re-written to use the mapping context api.
To get started, inject the grailsDomainClassMappingContext bean. See the api documentation for more information on the MappingContext, PersistentEntity (GrailsDomainClass), and PersistentProperty(GrailsDomainClassProperty)
For example:
class MyService {
def grailsDomainClassMappingContext //inject
def accessDomainProperties(Class clazz) {
PersistentEntity entityClass = grailsDomainClassMappingContext.getPersistentEntity(clazz.name)
List<PersistentProperty> persistentPropertyList = entityClass.persistentProperties
persistentPropertyList.each { property ->
println property.name
}
}
}
Hope this helps someone.

Resources