I have multiple data sources in my application and I want to be able to switch the datasource on a service class from the default one to a different one (so that it matches my Grails domain). Per the doc it states to use:
static datasource = 'dsName'
property on the service class, which I have done. However, the mainTransactionManager is still using my default data source.
I can see in the ChainedTransactionManager that it calls:
MultiTransactionStatus mts = new MultiTransactionStatus(transactionManagers.get(0));
The 0th index inside of transactionManagers contains my default data source... so how do I ensure that it doesn't use the transaction manager that contains the default data source?
Where/when does Grails read the
static datasource = '...'
property?
Basically I just want to lineup my datasource across my services and my domains.
Where/when does Grails read the static datasource = '...'
That property is read at https://github.com/grails/grails-core/blob/bd7cc10e17d34f20cedce979724f0e3bacd4cdb4/grails-plugin-services/src/main/groovy/org/codehaus/groovy/grails/plugins/services/ServicesGrailsPlugin.groovy#L74
That is invoking the getDatasource method at https://github.com/grails/grails-core/blob/bd7cc10e17d34f20cedce979724f0e3bacd4cdb4/grails-core/src/main/groovy/org/codehaus/groovy/grails/commons/DefaultGrailsServiceClass.java#L40.
Related
It seems like query datasources (ex: query:...) are not supported in Sitecore 8 MVC while using glass. I want to make a relative path so that branch templates will point to the correct datasource when created. Is there a way to do this with Sitecore's query builder? I saw the custom query option where a path can be specified but couldn't seem to get anything going. I think I might add a pipeline processor before the model gets bound by glass to change a datasource that starts with query: into a resolved path and pass that along the pipeline arguments.
You can add a datasource query to a Sublayout or Rendering Datasource Layout field. You will need to add a new Processor to the getRenderingDatasource Pipeline. I myself have used this on Branch Templates to make relative paths to the correct datasource.
Your query:. needs to be defined in the Datasource Location of the sublayout/rendering and make use of ancestor-or-self to make relative paths and traverse the tree to find the parent item holding the datasources.
query:.ancestor-or-self:: *[##templatename = 'home']/*[##templatename = 'storage']/*[##templatename = 'articles']
The processor will need to use the GetRenderingDatasourceArgs. These arguements will provide you pretty much everything you need. Essentially you will need to get the query:. you wrote in the Datasource Locations.
args.RenderingItem["Datasource Location"];
Replace the beginning of the query with the Context Item path (so that its relative) and then make a call to get the items;
private IEnumerable<Item> GetDatasourceLocationsFromQuery(string query)
{
string queryPath = query.Replace("query:.", args.ContextItemPath);
return args.ContextDatabase.SelectItem(queryPath);
}
This will then return the matching item that is the parent of the datasources.
A pattern we use here for large dynamic forms is to allow the client to edit pretty much the entire graph including children and removal and addition of children is handled in javascript. Failing use case is when user deletes a property of one of the children and for this example we'll say the email address of the second child is removed and the parm is sent empty.
Example Class Structure
Domain X
Long id
String name
SortedSet<Child> children
Domain Child
Long id
Integer position // used to sort
String name (required)
String email (required)
Parms are named in this manner:
x.id = 1
x.name = 'blah'
x.children[0].id = 1
x.children[0].position = 0
x.children[0].name = 'childa0'
x.children[0].email = 'child0#any.com'
x.children[1].id = 2
x.children[1].position = 1
x.children[1].name = 'child1'
x.children[1].email = ''
Current stored values:
x.id = 1
x.name = 'blah'
x.children[0].id = 1
x.children[0].position = 0
x.children[0].name = 'childa0'
x.children[0].email = 'child0#any.com'
x.children[1].id = 2
x.children[1].position = 1
x.children[1].name = 'child1'
x.children[1].email = 'child1#any.com'
The pattern to update has been:
Browser
user edits all and submits changes
parms are sent as shown above and in this use case user accidentally deleted email address that is required (yes submit could be prevented in this simple case but there are more extensive validation rules and this is just a simple example to illustrate issue)
Server
retrieve current parent domain class using id parm
check current stored version against edited version and ensure it has not changed
apply all parms to current domain object in this manner: x.properties = parms.x
This is where it breaks down. With Grails 2.2.2 the email property of child[1] is updated to an empty string and running validation catches the error. Grails 2.4.4 does NOT update the child value. I know the data binding changed and perhaps there are valid reasons for this change but I can't fathom it. This has worked from 1.3.6 to 2.2.2.
One thing to note is that if I do not retrieve the domain class and instead create a new instance with the parms passed in all of the child parms are set correctly.
X x = new X(params.x)
This seems to indicate some Grails issue as the user guide talks about both methods as equal - one to use for new instances and the other for updates but the examples clearly demonstrate that both methods should handle indexed child properties.
Any help or thoughts are appreciated!
I ran into this problem my self upgrading an application from 2.2.4 to 2.4.4.
Setting grails.databinding.useSpringBinder = true for config.groovy
and adding grails-web-databinding-spring to the pom worked flawlessy for me.
Obviously doing this was a lot less hassle than rewriting all the binding code :-)
Looking into this further Grails 2.4.4 documentation states that it will bind sets positionally if they are indexed (ie. [0]).
http://grails.org/doc/latest/guide/single.html#dataBinding
The section titled "Data Binding and Many-ended Associations" states that these parms will be bound and that new instances of the set will be created if their index is greater than the current set. This was true for me in Grails 2.2.2 but NOT in 2.4.4.
HOWEVER, earlier in the documentation in the section "Binding To Collections And Maps" it states clearly: "When updating existing elements in a Set the Map being assigned to the Set must have id elements in it which represent the element in the Set".
If you are upgrading to Grails 2.4.4 and have any complex form data binding I suggest you look there first to decide whether to upgrade. Due to these changes in data binding this has become the most complex upgrade we've encountered yet with Grails.
The other disappointment with 2.4.4 is that it states you can override the new binding and fall back to the old spring binding but you cannot past 2.4 - at least from what I can gather from others' posts and my attempts. Setting the config property as documented and adding the dependency required resulted in startup runtime errors.
Apparently older versions of grails prior to 2.4.4 would match the child instances to params positionally, i.e. using the indexes ([0],[1], etc.) to match the children not caring if the IDs of the instances matched. The new binder does want the IDs of the instances to match before binding. I had never realised I was not placing the ID in a hidden field as it always worked perfectly.
I had a similar problem after migrating to Grails 2.4.4 (from 2.2.2). After a lot of reading and seaching (you must to definitly read http://docs.grails.org/2.4.4/guide/single.html#dataBinding mencioned in user2863513 post) I've resolved it in a very simple way
In my application I had nested domains relationships. Example:
class A {
String name
static hasMany = [b:B]
}
class B {
String name
static hasMany = [c:C]
}
class C {
String name
}
Due to the form complexity, class C object were not binding correcly. I've resolved this defining the C atribute on class B as a List (remember, has many relationships are implemented as Sets by default). So, my class B changed to:
class B {
String name
static hasMany = [c:C]
List c
}
And voila! Everything works perfectly again.
Is there an elegant way to, at runtime, configure a GrailsDomainClass to use a DataSource or Connection at runtime? Ideally, this can simply use a in-memory H2 instance.
Here is my use case example. I am writing a grails service that needs to use the HQL syntax with domain objects to peform some complex database calculations. I would like it so that it can run concurrently with each thread using an isolated in-memory H2 instance.
What would be the best way to accomplish this? I know Dynamic DataSource routing might be one place to start, but how is this implemented elegantly in Grails? I need to avoid setting the instances in configuration files as the in-memory H2 instances need to be created on-the-fly.
I'm at this point right now, but not sure how to configure a domain object to use this connection.
def ds = new JdbcDataSource()
ds.setURL("jdbc:h2:mem:dw_1;MVCC=TRUE;LOCK_TIMEOUT=10000;INIT=CREATE SCHEMA IF NOT EXISTS dw_1")
ds.setUser("sa")
ds.setPassword("sa")
def conn = ds.getConnection()
Kind Regards,
In theory you could try setting additional datasource in config and configure domain classes to use multiple datasources and in runtime change connection settings for that additional in-memory datasource or do not change settings but clear it before using or clear on scheduled basis, or do not clear at all.
For the record: haven't used this feature yet myself.
One quick way to work this around is by creating a new datasource in DataSource.groovy like this:
dataSource_example {
dbCreate = ""
dialect = "..."
driverClassName = "..."
url = "your_db_url"
username = "your_username"
password = "your_password"
pooled = true
properties {
....
}
}
And then in your GrailsDomainClass:
public GrailsDomainClass {
static mapping = {
datasource "example"
table name: "grails_domain_class", schema: "schema_one"
}
}
I'm trying to use a domain that's configured for two datasources to copy data from one datasource to another. The documentation implies that this is straight-forward but I can only get it to save to the default datasource.
class LocalTransaction {
static mapping = {
datasources(['DEFAULT','migration'])
}
}
First I tried finding the transaction from the default datasource via LocalTransaction.findAllBy..(), then attempt to save changes via tr.migration.save(flush:true,failOnError:true) but the changes are saved to DEFAULT.
I think tried to create a new instance via LocalTransaction.migration.get(lt.id), copy the data over and then save, but that isn't saving to the migration datasource either.
Thanks,
Bill
Grails 2.0 has added support for multiple datasources to its core (this was formerly provided by a plugin). Please read the following section in the Grails documentation http://grails.org/doc/2.0.0.RC1/guide/conf.html#multipleDatasources
To save data in a specific datasource, you have to use its name before calling the save() closure, for example:
localTransactionObj.migration.save()
Hope that helps!
When I use criteria queries, the result contains array list of lazy initialized objects. that is, the list has values with handler org.codehaus.groovy.grails.orm.hibernate.proxy.GroovyAwareJavassistLazyInitializer.
This prevent me from doing any array operation (minus, remove etc) in it. When I use, GORM methods, I get array list of actual object types. How can I get the actual objects in criteria query?
The code is listed below.
availableTypes = Type.withCriteria() {
'in'("roleFrom", from)
'in'("roleTo", to)
}
availableTypes (an array list) has one value , but not actual object but value with a handler of GroovyAwareJavassistLazyInitializer
availableTypes (an array list) has values with type Type
availableTypes = Type.findByRoleFrom(from)
---------- Update ----------
I did further troubleshooting, and this is what I found. Probably the above description might be misleading, but I kept it in case it helps.
When using findAllBy for the first time, I get proxy objects rather than the actual instance. Then, I invoke the method through an ajax call, the actual instance is loaded (anything to do with cache loading??). When I refresh the page, it again loads the proxy
def typeFrom = Type.findAllByParty(partyFrom)
there is another use of findAllBy in the same method, which always returns actual instances.
def relFrom = Relation.findAllByParty(partyFrom)
When compared the two classes, the attribute 'party' of class Roles is part of a 1-m relation. like
class Role {
RoleType roleType
LocalDate validFrom
LocalDate validTo
static belongsTo = [party : Party ]
...
}
I know if I do statement like Party.findAll(), the role instances would be proxy till they access. But, when using gorm directly on the class (Role), why I am getting the proxy objects ???
thanks for the help.
thanks.
Turns out are a couple of possible solutions which I came across but didn't try, such as
Overloading the equals method so that the proxy and the domain
object use a primary key instead of the hashCode for equality
Using a join query so that you get actual instances back and not proxies
GrailsHibernateUtil.unwrapProxy(o)
HibernateProxyHelper.getClassWithoutInitializingProxy(object)
One solution that worked for me was to specify lazy loading to be false in the domain object mapping.
History of this problem seems to be discussed here: GRAILS-4614
See also: eager load