Is it possible to use a JNDI dataSource read only in Grails? - grails

I need to add a JNDI datasource from a legacy database to my Grails (1.2.2) application.
So far, the resource is added to my Tomcat (5.5) and DataSource.groovy contains:
development {
dataSource {
jndiName = "jdbc/lrc_legacy_db"
}
}
I also created some domain objects mapping the different tables to comfortably load and handle data from the DB with GORM. But I now want to assure, that every connection to this DB is really read-only. My biggest concern here is the dbCreate- property and the automatic database manipulation through GORM and the GORM classes.
Is it enough to just skip dbCreate?
How do I assure that the database will only be read and never ever manipulated in any way?

You should use the validate option for dbCreate.
EDIT: The documentation is quite a bit different than when I first posted this answer so the link doesn't quite get you to where the validate option is explained. A quick find will get you to the right spot.

According to the Grails documentation:
If your application needs to read but never modify instances of a persistent class, a read-only cache may be used
A read-only cache for a domain class can be configured by
1. Enable Caching
Add something like the following to DataSource.groovy
hibernate {
cache.use_second_level_cache=true
cache.use_query_cache=true
cache.provider_class='org.hibernate.cache.EhCacheProvider'
}
2. Make Cache Read-Only
For each domain class, you will need to add the following to the mapping closure:
static mapping = {
cache usage:'read-only', include:'non-lazy'
}

Related

Use read-only DB replica for read-only GORM methods and criteria

I have a read-only MySql DB replica and want to use it for all select-based GORM requests and criteria all over the project (Grails 3.1.16)
Is there any beautiful way to override the default DataSource only for the part of GORM methods (e.g. get, find)?
According to the documentation, we can use a particular dataSource for domain/service or use namespace with each method call. But I am looking for a more generic mechanism.
You can use dbresolver.
For example:
db.Use(dbresolver.Register(dbresolver.Config{
Replicas: []gorm.Dialector{mysql.Open("read_only_replica")},
}))
Is there any beautiful way to override the default DataSource only for
the part of GORM methods (e.g. get, find)?
There is not.
You can configure as many datasources as you like but you can't declaratively express that one is used for reads and others are used for writes or anything like that. You could easily let one be the default and then be explicit when you want to do others. For example, SomeDomainClass.nameOfDatasourceUsedForReads.list() etc.

How can I share domain between projects with different persistence strategies in grails?

I'm new to Grails and I'm facing some problems sharing my domain model between three different applications. Two of them need to persist model objects, and the third don't.
It seems the usual approach to manage this is by the creation of a plug-in and putting the domain classes in it. The problem is that the domain classes include specific persistence information, and there are some differences in the way each application persists the objects.
Moreover, one of the applications does not need to persist those objects at all, as it retrieves and deletes them using a JSON web interface from another. When I run this application in mode dbCreate = "create-drop", Grails creates unwanted tables for those classes on startup.
I think all the problem comes from mixing the model and persistence specific information in the domain classes.
How can I solve it? Is there a better approach I'm missing to share domain model?
Your approach is correct, in having a plugin with all the domain classes. This approach is suitable for having multiple configuration for dataSource and not manipulating the behavior of the plugin. In order to achieve the same you can modify the dataSource in each application accordingly. For example, something like below:
//Application 1:
//DataSource.groovy
dataSource{
environments{
production{
.........
dbCreate = "update"
url = "prod db url"
..........
}
}
}
//Application 2: [Similar to Application 1]
//DataSource.groovy
dataSource{
environments{
production{
.........
dbCreate = "update"
url = "prod db url"
..........
}
}
}
//Application 3: [which does not persist model to db]
//DataSource.groovy
dataSource{
environments{
production{
.........
//anything other than update, create-drop, validate does nothing
//Taking into consideration you already have the tables created from
//any of the other application.
dbCreate = "none"
url = "prod db url"
readOnly = true //To be on the safer side
..........
}
}
}
The same behavior is applicable for other environments. Refer DataSource for more insight on its properties.
In case you already have the tables and want to generate the domain classes for those tables, you can use db-reverse-engineer plugin effortlessly.
Although, you can use multiple datasources if you need other connections to be used from Application 3.

Grails - Adding a where clause to all domain objects

