Why does Gorm not recognize mongo domain class in Grails 4? - mongodb

Grails 4.0.10. Mongodb 5.0.9 Community.
I'm following the instructions at https://gorm.grails.org/latest/mongodb/manual/ with a Grails Plugin project.
First anomaly, build.gradle:
compile 'org.grails.plugins:mongodb:7.3.0'
Once I do this I get dependency errors and also have to add
compile 'org.mongodb:mongodb-driver-core:4.7.0'
compile 'org.mongodb:mongodb-driver-sync:4.7.0'
Ok, everything else is pretty much a vanilla project. I created a test domain class "QtxResponse" as
#Entity
class QtxResponse {
static mapWith = "mongo"
String objectId
static constraints = {
}
static mapping = {
//id column: "object_id"
objectId index: true
}
}
The project fires up without error. Using the console I create a new QtxResponse via create-domain-class with a String objectId property and try to save it. This is what I get:
java.lang.IllegalStateException: Either class [domainobject.qualtrics.QtxResponse] is not a domain class or GORM has not been initialized correctly or has already been shutdown. Ensure GORM is loaded and configured correctly before calling any methods on a GORM entity.
What is this telling me? Is it something with Gorm setup or something with mapping to mongodb? I have tried both with and without Hibernate.

For Grails 4.0.10, this configuration worked (with hibernate):
compile 'org.grails.plugins:mongodb:6.1.7'
compile 'org.mongodb:bson:4.7.0'
compile "org.grails.plugins:hibernate5"
compile "org.hibernate:hibernate-core:5.4.0.Final"
compile "org.hibernate:hibernate-ehcache:5.1.3.Final"

Related

Reading of DBname.system.indexes failed on Atlas cluster by mongobee after getting connected

