Details
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
index 049c42d..f7f25b7 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/DefaultTagDefinitionDao.java
@@ -23,6 +23,8 @@ import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.Transaction;
import org.skife.jdbi.v2.TransactionStatus;
import org.skife.jdbi.v2.exceptions.TransactionFailedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.ning.billing.ErrorCode;
@@ -32,9 +34,12 @@ import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.tag.ControlTagType;
import com.ning.billing.util.tag.DefaultTagDefinition;
import com.ning.billing.util.tag.TagDefinition;
+import com.ning.billing.util.tag.api.TagDefinitionEvent;
import com.ning.billing.util.tag.api.user.TagEventBuilder;
public class DefaultTagDefinitionDao implements TagDefinitionDao {
+ private static final Logger log = LoggerFactory.getLogger(DefaultTagDefinitionDao.class);
+
private final TagDefinitionSqlDao tagDefinitionSqlDao;
private final TagEventBuilder tagEventBuilder;
private final Bus bus;
@@ -83,17 +88,31 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
try {
return tagDefinitionSqlDao.inTransaction(new Transaction<TagDefinition, TagDefinitionSqlDao>() {
@Override
- public TagDefinition inTransaction(final TagDefinitionSqlDao transactional, final TransactionStatus status) throws Exception {
+ public TagDefinition inTransaction(final TagDefinitionSqlDao tagDefinitionSqlDao, final TransactionStatus status) throws Exception {
// Make sure the tag definition doesn't exist already
final TagDefinition existingDefinition = tagDefinitionSqlDao.getByName(definitionName);
if (existingDefinition != null) {
throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_ALREADY_EXISTS, definitionName);
}
- final TagDefinition definition = new DefaultTagDefinition(definitionName, description, false);
- tagDefinitionSqlDao.create(definition, context);
+ // Create it
+ final TagDefinition tagDefinition = new DefaultTagDefinition(definitionName, description, false);
+ tagDefinitionSqlDao.create(tagDefinition, context);
+
+ // Post an event to the bus
+ final TagDefinitionEvent tagDefinitionEvent;
+ if (tagDefinition.isControlTag()) {
+ tagDefinitionEvent = tagEventBuilder.newControlTagDefinitionCreationEvent(tagDefinition.getId(), tagDefinition, context.getUserToken());
+ } else {
+ tagDefinitionEvent = tagEventBuilder.newUserTagDefinitionCreationEvent(tagDefinition.getId(), tagDefinition, context.getUserToken());
+ }
+ try {
+ bus.postFromTransaction(tagDefinitionEvent, tagDefinitionSqlDao);
+ } catch (Bus.EventBusException e) {
+ log.warn("Failed to post tag definition creation event for tag " + tagDefinition.getId(), e);
+ }
- return definition;
+ return tagDefinition;
}
});
} catch (TransactionFailedException exception) {
@@ -120,10 +139,10 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
try {
tagDefinitionSqlDao.inTransaction(new Transaction<Void, TagDefinitionSqlDao>() {
@Override
- public Void inTransaction(final TagDefinitionSqlDao transactional, final TransactionStatus status) throws Exception {
+ public Void inTransaction(final TagDefinitionSqlDao tagDefinitionSqlDao, final TransactionStatus status) throws Exception {
// Make sure the tag definition exists
- final TagDefinition existingDefinition = tagDefinitionSqlDao.getByName(definitionName);
- if (existingDefinition == null) {
+ final TagDefinition tagDefinition = tagDefinitionSqlDao.getByName(definitionName);
+ if (tagDefinition == null) {
throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_DOES_NOT_EXIST, definitionName);
}
@@ -132,8 +151,22 @@ public class DefaultTagDefinitionDao implements TagDefinitionDao {
throw new TagDefinitionApiException(ErrorCode.TAG_DEFINITION_IN_USE, definitionName);
}
+ // Delete it
tagDefinitionSqlDao.deleteTagDefinition(definitionName, context);
+ // Post an event to the Bus
+ final TagDefinitionEvent tagDefinitionEvent;
+ if (tagDefinition.isControlTag()) {
+ tagDefinitionEvent = tagEventBuilder.newControlTagDefinitionDeletionEvent(tagDefinition.getId(), tagDefinition, context.getUserToken());
+ } else {
+ tagDefinitionEvent = tagEventBuilder.newUserTagDefinitionDeletionEvent(tagDefinition.getId(), tagDefinition, context.getUserToken());
+ }
+ try {
+ bus.postFromTransaction(tagDefinitionEvent, tagDefinitionSqlDao);
+ } catch (Bus.EventBusException e) {
+ log.warn("Failed to post tag definition deletion event for tag " + tagDefinition.getId(), e);
+ }
+
return null;
}
});
diff --git a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
index 4a7dd1c..6dee4b8 100644
--- a/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/tag/dao/TagDefinitionSqlDao.java
@@ -35,6 +35,7 @@ import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.sqlobject.mixins.Transmogrifier;
import org.skife.jdbi.v2.sqlobject.stringtemplate.ExternalizedSqlViaStringTemplate3;
import org.skife.jdbi.v2.tweak.ResultSetMapper;
@@ -46,7 +47,7 @@ import com.ning.billing.util.tag.TagDefinition;
@ExternalizedSqlViaStringTemplate3
@RegisterMapper(TagDefinitionSqlDao.TagDefinitionMapper.class)
-public interface TagDefinitionSqlDao extends EntitySqlDao<TagDefinition>, Transactional<TagDefinitionSqlDao> {
+public interface TagDefinitionSqlDao extends EntitySqlDao<TagDefinition>, Transactional<TagDefinitionSqlDao>, Transmogrifier {
@Override
@SqlUpdate
public void create(@TagDefinitionBinder final TagDefinition entity, @CallContextBinder final CallContext context);
diff --git a/util/src/main/java/com/ning/billing/util/tag/DefaultTagDefinition.java b/util/src/main/java/com/ning/billing/util/tag/DefaultTagDefinition.java
index 139a66c..d9f714d 100644
--- a/util/src/main/java/com/ning/billing/util/tag/DefaultTagDefinition.java
+++ b/util/src/main/java/com/ning/billing/util/tag/DefaultTagDefinition.java
@@ -50,4 +50,47 @@ public class DefaultTagDefinition extends EntityBase implements TagDefinition {
public Boolean isControlTag() {
return isControlTag;
}
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("DefaultTagDefinition");
+ sb.append("{description='").append(description).append('\'');
+ sb.append(", name='").append(name).append('\'');
+ sb.append(", isControlTag=").append(isControlTag);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultTagDefinition that = (DefaultTagDefinition) o;
+
+ if (description != null ? !description.equals(that.description) : that.description != null) {
+ return false;
+ }
+ if (isControlTag != null ? !isControlTag.equals(that.isControlTag) : that.isControlTag != null) {
+ return false;
+ }
+ if (name != null ? !name.equals(that.name) : that.name != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = name != null ? name.hashCode() : 0;
+ result = 31 * result + (description != null ? description.hashCode() : 0);
+ result = 31 * result + (isControlTag != null ? isControlTag.hashCode() : 0);
+ return result;
+ }
}
diff --git a/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDefinitionDao.java b/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDefinitionDao.java
new file mode 100644
index 0000000..3a44325
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/tag/dao/TestDefaultTagDefinitionDao.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2010-2012 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.tag.dao;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.commons.io.IOUtils;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import com.google.common.eventbus.Subscribe;
+import com.google.inject.Inject;
+import com.ning.billing.dbi.MysqlTestingHelper;
+import com.ning.billing.util.bus.Bus;
+import com.ning.billing.util.bus.BusEvent;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.tag.MockTagStoreModuleSql;
+import com.ning.billing.util.tag.TagDefinition;
+import com.ning.billing.util.tag.TestTagStore;
+import com.ning.billing.util.tag.api.TagDefinitionEvent;
+
+@Guice(modules = MockTagStoreModuleSql.class)
+public class TestDefaultTagDefinitionDao {
+ @Inject
+ private MysqlTestingHelper helper;
+
+ @Inject
+ private TagDefinitionDao tagDefinitionDao;
+
+ @Inject
+ private Clock clock;
+
+ @Inject
+ private Bus bus;
+
+ private CallContext context;
+ private EventsListener eventsListener;
+
+ @BeforeClass(groups = "slow")
+ public void setup() throws IOException {
+ final String utilDdl = IOUtils.toString(TestTagStore.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
+
+ helper.startMysql();
+ helper.initDb(utilDdl);
+
+ context = new DefaultCallContextFactory(clock).createCallContext("TagDefinition DAO test", CallOrigin.TEST, UserType.TEST, UUID.randomUUID());
+ bus.start();
+ }
+
+ @BeforeMethod(groups = "slow")
+ public void cleanup() throws Bus.EventBusException {
+ eventsListener = new EventsListener();
+ bus.register(eventsListener);
+ }
+
+ @AfterClass(groups = "slow")
+ public void stopMysql() {
+ bus.stop();
+ helper.stopMysql();
+ }
+
+ @Test(groups = "slow")
+ public void testCatchEventsOnCreateAndDelete() throws Exception {
+ final String definitionName = UUID.randomUUID().toString().substring(0, 5);
+ final String description = UUID.randomUUID().toString().substring(0, 5);
+
+ // Verify the initial state
+ Assert.assertEquals(eventsListener.getEvents().size(), 0);
+ Assert.assertEquals(eventsListener.getTagDefinitionEvents().size(), 0);
+
+ // Make sure we can create a tag definition
+ final TagDefinition createdTagDefinition = tagDefinitionDao.create(definitionName, description, context);
+ Assert.assertEquals(createdTagDefinition.getName(), definitionName);
+ Assert.assertEquals(createdTagDefinition.getDescription(), description);
+
+ // Make sure we can retrieve it via the DAO
+ final TagDefinition foundTagDefinition = tagDefinitionDao.getByName(definitionName);
+ Assert.assertEquals(foundTagDefinition, createdTagDefinition);
+
+ // Verify we caught an event on the bus
+ Assert.assertEquals(eventsListener.getEvents().size(), 1);
+ Assert.assertEquals(eventsListener.getTagDefinitionEvents().size(), 1);
+ final TagDefinitionEvent tagDefinitionFirstEventReceived = eventsListener.getTagDefinitionEvents().get(0);
+ Assert.assertEquals(eventsListener.getEvents().get(0), tagDefinitionFirstEventReceived);
+ Assert.assertEquals(tagDefinitionFirstEventReceived.getTagDefinitionId(), createdTagDefinition.getId());
+ Assert.assertEquals(tagDefinitionFirstEventReceived.getTagDefinition(), createdTagDefinition);
+ Assert.assertEquals(tagDefinitionFirstEventReceived.getBusEventType(), BusEvent.BusEventType.USER_TAGDEFINITION_CREATION);
+ Assert.assertEquals(tagDefinitionFirstEventReceived.getUserToken(), context.getUserToken());
+
+ // Delete the tag
+ tagDefinitionDao.deleteTagDefinition(definitionName, context);
+
+ // Make sure the tag is deleted
+ Assert.assertNull(tagDefinitionDao.getByName(definitionName));
+
+ // Verify we caught an event on the bus
+ Assert.assertEquals(eventsListener.getEvents().size(), 2);
+ Assert.assertEquals(eventsListener.getTagDefinitionEvents().size(), 2);
+ final TagDefinitionEvent tagDefinitionSecondEventReceived = eventsListener.getTagDefinitionEvents().get(1);
+ Assert.assertEquals(eventsListener.getEvents().get(1), tagDefinitionSecondEventReceived);
+ Assert.assertEquals(tagDefinitionSecondEventReceived.getTagDefinitionId(), createdTagDefinition.getId());
+ Assert.assertEquals(tagDefinitionSecondEventReceived.getTagDefinition(), createdTagDefinition);
+ Assert.assertEquals(tagDefinitionSecondEventReceived.getBusEventType(), BusEvent.BusEventType.USER_TAGDEFINITION_DELETION);
+ Assert.assertEquals(tagDefinitionSecondEventReceived.getUserToken(), context.getUserToken());
+ }
+
+ private static final class EventsListener {
+ private final List<BusEvent> events = new ArrayList<BusEvent>();
+ private final List<TagDefinitionEvent> tagDefinitionEvents = new ArrayList<TagDefinitionEvent>();
+
+ @Subscribe
+ public synchronized void processEvent(final BusEvent event) {
+ events.add(event);
+ }
+
+ @Subscribe
+ public synchronized void processTagDefinitionEvent(final TagDefinitionEvent tagDefinitionEvent) {
+ tagDefinitionEvents.add(tagDefinitionEvent);
+ }
+
+ public List<BusEvent> getEvents() {
+ return events;
+ }
+
+ public List<TagDefinitionEvent> getTagDefinitionEvents() {
+ return tagDefinitionEvents;
+ }
+ }
+}