I am implementing a simple chat system in Grails as part of an existing application.
The main classes to consider are:
User.groovy
class User {
...
static hasMany = [
...
chatMessages : ChatMessage,
conversationParticipations:ConversationParticipation
]
static constraints = {
...
}
}
ChatConversation.groovy
class ChatConversation {
static hasMany = [
conversationParticipations:ConversationParticipation,
chatMessages:ChatMessage
]
static constraints = {
}
}
ConversationParticipation.groovy - the intermediate class to remove the many-many between User and ChatConversation
class ConversationParticipation {
ChatMessageBuffer chatMessageBuffer
static constraints = {
chatMessageBuffer nullable : true
}
static belongsTo = [
user:User,
chatConversation:ChatConversation
]
}
ChatMessageBuffer.groovy - used to hold chat messages, not yet read by a Conversation Participant
class ChatMessageBuffer {
static hasMany = [
chatMessages : ChatMessage
]
static belongsTo = [
conversationParticipation:ConversationParticipation
]
static constraints = {
chatMessages nullable : true
conversationParticipation nullable : true
}
}
In a service I am calling methods to create a conversation and then to send any sent messages to the ChatMessageBuffers for that conversation like this
def createChatConversation(chatDetails)
{
def chatConversation = new ChatConversation()
chatConversation.save(flush:true, failOnError:true)
new ConversationParticipation(
user:getCurrentUser(),
chatConversation:chatConversation,
chatMessageBuffer:new ChatMessageBuffer()
).save(flush:true, failOnError:true)
new ConversationParticipation(
user:User.get(chatDetails.id),
chatConversation:chatConversation,
chatMessageBuffer: new ChatMessageBuffer()
).save(flush:true, failOnError:true)
return chatConversation
}
def sendMessage(chatMessageDetails)
{
//save the message
def chatMessage = new ChatMessage(
body:chatMessageDetails.chatMessage,
dateSent: new Date(),
user:getCurrentUser(),
chatConversation:ChatConversation.get(chatMessageDetails.chatConversationId)
).save(flush:true,failOnError : true)
//add the message to the message buffer for each participant of the conversation.
ConversationParticipation.findAllByChatConversation(
ChatConversation.get(chatMessageDetails.chatConversationId)
).each {
if(it.chatMessageBuffer.addToChatMessages(chatMessage).save(flush:true, failOnError:true))
{
println"adding to ${it.chatMessageBuffer.id}"
println"added to : ${it.chatMessageBuffer.dump()}"
}
}
def chatMessageBuffer = ChatMessageBuffer.get(1)
println"service : message buffer ${chatMessageBuffer.id}: ${chatMessageBuffer.dump()}"
return chatMessage
}
As you can see on creating a ConversationParticipation
object, I am also creating a ChatMessageBuffer
, which is cascading save when I call save on the new ConversationParticipation
.
My problem is when I am adding the ChatMessage
s to the two ChatMessageBuffer
s, the first ChatMessageBuffer
is not saving, but the second is. So when I go to add another ChatMessage
to the same buffers, the first buffer is empty, but the second buffer contains the previously added ChatMessage(s).
Does anybody have any idea where I am going wrong? Why the first one will not save/update?