Spring data neo4j not creating unique indexes/constraints in Grails - grails

I'm having some trouble getting unique constraints working with spring-data-neo4j in grails.
I suspect that it's because I've not wired it in properly, but the repository is being scanned and wired, and CRUD is working, so I'm not sure what I've done wrong.
I'm using grails 2.4.3, with these dependencies:
neo4jVerison="2.1.5"
dependencies {
compile("org.neo4j:neo4j-community:$neo4jVerison")
compile("org.neo4j.app:neo4j-server:$neo4jVerison")
compile("org.neo4j:neo4j-rest-graphdb:2.0.1")
compile("org.neo4j:neo4j-spatial:0.13-neo4j-2.1.4")
compile 'org.springframework.data:spring-data-neo4j:3.2.1.RELEASE'
test group:"org.neo4j", name:"neo4j-kernel", version: "$neo4jVerison", classifier:"tests"
test "org.grails:grails-datastore-test-support:1.0-grails-2.4"
test "xmlunit:xmlunit:1.5"
}
and these beans for my test environment:
testGraphDatabaseFactory(org.neo4j.test.TestGraphDatabaseFactory)
graphDb(GraphDatabaseService) { bean ->
bean.factoryBean = "testGraphDatabaseFactory"
bean.factoryMethod = "newImpermanentDatabase"
bean.destroyMethod = "shutdown" }
xmlns neo4j:"http://www.springframework.org/schema/data/neo4j"
neo4j.'repositories'( 'base-package': "repositories" )
neo4jTemplate(Neo4jTemplate, graphDb)
neo4jMappingContext(Neo4jMappingContext)
tx(NeoTransactions, graphDb)
The tx class just exposes a 'tx.tx { closure }' method that starts a graphDb transaction, and closes it even if the closure fails.
My domain class is:
package repositories
import org.springframework.data.neo4j.annotation.GraphId
import org.springframework.data.neo4j.annotation.Indexed
import org.springframework.data.neo4j.annotation.NodeEntity
#NodeEntity
class Junction {
#GraphId Long id;
#Indexed(unique = true) Long legacyId
}
and the repository is:
package repositories
import org.springframework.data.neo4j.repository.GraphRepository
interface JunctionRepository extends GraphRepository<Junction> {}
Given all of that, I would expect this to fail:
package repositories
import org.springframework.dao.DataIntegrityViolationException
import org.springframework.data.neo4j.conversion.Result
class JunctionRepositoryIntegrationSpec extends RepositorySpecification {
JunctionRepository junctionRepository
def tx
def "should not be able to create two junctions with the same legacyId"() {
given: "some junctions with the same id"
Junction j = new Junction(legacyId: 10)
Junction j2 = new Junction(legacyId: 10)
when: "both are saved"
tx.tx {
[j, j2].each { junctionRepository.save(it) }
}
then:
1 == junctionRepository.count()
when: "the second one is changed to have the same legacy id"
def j3 = new Junction(legacyId: 11)
tx.tx {
junctionRepository.save(j3)
j3.legacyId = 10
junctionRepository.save(j3)
}
then: "an exception should be thrown"
thrown DataIntegrityViolationException
}
}
Strangely although only one junction was saved (i.e. 1 == junctionRepository.count()) the exception wasn't thrown when I try and save the modified j3.
Additionally, when I open the database in the Neo4J web console and run :schema it doesn't appear as if any indexes/constraints have been created.
I'm guessing that my wiring is not configured correctly, as I believe that the indexes should be setup when the domain object is parsed at wiring time.
Does anyone know what's missing please?
FOLLOW-UP 1:
I suspect that I should not be creating a template or mapping context by hand. The canonical spring configuration appears to be <neo:config/>.
However, I get a strange error when I try and do that through the spring dsl:
xmlns neo4j:"http://www.springframework.org/schema/data/neo4j"
neo4j.'repositories'( 'base-package': "repositories" )
neo4j.'config'( 'graphDatabaseService': "graphDb" )
The error is:
| Error Fatal error running tests: Error creating bean with name 'junctionRepository':
Cannot resolve reference to bean 'neo4jTemplate' while setting bean property 'neo4jTemplate';
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating
bean with name 'neo4jTemplate' defined in class org.springframework.data.neo4j.config.Neo4jConfiguration:
Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.data.neo4j.support.Neo4jTemplate org.springframework.data.neo4j.config.Neo4jConfiguration.neo4jTemplate() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'neo4jMappingContext' defined in class org.springframework.data.neo4j.config.Neo4jConfiguration: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.data.neo4j.support.mapping.Neo4jMappingContext org.springframework.data.neo4j.config.Neo4jConfiguration.neo4jMappingContext() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityIndexCreator' defined in class org.springframework.data.neo4j.config.Neo4jConfiguration: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.data.neo4j.support.mapping.EntityIndexCreator org.springframework.data.neo4j.config.Neo4jConfiguration.entityIndexCreator() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'indexProvider' defined in class org.springframework.data.neo4j.config.Neo4jConfiguration: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.data.neo4j.support.index.IndexProvider org.springframework.data.neo4j.config.Neo4jConfiguration.indexProvider() throws java.lang.Exception] threw exception; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'graphDatabaseService' is defined (Use --stacktrace to see the full trace)
Hmm: No bean named 'graphDatabaseService' is defined? Is that a bug? neo4j.'config'( 'graphDatabaseService': "graphDb" ) tells it to use the graphDb bean, doesn't it?
FOLLOW-UP 2:
If I change the bean name to graphDatabaseService it works fine. Looks like neo4j.config isn't passing the named graphDb bean to all of those that it constructs. :)

