From 986280f115a26c28f6404f4f2ef9233caf29cb4d Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Wed, 22 Jan 2014 08:35:47 +0100 Subject: [PATCH] OO-948: create new roster entries without lock --- .../InstantMessagingService.java | 2 +- .../manager/InstantMessagingServiceImpl.java | 7 +-- .../instantMessaging/manager/RosterDAO.java | 42 ++++++++++++--- .../model/ImPreferencesImpl.java | 4 +- .../model/RosterEntryImpl.java | 7 +-- .../model/RosterEntryView.java | 4 +- .../instantMessaging/ui/ChatController.java | 4 +- .../ui/InstantMessagingMainController.java | 4 +- .../InstantMessageServiceTest.java | 6 +-- .../olat/instantMessaging/RosterDAOTest.java | 51 +++++++++++++++++++ 10 files changed, 105 insertions(+), 26 deletions(-) diff --git a/src/main/java/org/olat/instantMessaging/InstantMessagingService.java b/src/main/java/org/olat/instantMessaging/InstantMessagingService.java index 9c2063c6825..cad93dfd169 100644 --- a/src/main/java/org/olat/instantMessaging/InstantMessagingService.java +++ b/src/main/java/org/olat/instantMessaging/InstantMessagingService.java @@ -73,7 +73,7 @@ public interface InstantMessagingService { * @param chatResource * @param listener */ - public void listenChat(Identity identity, OLATResourceable chatResource, boolean anonym, boolean asVip, GenericEventListener listener); + public void listenChat(Identity identity, OLATResourceable chatResource, String nickName, boolean anonym, boolean asVip, GenericEventListener listener); /** * Go away diff --git a/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java b/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java index e03b442cdbf..3be8b576b74 100644 --- a/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java +++ b/src/main/java/org/olat/instantMessaging/manager/InstantMessagingServiceImpl.java @@ -205,8 +205,6 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant } String fullName = userManager.getUserDisplayName(me); rosterDao.updateRosterEntry(chatResource, me, fullName, nickName, anonym, vip); - dbInstance.commit();//commit before sending event - coordinator.getCoordinator().getEventBus().fireEventToListenersOf(event, chatResource); } @@ -376,11 +374,10 @@ public class InstantMessagingServiceImpl extends BasicManager implements Instant } @Override - public void listenChat(Identity identity, OLATResourceable chatResource, + public void listenChat(Identity identity, OLATResourceable chatResource, String nickName, boolean anonym, boolean vip, GenericEventListener listener) { String fullName = userManager.getUserDisplayName(identity); - rosterDao.updateRosterEntry(chatResource, identity, fullName, null, anonym, vip); - dbInstance.commit(); + rosterDao.updateRosterEntry(chatResource, identity, fullName, nickName, anonym, vip); coordinator.getCoordinator().getEventBus().registerFor(listener, identity, chatResource); } diff --git a/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java b/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java index 04c17737eef..e85024fb91f 100644 --- a/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java +++ b/src/main/java/org/olat/instantMessaging/manager/RosterDAO.java @@ -59,22 +59,39 @@ public class RosterDAO { return entry; } + /** + * The method commit the transaction in case of a select for update + * @param chatResource + * @param identity + * @param fullName + * @param nickName + * @param anonym + * @param vip + */ public void updateRosterEntry(OLATResourceable chatResource, Identity identity, String fullName, String nickName, boolean anonym, boolean vip) { - RosterEntryImpl entry = loadForUpdate(chatResource, identity); + RosterEntryImpl entry = load(chatResource, identity); if(entry == null) { createRosterEntry(chatResource, identity, fullName, nickName, anonym, vip); } else { - entry.setFullName(fullName); - entry.setNickName(nickName); - entry.setAnonym(anonym); - dbInstance.getCurrentEntityManager().merge(entry); + if(entry.isAnonym() == anonym + && ((fullName == null && entry.getFullName() == null) || (fullName != null && fullName.equals(entry.getFullName()))) + && ((nickName == null && entry.getNickName() == null) || (nickName != null && nickName.equals(entry.getNickName())))) { + return; + } + + RosterEntryImpl reloadedEntry = loadForUpdate(entry); + reloadedEntry.setFullName(fullName); + reloadedEntry.setNickName(nickName); + reloadedEntry.setAnonym(anonym); + dbInstance.getCurrentEntityManager().merge(reloadedEntry); + dbInstance.commit(); } } - private RosterEntryImpl loadForUpdate(OLATResourceable ores, Identity identity) { + private RosterEntryImpl load(OLATResourceable ores, Identity identity) { TypedQuery<RosterEntryImpl> query = dbInstance.getCurrentEntityManager() - .createNamedQuery("loadIMRosterEntryForUpdate", RosterEntryImpl.class) + .createNamedQuery("loadIMRosterEntry", RosterEntryImpl.class) .setParameter("resid", ores.getResourceableId()) .setParameter("resname", ores.getResourceableTypeName()) .setParameter("identityKey", identity.getKey()); @@ -85,6 +102,17 @@ public class RosterDAO { return null; } + private RosterEntryImpl loadForUpdate(RosterEntryImpl rosterEntry) { + TypedQuery<RosterEntryImpl> query = dbInstance.getCurrentEntityManager() + .createNamedQuery("loadIMRosterEntryForUpdate", RosterEntryImpl.class) + .setParameter("entryKey", rosterEntry.getKey()); + List<RosterEntryImpl> entries = query.getResultList(); + if(entries.size() > 0) { + return entries.get(0); + } + return null; + } + public List<RosterEntryImpl> getRoster(OLATResourceable ores, int firstResult, int maxResults) { TypedQuery<RosterEntryImpl> query = dbInstance.getCurrentEntityManager() .createNamedQuery("loadIMRosterEntryByResource", RosterEntryImpl.class) diff --git a/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java b/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java index 6df47ce15cc..99baafed7b2 100644 --- a/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java +++ b/src/main/java/org/olat/instantMessaging/model/ImPreferencesImpl.java @@ -69,8 +69,8 @@ public class ImPreferencesImpl implements ImPreferences, Persistable, CreateInfo private static final long serialVersionUID = -7269061512818714778L; @Id - @GeneratedValue(generator = "system-uuid") - @GenericGenerator(name = "system-uuid", strategy = "hilo") + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "hilo") @Column(name="id", nullable=false, unique=true, insertable=true, updatable=false) private Long key; diff --git a/src/main/java/org/olat/instantMessaging/model/RosterEntryImpl.java b/src/main/java/org/olat/instantMessaging/model/RosterEntryImpl.java index 12c1cdafdb0..98fba00d8c8 100644 --- a/src/main/java/org/olat/instantMessaging/model/RosterEntryImpl.java +++ b/src/main/java/org/olat/instantMessaging/model/RosterEntryImpl.java @@ -46,8 +46,9 @@ import org.olat.core.id.Persistable; @Table(name="o_im_roster_entry") @NamedQueries({ @NamedQuery(name="loadIMRosterEntryByIdentityandResource", query="select entry from imrosterentry entry where entry.identityKey=:identityKey and entry.resourceId=:resid and entry.resourceTypeName=:resname"), - @NamedQuery(name="loadIMRosterEntryForUpdate", query="select entry from imrosterentry entry where entry.identityKey=:identityKey and entry.resourceId=:resid and entry.resourceTypeName=:resname", + @NamedQuery(name="loadIMRosterEntryForUpdate", query="select entry from imrosterentry entry where entry.key=:entryKey", lockMode=LockModeType.PESSIMISTIC_WRITE), + @NamedQuery(name="loadIMRosterEntry", query="select entry from imrosterentry entry where entry.identityKey=:identityKey and entry.resourceId=:resid and entry.resourceTypeName=:resname"), @NamedQuery(name="loadIMRosterEntryByResource", query="select entry from imrosterentry entry where entry.resourceId=:resid and entry.resourceTypeName=:resname") }) public class RosterEntryImpl implements Persistable, CreateInfo { @@ -55,8 +56,8 @@ public class RosterEntryImpl implements Persistable, CreateInfo { private static final long serialVersionUID = -4265724240924748369L; @Id - @GeneratedValue(generator = "system-uuid") - @GenericGenerator(name = "system-uuid", strategy = "hilo") + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "hilo") @Column(name="id", nullable=false, unique=true, insertable=true, updatable=false) private Long key; diff --git a/src/main/java/org/olat/instantMessaging/model/RosterEntryView.java b/src/main/java/org/olat/instantMessaging/model/RosterEntryView.java index bae0abaa89e..6b66b90dd60 100644 --- a/src/main/java/org/olat/instantMessaging/model/RosterEntryView.java +++ b/src/main/java/org/olat/instantMessaging/model/RosterEntryView.java @@ -53,8 +53,8 @@ public class RosterEntryView implements Persistable, CreateInfo { private static final long serialVersionUID = -4265724240924748369L; @Id - @GeneratedValue(generator = "system-uuid") - @GenericGenerator(name = "system-uuid", strategy = "hilo") + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "hilo") @Column(name="re_id", nullable=false, unique=true, insertable=true, updatable=false) private Long key; diff --git a/src/main/java/org/olat/instantMessaging/ui/ChatController.java b/src/main/java/org/olat/instantMessaging/ui/ChatController.java index f9cd7f6e135..5c86bba4d65 100644 --- a/src/main/java/org/olat/instantMessaging/ui/ChatController.java +++ b/src/main/java/org/olat/instantMessaging/ui/ChatController.java @@ -141,7 +141,6 @@ public class ChatController extends BasicController implements GenericEventListe } // register to chat events for this resource - imService.listenChat(getIdentity(), getOlatResourceable(), defaultAnonym, vip, this); if(privateReceiverKey == null) { buddyList = new Roster(getIdentity().getKey()); @@ -150,8 +149,11 @@ public class ChatController extends BasicController implements GenericEventListe //chat started as anonymous depending on configuratino rosterCtrl = new RosterForm(ureq, getWindowControl(), buddyList, defaultAnonym, offerAnonymMode); listenTo(rosterCtrl); + String nickName = rosterCtrl.getNickName(); + imService.listenChat(getIdentity(), getOlatResourceable(), nickName, defaultAnonym, vip, this); } else { buddyList = null; + imService.listenChat(getIdentity(), getOlatResourceable(), null, defaultAnonym, vip, this); } chatPanelCtr = new FloatingResizableDialogController(ureq, getWindowControl(), mainVC, diff --git a/src/main/java/org/olat/instantMessaging/ui/InstantMessagingMainController.java b/src/main/java/org/olat/instantMessaging/ui/InstantMessagingMainController.java index 3d7df0b9253..719fa688522 100644 --- a/src/main/java/org/olat/instantMessaging/ui/InstantMessagingMainController.java +++ b/src/main/java/org/olat/instantMessaging/ui/InstantMessagingMainController.java @@ -150,8 +150,8 @@ public class InstantMessagingMainController extends BasicController implements G listenTo(chatMgrCtrl); newMsgIcon.put("chats", chatMgrCtrl.getInitialComponent()); - //listen to privat chat messages - imService.listenChat(getIdentity(), getPrivatListenToResourceable(), false, false, this); + //listen to private chat messages + imService.listenChat(getIdentity(), getPrivatListenToResourceable(), null, false, false, this); singleUserEventCenter = ureq.getUserSession().getSingleUserEventCenter(); singleUserEventCenter.registerFor(this, getIdentity(), InstantMessagingService.ASSESSMENT_EVENT_ORES); diff --git a/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java b/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java index 534b33dc49a..425bd220767 100644 --- a/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java +++ b/src/test/java/org/olat/instantMessaging/InstantMessageServiceTest.java @@ -82,8 +82,8 @@ public class InstantMessageServiceTest extends OlatTestCase { Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-1-" + UUID.randomUUID().toString()); Identity chatter2 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-2-" + UUID.randomUUID().toString()); OLATResourceable chatResource = OresHelper.createOLATResourceableInstance(UUID.randomUUID().toString(), chatter1.getKey()); - imService.listenChat(chatter1, chatResource, false, false, dummyListener); - imService.listenChat(chatter2, chatResource, true, true, dummyListener); + imService.listenChat(chatter1, chatResource, null, false, false, dummyListener); + imService.listenChat(chatter2, chatResource, "Chatter-2", true, true, dummyListener); dbInstance.commitAndCloseSession(); //check if the buddies listen to the chat @@ -109,7 +109,7 @@ public class InstantMessageServiceTest extends OlatTestCase { //create a chat Identity chatter1 = JunitTestHelper.createAndPersistIdentityAsUser("Chat-3-" + UUID.randomUUID().toString()); OLATResourceable chatResource = OresHelper.createOLATResourceableInstance(UUID.randomUUID().toString(), chatter1.getKey()); - imService.listenChat(chatter1, chatResource, false, false, new DummyListener()); + imService.listenChat(chatter1, chatResource, null, false, false, new DummyListener()); dbInstance.commitAndCloseSession(); BuddyStats stats = imService.getBuddyStats(chatter1); diff --git a/src/test/java/org/olat/instantMessaging/RosterDAOTest.java b/src/test/java/org/olat/instantMessaging/RosterDAOTest.java index 9ae23306357..27512de5b63 100644 --- a/src/test/java/org/olat/instantMessaging/RosterDAOTest.java +++ b/src/test/java/org/olat/instantMessaging/RosterDAOTest.java @@ -31,6 +31,7 @@ import org.olat.core.id.OLATResourceable; import org.olat.core.util.resource.OresHelper; import org.olat.instantMessaging.manager.RosterDAO; import org.olat.instantMessaging.model.RosterEntryImpl; +import org.olat.instantMessaging.model.RosterEntryView; import org.olat.test.JunitTestHelper; import org.olat.test.OlatTestCase; import org.springframework.beans.factory.annotation.Autowired; @@ -89,6 +90,28 @@ public class RosterDAOTest extends OlatTestCase { Assert.assertEquals(chatResource.getResourceableId(), entry.getResourceId()); } + @Test + public void testGetRosterViews() { + OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-8-" + UUID.randomUUID().toString(), System.currentTimeMillis()); + Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-roster-8-" + UUID.randomUUID().toString()); + rosterDao.createRosterEntry(chatResource, id, "My little name", "Nock", false, false); + dbInstance.commitAndCloseSession(); + + List<RosterEntryView> entries = rosterDao.getRosterView(chatResource, 0, -1); + Assert.assertNotNull(entries); + Assert.assertEquals(1, entries.size()); + + RosterEntryView entry = entries.get(0); + Assert.assertNotNull(entry); + Assert.assertNotNull(entry.getKey()); + Assert.assertEquals(id.getKey(), entry.getIdentityKey()); + Assert.assertEquals("My little name", entry.getFullName()); + Assert.assertEquals("Nock", entry.getNickName()); + Assert.assertFalse(entry.isAnonym()); + Assert.assertEquals(chatResource.getResourceableTypeName(), entry.getResourceTypeName()); + Assert.assertEquals(chatResource.getResourceableId(), entry.getResourceId()); + } + @Test public void testUpdateRosterEntry() { OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-7-" + UUID.randomUUID().toString(), System.currentTimeMillis()); @@ -121,6 +144,34 @@ public class RosterDAOTest extends OlatTestCase { Assert.assertEquals(chatResource.getResourceableId(), reloadEntry.getResourceId()); } + @Test + public void testUpdateRosterEntry_createNew() { + OLATResourceable chatResource = OresHelper.createOLATResourceableInstance("unit-test-7-" + UUID.randomUUID().toString(), System.currentTimeMillis()); + Identity id = JunitTestHelper.createAndPersistIdentityAsAdmin("im-roster-7-" + UUID.randomUUID().toString()); + rosterDao.updateRosterEntry(chatResource, id, "My old name", "Truck", true, false); + dbInstance.commitAndCloseSession(); + + //load the entry + List<RosterEntryImpl> entries = rosterDao.getRoster(chatResource, 0, -1); + Assert.assertNotNull(entries); + Assert.assertEquals(1, entries.size()); + + RosterEntryImpl entry = entries.get(0); + + Assert.assertNotNull(entries); + Assert.assertEquals(1, entries.size()); + + RosterEntryImpl reloadEntry = entries.get(0); + Assert.assertNotNull(reloadEntry); + Assert.assertNotNull(reloadEntry.getKey()); + Assert.assertEquals(id.getKey(), reloadEntry.getIdentityKey()); + Assert.assertEquals("My old name", reloadEntry.getFullName()); + Assert.assertEquals("Truck", reloadEntry.getNickName()); + Assert.assertTrue(entry.isAnonym()); + Assert.assertEquals(chatResource.getResourceableTypeName(), reloadEntry.getResourceTypeName()); + Assert.assertEquals(chatResource.getResourceableId(), reloadEntry.getResourceId()); + } + @Test public void testDeleteRosterEntries() { //create an entry -- GitLab