We are using Grails 2.1.1 and Searchable plugin 0.6.4 in our Grails applications and implemented searchable on some domains which are indicated below with all the mappings.
class User {
.....
static hasMany = [userEducations : UserEducations , userWorkings : UserWorkings ]
......
static searchable = {
content: spellCheck 'include'
all termVector: "yes"
userEducations component: true
userWorkings component: true
}
......
}
class UserEducations {
.....
Schools schools
.....
static belongsTo = [user : User ]
......
static searchable = {
content: spellCheck 'include'
all termVector: "yes"
schools component: true
}
......
}
class UserWorkings {
.....
Organizations organizations
.....
static belongsTo = [user : User ]
....
static searchable = {
content: spellCheck 'include'
all termVector: "yes"
organizations component: true
}
......
}
class Schools {
......
static searchable = true
......
}
class Organizations {
......
static searchable = true
......
}
The data is saving successfully with correct mapping and constraints.
The problem starts when we have the drowslike below in table user with relationship
User a1 -> UserEducations b1 -> Schools d1
and
User a2 -> UserEducations b2 -> Schools d1
or
User a1 -> UserWorkings c1 -> Organizations e1
and
User a2 - > UserWorkings c2 -> Organizations e1
(We are not sure about above fact may be the problem happened due to large no. of data.)
Then when we try to start the server then we receive below exception and server wouldn't start
We have tried by removing searchable index and restarting again then it also not start.
The server starts only when we truncate tables corresponding to above 5 domains.
18:30:54,133 [Compass Gps Index [pool-5-thread-5]] ERROR indexer.ScrollableHibernateIndexEntitiesIndexer - {hibernate}: Failed to index the database
org.compass.core.engine.SearchEngineException: Processor [4]: Failed to add job [Job Create [alias [Organizations] uid [Organizations#456#]] Resource [{Organizations} [stored/uncompressed,indexed,omitNorms<alias:Organizations>],[stored/uncompressed,indexed,omitNorms,omitTf<$/Organizations/id:456>],[stored/uncompressed,indexed<active:true>],[stored/uncompressed,indexed<dateCreated:2013-02-28-14-03-05-0-PM>],[stored/uncompressed,indexed,tokenized<aaa:109122482450911>],[stored/uncompressed,indexed<lastUpdated:2013-02-28-14-03-05-0-PM>],[stored/uncompressed,indexed,tokenized<name:Asc>],[stored/uncompressed,indexed<version:0>],[stored/uncompressed,indexed,omitNorms,omitTf<$/uid:Bs#456#>]]] after [10000ms] and backlog size [100]
at org.compass.core.lucene.engine.transaction.support.AbstractConcurrentTransactionProcessor$Processor.addJob(AbstractConcurrentTransactionProcessor.java:496)
at org.compass.core.lucene.engine.transaction.support.AbstractConcurrentTransactionProcessor.create(AbstractConcurrentTransactionProcessor.java:158)
at org.compass.core.lucene.engine.LuceneSearchEngine.createOrUpdate(LuceneSearchEngine.java:290)
at org.compass.core.lucene.engine.LuceneSearchEngine.create(LuceneSearchEngine.java:268)
at org.compass.core.impl.DefaultCompassSession.create(DefaultCompassSession.java:413)
at org.compass.core.impl.DefaultCompassSession.create(DefaultCompassSession.java:397)
at org.compass.core.impl.ExistingCompassSession.create(ExistingCompassSession.java:305)
at org.compass.gps.device.hibernate.indexer.ScrollableHibernateIndexEntitiesIndexer$RowBuffer.flush(ScrollableHibernateIndexEntitiesIndexer.java:212)
at org.compass.gps.device.hibernate.indexer.ScrollableHibernateIndexEntitiesIndexer$RowBuffer.close(ScrollableHibernateIndexEntitiesIndexer.java:206)
at org.compass.gps.device.hibernate.indexer.ScrollableHibernateIndexEntitiesIndexer.performIndex(ScrollableHibernateIndexEntitiesIndexer.java:151)
at org.compass.gps.device.support.parallel.ConcurrentParallelIndexExecutor$1$1.doInCompassWithoutResult(ConcurrentParallelIndexExecutor.java:104)
at org.compass.core.CompassCallbackWithoutResult.doInCompass(CompassCallbackWithoutResult.java:29)
at org.compass.core.CompassTemplate.execute(CompassTemplate.java:133)
at org.compass.gps.impl.SingleCompassGps.executeForIndex(SingleCompassGps.java:147)
at org.compass.gps.device.support.parallel.ConcurrentParallelIndexExecutor$1.call(ConcurrentParallelIndexExecutor.java:102)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:679)
Our problem is similar to below post
http://grails.1312388.n4.nabble.com/hibernate-Searchable-failing-to-index-on-program-start-td4119566.html
We have tried our best to sort out the problem but no luck.
Please help us to solve this problem.
Go to your console and enter:
grails install-searchable-config
Then open myproject/grails-app/conf/Searchable.groovy and search for the following and change the values as I pointed out.
mirrorChanges = false
bulkIndexOnStartup = false
in Bootstrap.groovy:
class BootStrap {
def searchableService
def init = { servletContext ->
// do any data loading you would normally do
// Manually start the mirroring process to ensure that it comes after the automated migrations.
println "Performing bulk index"
searchableService.reindex()
println "Starting mirror service"
searchableService.startMirroring()
}
}
Related
I'm currently upgrading a Grails 4.0.1 application to Grails 4.0.11 and I'm running into an issue with the join tables for one of my domain classes.
My Account class has multiple hasMany relationships with my class CompletionStatus:
import grails.compiler.GrailsCompileStatic
import grails.gorm.hibernate.mapping.MappingBuilder
#GrailsCompileStatic
class Account {
String name
static hasMany = [successCompletionStatuses: CompletionStatus, noShowCompletionStatuses: CompletionStatus,
partialSegmentAttendanceCompletionStatuses: CompletionStatus]
// Have distinct join tables for the CompletionStatus associations
// https://github.com/grails/grails-core/issues/10811#issuecomment-337931115
static mapping = MappingBuilder.orm {
property('successCompletionStatuses') {
joinTable { name "account_success_completion_statuses" }
}
property('noShowCompletionStatuses') {
joinTable { name "account_no_show_completion_statuses" }
}
property('partialSegmentAttendanceCompletionStatuses') {
joinTable {
name "account_partial_completion_statuses"
key {
name "account_partial_completion_statuses_id"
}
column {
name "different_completion_status_id"
}
}
}
}
static constraints = {
name blank: false
}
}
import grails.compiler.GrailsCompileStatic
#GrailsCompileStatic
class CompletionStatus {
String courseType
String status
static constraints = {
courseType nullable: true
status blank: false
}
}
The mapping in Account works as expected in Grails 4.0.1, with multiple join tables being created in the database. However, when running the application in Grails 4.0.11 I get an error at startup which I eventually discovered can be prevented by removing the multiple hasMany relationships from Account:
Caused by: java.lang.NullPointerException: null
at org.hibernate.mapping.Column.getCanonicalName(Column.java:362)
at org.hibernate.mapping.Table.getColumn(Table.java:233)
at org.hibernate.mapping.Table.addColumn(Table.java:257)
at org.grails.orm.hibernate.cfg.GrailsDomainBinder.bindSimpleValue(GrailsDomainBinder.java:2938)
at org.grails.orm.hibernate.cfg.GrailsDomainBinder.bindCollectionSecondPass(GrailsDomainBinder.java:450)
at org.grails.orm.hibernate.cfg.GrailsDomainBinder$GrailsCollectionSecondPass.doSecondPass(GrailsDomainBinder.java:3406)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1693)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1661)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:286)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.build(MetadataBuildingProcess.java:83)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:473)
at org.hibernate.boot.internal.MetadataBuilderImpl.build(MetadataBuilderImpl.java:84)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:689)
at org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration.buildSessionFactory(HibernateMappingContextConfiguration.java:287)
at org.grails.orm.hibernate.connections.HibernateConnectionSourceFactory.create(HibernateConnectionSourceFactory.java:86)
at org.grails.orm.hibernate.connections.AbstractHibernateConnectionSourceFactory.create(AbstractHibernateConnectionSourceFactory.java:39)
at org.grails.orm.hibernate.connections.AbstractHibernateConnectionSourceFactory.create(AbstractHibernateConnectionSourceFactory.java:23)
at org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory.create(AbstractConnectionSourceFactory.java:64)
at org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory.create(AbstractConnectionSourceFactory.java:52)
at org.grails.datastore.mapping.core.connections.ConnectionSourcesInitializer.create(ConnectionSourcesInitializer.groovy:24)
at org.grails.orm.hibernate.HibernateDatastore.<init>(HibernateDatastore.java:212)
at sun.reflect.GeneratedConstructorAccessor64.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:175)
... 123 common frames omitted
I found I was able to get the database tables account_success_completion_statuses and account_no_show_completion_statuses created by specifying the mapping in Acccount like so, but I am still unable to customize the table name and column names for account_partial_completion_statuses:
static mapping = MappingBuilder.orm {
property('successCompletionStatuses') {
joinTable "account_success_completion_statuses"
}
property('noShowCompletionStatuses') {
joinTable "account_no_show_completion_statuses"
}
property('partialSegmentAttendanceCompletionStatuses') {
joinTable {
name "account_partial_completion_statuses"
key "account_partial_completion_statuses_id"
// This isn't setting the column name
column "different_completion_status_id"
// This isn't setting the column name either
// column { name "different_completion_status_id" }
}
}
}
With the mapping above, a database table named account_completion_status is created instead of account_partial_completion_statuses, and it has columns account_partial_completion_statuses_id and completion_status_id.
For more context in case it is needed, I'm using MySQL 5.6.51 and the library mysql:mysql-connector-java:5.1.48 in my application.
I found the solution in the Grails documentation on joinTable!
The join tables are created properly in the database and the application runs fine when I specify my Account class like so:
import grails.compiler.GrailsCompileStatic
#GrailsCompileStatic
class Account {
String name
static hasMany = [successCompletionStatuses: CompletionStatus,
noShowCompletionStatuses: CompletionStatus,
partialSegmentAttendanceCompletionStatuses: CompletionStatus]
// Have distinct join tables for the CompletionStatus associations
// https://docs.grails.org/3.1.1/ref/Database%20Mapping/joinTable.html
static mapping = {
successCompletionStatuses joinTable: [
name: 'account_success_completion_statuses']
noShowCompletionStatuses joinTable: [
name: 'account_no_show_completion_statuses']
partialSegmentAttendanceCompletionStatuses joinTable: [
name: 'account_partial_completion_statuses',
key: 'account_partial_completion_statuses_id',
column: 'different_completion_status_id']
}
static constraints = {
name blank: false
}
}
In my TYPO3 9 installation I'am working on a custom sitemap.xml for my own extension (Events). There I want to have a separate pageId / detail page for each entry.
As i understood in the config section of tx_seo I can only provide one specific pageId as detail page id - correct?
I tried this config:
plugin.tx_seo {
config {
xmlSitemap {
sitemaps {
veranstaltung {
provider = TYPO3\CMS\Seo\XmlSitemap\RecordsXmlSitemapDataProvider
config {
table = tx_ntevents_domain_model_veranstaltung
sortField = kursnummer
lastModifiedField = tstamp
recursive = 1
pid = 110
url {
pageId = # here different pages which can be found in tx_ntevents_domain_model_veranstaltung.seite1 #
fieldToParameterMap {
uid = nt_events_pi1[veranstaltung] # is this correct? #
}
additionalGetParameters {
nt_events_pi1.controller = Veranstaltung
nt_events_pi1.action = show
}
}
...
With this setup tx_seo finds all entries but does not
provide a specific page id for each entry and
does not generate the nice slug url
Here is the slug code from config.yaml
NtEvents:
type: Extbase
extension: NtEvents
plugin: Events
routes:
-
routePath: '/{veranstaltung-url}'
_controller: 'Veranstaltung::show'
_arguments:
veranstaltung-url: veranstaltung
defaultController: 'Veranstaltung::list'
aspects:
veranstaltung-url:
type: PersistedAliasMapper
tableName: tx_ntevents_domain_model_veranstaltung
routeFieldName: slug
routeValuePrefix: /
You can create your own DataProvider, in your case it would probably be easiest to copy the original "\TYPO3\CMS\Seo\XmlSitemap\RecordsXmlSitemapDataProvider" into your own extension and rewrite it according to your wishes or adapt it accordingly.
I am having a weird issue. I have a Domain object:
class MyClass {
String name
Boolean new = true
String number
String type
Byte[] data
Date dateCreated
Date lastUpdated
static belongsTo = [
other: MyOtherClass
]
static mapping = {
table 'my_classes'
data column: "data", sqlType: "MEDIUMBLOB"
}
static constraints = {
data maxSize: 8000 * 66
number nullable: true
}
}
In the Controller I have (edited to show entire method):
def list = {
def myOtherClasses = MyOtherClass.getAll()
if ( !params.max ) params.max = 20
if ( !params.sort && !params.order ) {
params.sort = "new"
params.order= "desc"
}
def myClassCount = MyClass.createCriteria().count() {
'in'( 'other', myOtherClasses )
order( params.sort, params.order )
}
def myClassList = MyClass.createCriteria().list() {
'in'( 'other', myOtherClasses )
order( params.sort, params.order )
}
return [ myClassList: myClassList, myClassCount: myClassCount ]
}
The result if fine and the view is correct. But each time this code runs, the data property isDirty, so version is incremented, and lastUpdated is updated.
The data property is holding audio data, but I don't think that is relevant.
I can't figure out what is going on here. So my question is, how do I make it stop updating?
Using:
Grails 2.4.4
Hibernate 3.6.10.18
MySQL 5.7.9
Thanks in advance :)
After much research and testing, and a few great articles, I have found a solution:
Instead of using type Byte[] in the Domain Object, I use java.sql.Blob, and removed the sqlType in the mapping.
In the controller, I had to make a few changes to access the Byte[] data from the Blob, but that was easy.
I still don't know why this was happening, and I couldn't find any info on it, but it is working as expected now.
Currently i'm using a custom marshaller to render json:
JSON.registerObjectMarshaller( PlannedEvent) { PlannedEvent pe ->
return [
id : pe.id,
event : [
eventId : pe.baseEvent.id,
subject : pe.baseEvent.subject
],
//rooms: pe.rooms
rooms: [
id : pe.rooms
]
]
}
This gives the following output:
{"id":1,"event":{"eventId":626,"subject":"Baggeren hc (Kv2)"},"rooms":{"id":[8]}}
I would like to know how to set up my map so the value for rooms is a list with each index representing a separate room. Instead of keys, like "id", being set up as a list. The solution in comment gives to much information about the room, so I can't use that.
Wanted result :
"rooms":[{"id":8},{"id":9}]}
If i am correct for your domain modelling you have a hasMany relationship between PlannedEvent & Room .So if you want to get only the list of ROOMS as IDs from the PlannedEvent domian you need to register custom marshallar for Rooms also like :
JSON.registerObjectMarshaller( Room) { Room room ->
// Map of IDs is returned from here
def returnMap = [:]
returnMap["id"] = room.id
return returnMap
}
And in PlannedEvent:
JSON.registerObjectMarshaller( PlannedEvent) { PlannedEvent pe ->
// This is also a map but the value of key rooms will contain the list of IDs of each room
def roomList = [:]
roomList["rooms"] = pe.rooms
return roomList
}
And for next time please clarify your domians & also what do you want clearly.
I am working with play framework with scala and
what am i doing :
login page to login into web app
sign up page to register into web app
after login i want to store all databases values to user
what i want to do:
when user register for web app then i want to store user values into database with current time and date but my form is giving error.
error:
List(FormError(dates,error.required,List())),None)
controllers/Application.scala
object Application extends Controller {
val ta:Form[Keyword] = Form(
mapping(
"id" -> ignored(NotAssigned:Pk[Long]),
"word" -> nonEmptyText,
"blog" -> nonEmptyText,
"cat" -> nonEmptyText,
"score"-> of[Long],
"summaryId"-> nonEmptyText,
"dates" -> date("yyyy-MM-dd HH:mm:ss")
)(Keyword.apply)(Keyword.unapply)
)
def index = Action {
Ok(html.index(ta));
}
def newTask= Action { implicit request =>
ta.bindFromRequest.fold(
errors => {println(errors)
BadRequest(html.index(errors))},
keywo => {
Keyword.create(keywo)
Ok(views.html.data(Keyword.all()))
}
)
}
models/keyword.scala
case class Keyword(id: Pk[Long],word: String,blog: String,cat: String,score: Long, summaryId: String,dates: Date )
object Keyword {
val keyw = {
get[Pk[Long]]("keyword.id") ~
get[String]("keyword.word")~
get[String]("keyword.blog")~
get[String]("keyword.cat")~
get[Long]("keyword.score") ~
get[String]("keyword.summaryId")~
get[Date]("keyword.dates") map {
case id~blog~cat~word~score~summaryId~dates => Keyword(id,word,blog,cat,score, summaryId,dates)
}
}
def all(): List[Keyword] = DB.withConnection { implicit c =>
SQL("select * from keyword").as(Keyword.keyw *)
}
def create(key: Keyword){DB.withConnection{implicit c=>
SQL("insert into keyword values({word},{blog}, {cat}, {score},{summaryId},{dates})").on('word-> key.word,'blog->key.blog,
'cat -> key.cat,
'score-> key.score,
'summaryId -> key.summaryId,
'dates->new Date()).executeUpdate
}
}
views/index.scala.html
#(taskForm: Form[Keyword])
#import helper._
#main("Todo list") {
#form(routes.Application.newTask) {
#inputText(taskForm("word"))
#inputText(taskForm("blog"))
#inputText(taskForm("cat"))
#inputText(taskForm("score"))
#inputText(taskForm("summaryId"))
<input type="submit">
Go Back
}
}
please give me some idea to store date into mysql databse and date is not a field of form
There are two possible solutions:
1. Hidden text field with date(that you override when saving)
2. Have a separate class for the form and dbTable.
You can set a default value for your dates field in the form by replacing "dates" -> date("yyyy-MM-dd HH:mm:ss") with "dates" -> ignored(new Date()). This will ignore any posted data for "dates" and automatically bind it to new Date() (or any value you provide it).