Yes it does rely on the name graphDatabaseService (unfortunately).
Also make sure that your tx class also calls tx.success() not just tx.close()

Related

How to test with DomainUnitTest when multiTenancy

How do test domain classes when I use multiTenancy?
I can see that I need to extend with HibernateSpec and overwrite getConfiguration.
This goes okay when I use ServiceUnitTest but not for DomainUnitTest
Simple example:
application.yml is setup with:
grails:
gorm:
multiTenancy:
mode: DISCRIMINATOR
tenantResolverClass: security.CompanyTenantResolver
My test:
class TestSpec extends HibernateSpec implements DomainUnitTest<Test>{
void "expect ok test"() {
expect:
true
}
def setup() {
System.setProperty(SystemPropertyTenantResolver.PROPERTY_NAME, 'unit-test')
}
def cleanup() {
System.setProperty(SystemPropertyTenantResolver.PROPERTY_NAME, '')
}
#Override
Map getConfiguration() {
[(Settings.SETTING_MULTI_TENANT_RESOLVER_CLASS): SystemPropertyTenantResolver]
}
}
No matter what I try i get:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.grails.beans.ConstraintsEvaluator': Cannot resolve reference to bean 'grailsDomainClassMappingContext' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'grailsDatastore': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.datastore.mapping.simple.SimpleMapDatastore]: Constructor threw exception; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.lang.Class<?>]
Is it a error in grails or have forgotten something?
it is a error in grails version 3.3.2 works okay in version 3.3.0

unable to start Grail application

I am learning Grail and was trying to below code but could not start the application after referencing two classes make and model in vehicle class. also I am adding year as an integer in vehicle class
Running application...
2017-03-05 08:48:32.229 ERROR --- [ost-startStop-1] o.s.b.c.embedded.tomcat.TomcatStarter : Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'grailsCacheFilter': Cannot create inner bean '(inner bean)#692e68e0' of type [grails.plugin.cache.web.filter.simple.MemoryPageFragmentCachingFilter] while setting bean property 'filter'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '(inner bean)#692e68e0': Unsatisfied dependency expressed through method 'setUrlMappingsHandlerMapping' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'urlMappingsHandlerMapping': Unsatisfied dependency expressed through method 'setWebRequestInterceptors' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openSessionInViewInterceptor': Cannot resolve reference to bean 'hibernateDatastore' while setting bean property 'hibernateDatastore'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateDatastore': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.orm.hibernate.HibernateDatastore]: Constructor threw exception; nested exception is org.hibernate.MappingException:
**Could not determine type for: groovy.lang.Binding, at table: vhicle, for columns: [org.hibernate.mapping.Column(binding)]**
2017-03-05 08:48:32.392 ERROR --- [ main] o.s.boot.SpringApplication : Application startup failed
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:137)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:536)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at grails.boot.GrailsApp.run(GrailsApp.groovy:83)
at grails.boot.GrailsApp.run(GrailsApp.groovy:387)
at grails.boot.GrailsApp.run(GrailsApp.groovy:374)
at grails.boot.GrailsApp$run.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':bootRun'.
Process 'command '/usr/lib/jvm/java-7-oracle/bin/java'' finished with non-zero exit value 1
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
| Error Failed to start server (Use --stacktrace to see the full trace)
Here is my Vhicle.groovy
package com.example
class Vehicle {
Integer year
String name
Model model
Make make
static constraints = {
year min: 1900
name maxSize: 255
}
}
def vehicle = Vehicle.findByName('pickup')
if(vehicle) {
println vehicle.model // e.g, 'Titan'
println vehicle.make // e.g, 'Nissan'
}
Model.groovy
package com.example
class Model {
String name
static belongsTo = [ make: Make ]
static constraints = {
}
String to_String(){
name
}
}
Here is my Make.groovy
package com.example
class Make {
String name
static constraints = {
}
String to_String(){
name
}
}
Check your groovy file name vehicle.groovy you have misspelled. You have written like vhicle.groovy it should be Vehicle.groovy as Class name is Vehicle.
As it says in the exception:
at table: vhicle
You've misspelled vehicle somewhere