We have a Grails application that connects to a legacy database in which every table has a column called deleted which indicates if an entity has been deleted or not (this means data never actually gets deleted from the table, it gets archived after a certain amount of time). For each of our domain objects we would like to add an automatic where clause that looks like:
where deleted = false
so that we do not have to add this explicitly to every query within the application. Is there a way to achieve this in grails?
I use the Hibernate Filter plugin for these kinds of things.
I don't think that GORM supports this directly. However, you can take advantage of the hibernate interceptor and add it yourself. In particular, you can use the onPrepareStatement hook to add the where clause to each query that hibernate generates. For example:
// src/groovy/mypackage/MyEntityInterceptor.groovy
package mypackage
class MyEntityInterceptor extends org.hibernate.EmptyInterceptor {
String onPrepareStatement(String sql) {
return addNotDeletedClause(sql)
}
}
// grails-app/conf/spring/resources.groovy
beans = {
entityInterceptor(MyEntityInterceptor)
}
Unfortunately, you'll have to parse the incoming SQL statement to figure out where to insert the where clause.

EF Code first database/table initialization - WHEN does it happen?

My application is using EF code-first design and all generally works very well.
Via a private configuration file, I can specify how I would like EF to handle changes to the db schema, and so create/recreate the relevant tables as desired - the options are "never" "create", "always", "onSchemaChanged" and (for the future) "onSchemaModified".
This works well - but I am getting lost in a couple of places .....
During development, I would like to use the hook as described in
"Database in use error with Entity Framework 4 Code First" - but this seems to execute on EVERY run of my program"
public void InitializeDatabase(Context context)
{
context.Database.SqlCommand("ALTER DATABASE Tocrates SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
_initializer.InitializeDatabase(context); // Maybe this does nothing if not needed
context.Database.SqlCommand("ALTER DATABASE Tocrates SET MULTI_USER")
}
So .. to real my question: Is there an override that I can use to detect whether EF will ACTUALLY be trying to modify the database, so I can set this SINGLE_USER stuff when needed? And if so, can I detect the reason EF it is doing so (see my list of options above) so I can log the reason for change?...
All help and suggestions are very much appreciated.
Unless you have set the database intializer to null initializers run always once (per application lifetime) when you are using a context for the first time. What then actually happens depends on the initializer (your inner _intializer):
For DropCreateDatabaseAlways and CreateDatabaseIfNotExists it's clear by their name what they do.
For DropCreateDatabaseIfModelChanges there is only the question if the model changed or not. EF detects this by comparing a model hash with a hash stored in the database. You can check this yourself by calling...
bool compatible = context.Database.CompatibleWithModel(true);
...within your custom InitializeDatabase and then decide based on the result if you want to send your SqlCommands or not. (Don't call this with a self-created context because it will cause the database to be intialized first before the model compatibilty is checked.) The parameter bool throwIfNoMetadata (which is true in my example) causes EF to throw an exception if the model hash in the database does not exist. Otherwise the method will return true in that case.
For a custom inner initializer: Whatever your code will do.

How do I avoid automatic schema modifications when working with legacy databases using Grails?

Grails does automatic schema modifications (including index/foreign key updates) when changing the domain model. This is usually fine, but when working with legacy databases I would like to completely disable all table modifications.
How do I instruct Grails never to modify the table structure (including indexes and foreign key constraints)?
This is how I've currently setup the mapping:
class ClassName {
String string1
String string2
AnotherClass anotherClass
static mapping = {
version(false)
table("legacy_table")
string1(column: "some_legacy_field_1")
string2(column: "some_legacy_field_2")
anotherClass(column: "another_class_id", nullable: true, ignoreNotFound: true)
}
}
The dataSource defined in /grails-app/conf/DataSource.groovy has a dbCreate property, which can be set to validate to check that the schema matches the domain model without changing it in any way.
More details here:
http://grails.org/doc/latest/guide/3.%20Configuration.html#3.3%20The%20DataSource
As mentioned before, the property dbCreate is the one you use to specify how the database would be altered every time there are changes done in the Domain classes. I would suggest removing this property entirely as Burt suggested, so Hibernate does not control how the database is updated since that could cause certain conflicts depending on the changes you make to your domain classes.
The way I manage the database changes in our project is by using a database migration, I recommend using Liquibase, there is plug in for Grails that works perfectly, it is easy to use and offer great flexibility.

Resources