I have a Jhipster Spring boot project. Recently I shifted from mlabs standalone sandboxes to Atlas cluster sandbox M0 Free tier replica set. It even worked and I had made some database operations on it. But now for some reason then there is a read permission error
Error creating bean with name 'mongobee' defined in class path resource [DatabaseConfiguration.class]: Invocation of init method failed; nested exception is com.mongodb.MongoQueryException: Query failed with error code 8000 and error message 'user is not allowed to do action [find] on [test.system.indexes]' on server ********-shard-00-01-mfwhq.mongodb.net:27017
You can see the full stack here https://pastebin.com/kaxcr7VS
I have searched high and low and all I could find is that M0 tier user doesn't have permissions to overwrite admin database which I am not doing.
Even now connection to Mlabs DB works fine but have this issue on Atlas DB M0 tier.
Mongo DB version : 3.4
Jars and It's version
name: 'mongobee', version: '0.10'
name: 'mongo-java-driver', version: '3.4.2'
#Neil Lunn
The userId I am using to connect is that of admin's and the connection read and write works through shell or Robo3T(mongo client)
After discussion with MongoDB support team, MongoDB 3.0 deprecates direct access to the system.indexes collection, which had previously been used to list all indexes in a database. Applications should use db.<COLLECTION>.getIndexes() instead.
From MongoDB Atlas docs it can be seen that they may forbid calls to system. collections:
Optionally, for the read and readWrite role, you can also specify a collection. If you do not specify a collection for read and readWrite, the role applies to all collections (excluding some system. collections) in the database.
From the stacktrace it's visible that MongoBee is trying to make this call, so it's now the library issue and it should be updated.
UPDATE:
In order to fix an issue until MongoBee has released new version:
Get the latest sources of MongoBee git clone git#github.com:mongobee/mongobee.git, cd mongobee
Fetch pull request git fetch origin pull/87/head:mongobee-atlas
Checkout git checkout mongobee-atlas
Install MongoBee jar mvn clean install
Get compiled jar from /target folder or local /.m2
Use the jar as a dependency on your project
Came across this issue this morning. Heres a quick and dirty monkey-patch for the problem:
package com.github.mongobee.dao;
import com.github.mongobee.changeset.ChangeEntry;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import java.util.List;
import static com.github.mongobee.changeset.ChangeEntry.CHANGELOG_COLLECTION;
public class ChangeEntryIndexDao {
public void createRequiredUniqueIndex(DBCollection collection) {
collection.createIndex(new BasicDBObject()
.append(ChangeEntry.KEY_CHANGEID, 1)
.append(ChangeEntry.KEY_AUTHOR, 1),
new BasicDBObject().append("unique", true));
}
public DBObject findRequiredChangeAndAuthorIndex(DB db) {
DBCollection changelogCollection = db.getCollection(CHANGELOG_COLLECTION);
List<DBObject> indexes = changelogCollection.getIndexInfo();
if (indexes == null) return null;
for (DBObject index : indexes) {
BasicDBObject indexKeys = ((BasicDBObject) index.get("key"));
if (indexKeys != null && (indexKeys.get(ChangeEntry.KEY_CHANGEID) != null && indexKeys.get(ChangeEntry.KEY_AUTHOR) != null)) {
return index;
}
}
return null;
}
public boolean isUnique(DBObject index) {
Object unique = index.get("unique");
if (unique != null && unique instanceof Boolean) {
return (Boolean) unique;
} else {
return false;
}
}
public void dropIndex(DBCollection collection, DBObject index) {
collection.dropIndex(index.get("name").toString());
}
}
Caused by: java.lang.NoSuchMethodError: com.github.mongobee.dao.ChangeEntryIndexDao.<init>(Ljava/lang/String;)V
at com.github.mongobee.dao.ChangeEntryDao.<init>(ChangeEntryDao.java:34)
at com.github.mongobee.Mongobee.<init>(Mongobee.java:87)
at com.xxx.proj.config.DatabaseConfiguration.mongobee(DatabaseConfiguration.java:62)
at com.xxx.proj.config.DatabaseConfiguration$$EnhancerBySpringCGLIB$$4ae465a5.CGLIB$mongobee$1(<generated>)
at com.xxx.proj.config.DatabaseConfiguration$$EnhancerBySpringCGLIB$$4ae465a5$$FastClassBySpringCGLIB$$f202afb.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358)
at com.xxx.proj.config.DatabaseConfiguration$$EnhancerBySpringCGLIB$$4ae465a5.mongobee(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 22 common frames omitted
jhipster 5 must be using a different version, because i get that when implementing the above code. looks like its expecting a different version.
This access to system.indexes is an open issue in mongobee. The issue has been fixed in the project, but the project was abandoned before the fix was ever released.
Due to this project abandonment, two successor libraries have since been forked from mongobee which have fixed this issue: Mongock and mongobeeJ.
Switching your application's dependency from the mongobee library to one of these successor libraries will allow you to run mongobee database migrations on Atlas.
To summarize these libraries:
Mongock - Forked from mongobee in 2018. Actively maintained. Has evolved significantly from the original, including built-in support for Spring, Spring Boot, and both versions 3 & 4 of the Mongo Java driver.
mongobeeJ - Forked from mongobee in 2018. Five updated versions have been released. Minimal evolution from the original mongobee. Mongo Java Driver 4 support was implemented in August, 2020. This project was deprecated in August, 2020, with a recommendation from its creators to use a library such as Mongock instead.

Apache cayenne - cdbimport task restores PK Generation strategy do default

I have a problem with PK generation strategy in cayenne.
I'm using PostgreSQL 9.6 with Apache Cayenne 4.0.B1.
This is my table in postgres:
create table ui_template (
id varchar(50) primary key default uuid_generate_v1(),
path varchar(300) not null,
type varchar(50) not null
);
Then I'm doing Tools -> Reengineer Database Schema in Cayenne Modeler.
I got table and enity.
And now i have to set PK Generation Strategy to Database-Generated, to let DB generate my PK's. Everything works fine when I'm inserting objects through ObjectContext. But, if I'm running gradle task cdbimport it overwrites my datamap.map.xml file with another one without Generation Strategy.
Please give me advice what I'm doing wrong.
This is my gradle task
buildscript {
// add Maven Central repository
repositories {
mavenCentral()
}
// add Cayenne Gradle Plugin
dependencies {
classpath group: 'org.apache.cayenne.plugins', name: 'cayenne-gradle-plugin', version: '4.0.B1'
classpath group: 'org.postgresql', name: 'postgresql', version: '42.1.3'
}
}
// apply plugin
apply plugin: 'org.apache.cayenne'
// set default DataMap
cayenne.defaultDataMap 'resources/datamap.map.xml'
// add Cayenne dependencies to your project
dependencies {
// this is a shortcut for 'org.apache.cayenne:cayenne-server:VERSION_OF_PLUGIN'
compile cayenne.dependency('server')
compile cayenne.dependency('java8')
}
cdbimport {
dataSource {
driver 'org.postgresql.Driver'
url 'jdbc:postgresql://localhost:5432/my_db'
username 'user'
password 'pass'
}
}
You are doing nothing wrong, it seems that you found a weak spot in cdbimport.
In your case Cayenne doesn't understand default values, for Postgres DB Cayenne marks only serial columns as db-generated.
You can either change your PK to serial (unless you have some special requirements it is always a good idea) or you can try to exclude those PKs from cdbimport task like this:
cdbimport {
//...
includeTable 'ui_template', {
excludeColumns 'id'
}
}
Be aware that excluding PKs can lead to problems with importing relationships. And moreover if you use includeTable you should explicitly list all required tables.

Correct mongo database is not picked up from the connection parameter, instead have to map it manually

I am having an issue where I need to manually map the correct database to the domain instead of it being picked up from the connection argument.
I am using grails 3.2.8, plugin "org.grails.plugins:mongodb:6.1.0". I have both hibernate and mongodb plugin enabled.
I have define my connection URL as
//application.yml
mongodb:
url: 'mongodb://${MONGODB_USERNAME}:${MONGODB_PASSWORD}#${MONGODB_REPLICA_SET}/${MONGODB_DATABASE}?${MONGODB_CONNECTION_OPTIONS}'
My domain object is defined as :
class ReportData {
String id
Long someField
static mapWith = "mongo"
static mapping = {
//database "db-name" DOESN'T WORK WHEN COMMENTING OUT THIS LINE
}
}
Shouldn't the database(system property MONGODB_DATABASE) be picked up auto-magically from the connection url? I am not sure if this is a bug or I am missing some configuration aspect.
I realized that I had not added following in my build.gradle file:
bootRun {
systemProperties = System.properties
}
so my application environment settings were not even getting applied correctly and hence my connection url was invalid.
I found that detail here: http://docs.grails.org/latest/guide/conf.html

How to add postgresql jar in GGST

I have the db and current jar postgresql-9.4.1207.jre7.j to conect.
Now, from GGST im unable to find the option to add my jar.it seems to be similar to maven but still cant find the option
Finally i wonder if the driverClassName should be org.postgresql.Driver
dataSource {
pooled = true
driverClassName = "org.postgresql.Driver"
username = "root"
password = "root"
}
With Grails you don't actually add the jar. Instead, you declare the dependency in build.gradle (for Grails 3). For example, in the dependencies closure add the Maven artefact for postgresql like this:
dependencies {
...
compile 'org.postgresql:postgresql:9.4.1207.jre7'
}
For Grails 2 the concept is the same except the file is grails-app/conf/BuildConfig.groovy.

symfony2 : sonata userbundle + fos userbundle + mongodb => error "sonata.user.mongodb.user_manager" does not exist

I'm trying to use Sonata/UserBundle with mongodb but I'm facing an issue.
I've got an ugly error:
The service definition "sonata.user.mongodb.user_manager" does not
exist.
Here is the concerned configuration part :
# in app/config/config.yml
[...]
fos_user:
db_driver: mongodb
firewall_name: main
user_class: Project\MyApplicationBundle\Document\User
service:
user_manager: sonata.user.mongodb.user_manager
[...]
If I comment the service part, it works but I have an empty document created in the DB when I add a new user.
I have found that stable release of bundle version 2.2.4 has no mongodb.xml in Resources/config directory.
I changed development version (~2.2#dev) ant this works fine now.
now it looks like this: "sonata-project/user-bundle": "~2.2#dev"