Grails 3 domain composition using #Delegate

In my app I have a set of 1000 or so "HouseProto" domain objects, which have a bunch of static properties that I need in my "HouseInstance" object.
At scale, maybe there are large numbers of HouseInstance objects each modeled on the HouseProtos. Here is how I tried to model the HouseInstance domain object.
class HouseInstance {
#Delegate
HouseProto houseProto
User agent
static belongsTo=[world: World]
static constraints = {
agent nullable:true
}
}
HouseProto has a lot of fields like "squareFeet" and "bedroomCount" etc.
I used the #Delegate annotation because I'd like to be able to do something like
houseInstance.streetAddress
instead of
houseInstance.houseProto.streetAddress
but this fails on compile. Buried at the end of the console output below is a reference to the "features" field of HouseProto (a hasMany Set) which suggests that might have something to do with it. Remove the delegate annotation, though and it all works fine. (Feature is a domain class that belongsTo HouseProto.)
My question is simply whether or not the #Delegate annotation is incompatible with Domain classes because it interferes with GORM for some reason? It seems like it will do what I want if it can be made to compile.
HouseProto looks more or less like this:
class HouseProto {
def houseService
String streetAddress
Owner owner
Integer sqft
Double acreage
Integer bedroom
...
Double kitchenQuality =0
Double loanBalance =0
Neighborhood neighborhood
String toString() {
"$streetAddress"
}
static hasMany = [features: Feature]
static constraints = {
streetAddress nullable: false, unique: true;
owner nullable: true
sqft nullable: false
neighborhood nullable: false
}
}
The runtime console output starts with this:
ERROR org.springframework.boot.context.embedded.tomcat.TomcatStarter - Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message: Error creating bean with name 'grailsCacheFilter': Cannot create inner bean '(inner bean)#5ec1152d' of type [grails.plugin.cache.web.filter.simple.MemoryPageFragmentCachingFilter] while setting bean property 'filter'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name '(inner bean)#5ec1152d': Unsatisfied dependency expressed through method 'setUrlMappingsHandlerMapping' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'urlMappingsHandlerMapping': Unsatisfied dependency expressed through method 'setWebRequestInterceptors' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openSessionInViewInterceptor': Cannot resolve reference to bean 'hibernateDatastore' while setting bean property 'hibernateDatastore'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateDatastore': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.orm.hibernate.HibernateDatastore]: Constructor threw exception; nested exception is org.hibernate.MappingException: collection element mapping has wrong number of columns: com.grapevine.negotiator2.HouseInstance.features type: object
Disconnected from the target VM, address: '127.0.0.1:57570', transport: 'socket'
ERROR org.springframework.boot.SpringApplication - Application startup failed
As far as I aware #Delegate is not supported in domains, you may have more luck using a trait that both HouseInstance and HouseProto implement

Using abstract Services in Grails

