Grails 3.3: transient properties and GrailsDomainClassProperty - grails

Contemplating upgrade of a plugin from Grails 3.2.11 to Grails 3.3.2 while accomodating the slashing change in the domain class API. PersistentProperty replaces GrailsDomainClassProperty but has no isPersistent() method.
How do I find out programmatically if a domain class property is transient? Does PersistentEntity return transient properties at all?
(I tend to use transient properties a lot. Great for productivity.)

PersistentEntity.getPersistentProperties() will give you list of properties to be persisted - meaning it doesn't include transient properties. You can try:
GrailsClassUtils.getStaticPropertyValue(MyDomain, "transients")?.contains("myPropertyName")

Related

Grails 4 replacement for DefaultGrailsDomainClass?

I'm recreating a working Grails 2.2.5 application in Grails 4 in order to get to know the new version (with the view to migrating all 2.2.x apps over in due course). So far I've only moved a handful of Groovy classes from the src directory over, but I'm running into a compile problem with a class which is apparently no longer present in Grails 4, org.codehaus.groovy.grails.commons.DefaultGrailsDomainClass. I use this to iterate through the persistent properties of a domain class (with persistentProperties). How would I do this in Grails 4? I.e., get all the persistent properties of a domain class?
DefaultGrailsDomainClass is indeed deprecated since Grails 3.3.2 in favor of the mapping context API. Fortunately, it is quite straightforward to replace the deprecated implementation.
Inject the grailsDomainClassMappingContext bean in your service or controller:
def grailsDomainClassMappingContext
then get the persistent entity by providing its name:
def entity = grailsDomainClassMappingContext.getPersistentEntity(domainObjName)
where domainObjName is a string and entity is an instance of org.grails.datastore.mapping.model.PersistentEntity. You can also get a specific property by using:
def property = entity.getPropertyByName(propertyName)
where propertyName is a string and property is an instance of org.grails.datastore.mapping.model.PersistentProperty.
The interfaces PersistentEntity and PersistentProperty offer a variety of useful methods to cover many uses.

Grails 3 Accessing Grails domain constraints at runtime

I used to access grails 2 constraints in my gsp like this :
${MyDomainClass.constraints.myProperty.inList.collect{it.name()}}
It doesn't work in Grails 3 anymore
In Grails 3.0 domain and command objects are using the trait grails.validation.Validateable (Source can be found here). That trait gives you access to the constraints by providing the following method.
static Map<String, ConstrainedProperty> getConstraintsMap();
In order to access the constraints you call that method on your domain or command object. The following example accesses the nullable constraint on a domain objects property called day.
domainObject.getConstraintsMap()['day']['nullable']
That way, which was valid in Grails 2, still works...
grailsApplication.getArtefact('Domain',
'MyDomainClass').getConstrainedProperties().myProperty.inList.collect{it.name()}
see GrailsDomainClass API

Grails access Config properties in Secured annotation

I am trying to access the Config of the grails application via the #Secured annotation of spring security with the aim to externalize the role name later.
Sadly, I wasn't able to get this working. Neither by trying to use deprecated ConfigurationHolder class nor getting reference to grailsApplication object.
import org.codehaus.groovy.grails.commons.ConfigurationHolder as CH
#Secured([CH.config.grails.app.user])
class MyController { ...}
Config.groovy:
...
grails.app.user = "ROLE_APPNAME_USER"
...
Does anyone have an advice how to solve this?
EDIT
Came across Burt's article which was informational.
You can't - annotation element values must be compile-time constants because they're resolved by the compiler and stored as part of the class bytecode.
You may have more luck using one of the other mechanisms to specify security constraints (static rules or Requestmap instances in the database) instead of annotations.

How to create/use shared domain properties/methods in Grails 2?

before Grails 2.x we used an abstract class to model shared domain properties. This worked perfect but now when using Grails 2.x is see no way of creating shared domain properties and methods. When i use an abstract class and let my domain classes extend that abstract class i get one big database table.
Is there a alternative way of creating shared domain properties / methods?
Docs says that you need to move your base class into the /src/groovy at this case

Where should I place a transient domain class in a grails app?

Where should I place a transient domain class in a grails app?
Ie I have an Action class that will be passed about, and used, but never saved. Should this be in the grails-app/domain folder, or somewhere else?
grails-app/domain is for persistent domain classes, but not all of your application's domain-related classes need to be there, e.g. in this case where you want to use it as a value object. You can put these in src/groovy along with other classes that aren't considered Grails artifacts.
If you want the classes to support validation, you can annotate them with #Validateable - see section "7.5 Validation Non Domain and Command Object Classes" in the ref docs: http://grails.org/doc/latest/
I think a CommandObject may fit the bill. These typically go in the same directory as your controllers, have the same validation features available to domain objects, but are never persisted. Great for things like search forms.

Resources