I am adding features to a Grails 2.2.3 application, and I have the following two Services:
abstract class AbstractProcessService {
def grailsApplication
ConfigObject getConfig() {
return grailsApplication.config.processes
}
}
class PhotoMoverService extends AbstractProcessService {
void processPhotos() {
// Method body
}
private ConfigObject getPhotoConfig() {
config.photoMover
}
}
When a Quartz job finally goes to run the processPhotos() method of PhotoMoverService, the following error occurs:
core.ErrorLogger An error occured instantiating job to be executed. job= 'Photo Processes.com.company.processes.PhotoMoverJob'
org.quartz.SchedulerException: Job instantiation failed [See nested exception: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.company.processes.PhotoMoverJob': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'photoMoverService': Cannot create inner bean '(inner bean)' while setting bean property 'target'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#2': Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public java.lang.Object org.codehaus.groovy.grails.commons.AbstractGrailsClass.newInstance()] threw exception; nested exception is org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.company.processes.PhotoMoverService]!]
at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:375)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.company.processes.PhotoMoverJob': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'photoMoverService': Cannot create inner bean '(inner bean)' while setting bean property 'target'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#2': Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public java.lang.Object org.codehaus.groovy.grails.commons.AbstractGrailsClass.newInstance()] threw exception; nested exception is org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.company.processes.PhotoMoverService]!
at grails.plugins.quartz.GrailsJobFactory.createJobInstance(GrailsJobFactory.java:48)
at grails.plugins.quartz.QuartzMonitorJobFactory.createJobInstance(QuartzMonitorJobFactory.groovy:22)
... 2 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'photoMoverService': Cannot create inner bean '(inner bean)' while setting bean property 'target'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#2': Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public java.lang.Object org.codehaus.groovy.grails.commons.AbstractGrailsClass.newInstance()] threw exception; nested exception is org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.company.processes.PhotoMoverService]!
... 4 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#2': Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public java.lang.Object org.codehaus.groovy.grails.commons.AbstractGrailsClass.newInstance()] threw exception; nested exception is org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.company.processes.PhotoMoverService]!
... 4 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public java.lang.Object org.codehaus.groovy.grails.commons.AbstractGrailsClass.newInstance()] threw exception; nested exception is org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.company.processes.PhotoMoverService]!
... 4 more
Caused by: org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.company.processes.PhotoMoverService]!
... 4 more
Caused by: java.lang.NullPointerException: Cannot get property 'config' on null object
at com.company.processes.AbstractProcessService.getConfig(AbstractProcessService.groovy:23)
at com.company.processes.PhotoMoverService.getPhotoConfig(PhotoMoverService.groovy:213)
... 4 more
When I debug the application, grailsApplication in AbstractProcessService is null like it is not being injected properly. Can anyone tell me 1) Why it is not being injected and 2) what I can do to make that happen. Thanks!

Cannot load JDBC driver class 'net.sourceforge.jtds.jdbc.Driver' when compiling Grails project

This is my first post so be gentle! :)
I've set up a grails project (fairly new at grails too) and am attempting to connect it to a SQL 2008 database, I've added the jtds-1.3.0.jar to the lib folder and to my build path, and then I've altered my DataSource.groovy file to read as follows: -
dataSource {
pooled = true
driverClassName = "net.sourceforge.jtds.jdbc.Driver"
dialect = "org.hibernate.dialect.SQLServerDialect"
}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = false
cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
}
// environment specific settings
development {
dataSource {
dbCreate = "update"
url= "jdbc:jtds:sqlserver://TestServer:1433;databaseName=TestTable"
username = "test"
password = "test"
// logSql=true
}
}
Trouble is when I try to compile I get a massive error which reads as follows, what am I missing? I've googled about but can't find an obvious solution... :S
| Error 2013-03-08 12:44:33,451 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error executing bootstraps: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Cannot resolve reference to bean 'lobHandlerDetector' while setting bean property 'lobHandler'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'lobHandlerDetector': Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class 'net.sourceforge.jtds.jdbc.Driver'
Message: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Cannot resolve reference to bean 'lobHandlerDetector' while setting bean property 'lobHandler'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'lobHandlerDetector': Invocation of init method failed; nested exception is org.springframework.jdbc.support.MetaDataAccessException: Error while extracting DatabaseMetaData; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class 'net.sourceforge.jtds.jdbc.Driver'
I have had similar problems in the past.
I've changed the version of JTDS to 1.2.6 and all works fine.
By the way - you don't need to add the jar manually. You just have to add the following to your BuildConfig.groovy (in the dependencies section):
runtime 'net.sourceforge.jtds:jtds:1.2.6'

Resources