diff --git a/src/main/java/de/thm/arsnova/event/AfterFullUpdateEvent.java b/src/main/java/de/thm/arsnova/event/AfterFullUpdateEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d944d51cfd05c80084d9b73dba062883f657d38
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/event/AfterFullUpdateEvent.java
@@ -0,0 +1,16 @@
+package de.thm.arsnova.event;
+
+import de.thm.arsnova.model.Entity;
+
+public class AfterFullUpdateEvent<E extends Entity> extends AfterUpdateEvent<E> {
+	private final E oldEntity;
+
+	public AfterFullUpdateEvent(final Object source, final E entity, final E oldEntity) {
+		super(source, entity);
+		this.oldEntity = oldEntity;
+	}
+
+	public E getOldEntity() {
+		return oldEntity;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/event/AfterPatchEvent.java b/src/main/java/de/thm/arsnova/event/AfterPatchEvent.java
index 4b73660d36aef3cb763d09f099dbc81535c8a700..847bca9e9396ed56d3c244ed5eecf41bc9484e78 100644
--- a/src/main/java/de/thm/arsnova/event/AfterPatchEvent.java
+++ b/src/main/java/de/thm/arsnova/event/AfterPatchEvent.java
@@ -2,8 +2,17 @@ package de.thm.arsnova.event;
 
 import de.thm.arsnova.model.Entity;
 
+import java.util.Map;
+
 public class AfterPatchEvent<E extends Entity> extends AfterUpdateEvent<E> {
-	public AfterPatchEvent(final Object source, final E entity) {
+	private final Map<String, Object> changes;
+
+	public AfterPatchEvent(final Object source, final E entity, final Map<String, Object> changes) {
 		super(source, entity);
+		this.changes = changes;
+	}
+
+	public Map<String, Object> getChanges() {
+		return changes;
 	}
 }
diff --git a/src/main/java/de/thm/arsnova/event/AfterUpdateEvent.java b/src/main/java/de/thm/arsnova/event/AfterUpdateEvent.java
index 702173630447bc819fe8bf66771a64c56e8b584d..7920b79d220fc72ce48543d3d9997fdaebb65035 100644
--- a/src/main/java/de/thm/arsnova/event/AfterUpdateEvent.java
+++ b/src/main/java/de/thm/arsnova/event/AfterUpdateEvent.java
@@ -2,7 +2,7 @@ package de.thm.arsnova.event;
 
 import de.thm.arsnova.model.Entity;
 
-public class AfterUpdateEvent<E extends Entity> extends CrudEvent<E> {
+public abstract class AfterUpdateEvent<E extends Entity> extends CrudEvent<E> {
 	public AfterUpdateEvent(final Object source, final E entity) {
 		super(source, entity);
 	}
diff --git a/src/main/java/de/thm/arsnova/event/BeforeFullUpdateEvent.java b/src/main/java/de/thm/arsnova/event/BeforeFullUpdateEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..8514163395a1679925eecc3dd48c42f76fe0fbbe
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/event/BeforeFullUpdateEvent.java
@@ -0,0 +1,16 @@
+package de.thm.arsnova.event;
+
+import de.thm.arsnova.model.Entity;
+
+public class BeforeFullUpdateEvent<E extends Entity> extends BeforeUpdateEvent<E> {
+	private final E oldEntity;
+
+	public BeforeFullUpdateEvent(final Object source, final E entity, final E oldEntity) {
+		super(source, entity);
+		this.oldEntity = oldEntity;
+	}
+
+	public E getOldEntity() {
+		return oldEntity;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/event/BeforePatchEvent.java b/src/main/java/de/thm/arsnova/event/BeforePatchEvent.java
index 82eee8540dd42629a35834dbb7f365e962599fb5..717d14f98f82b781bb3152d842947248380064a3 100644
--- a/src/main/java/de/thm/arsnova/event/BeforePatchEvent.java
+++ b/src/main/java/de/thm/arsnova/event/BeforePatchEvent.java
@@ -2,8 +2,17 @@ package de.thm.arsnova.event;
 
 import de.thm.arsnova.model.Entity;
 
+import java.util.Map;
+
 public class BeforePatchEvent<E extends Entity> extends BeforeUpdateEvent<E> {
-	public BeforePatchEvent(final Object source, final E entity) {
+	private final Map<String, Object> changes;
+
+	public BeforePatchEvent(final Object source, final E entity, final Map<String, Object> changes) {
 		super(source, entity);
+		this.changes = changes;
+	}
+
+	public Map<String, Object> getChanges() {
+		return changes;
 	}
 }
diff --git a/src/main/java/de/thm/arsnova/event/BeforeUpdateEvent.java b/src/main/java/de/thm/arsnova/event/BeforeUpdateEvent.java
index 65fc96e1009ca9a1423fbe596049af898124617f..f5964dce95cff6844548cbb79cecd531cec26d43 100644
--- a/src/main/java/de/thm/arsnova/event/BeforeUpdateEvent.java
+++ b/src/main/java/de/thm/arsnova/event/BeforeUpdateEvent.java
@@ -2,7 +2,7 @@ package de.thm.arsnova.event;
 
 import de.thm.arsnova.model.Entity;
 
-public class BeforeUpdateEvent<E extends Entity> extends CrudEvent<E> {
+public abstract class BeforeUpdateEvent<E extends Entity> extends CrudEvent<E> {
 	public BeforeUpdateEvent(final Object source, final E entity) {
 		super(source, entity);
 	}
diff --git a/src/main/java/de/thm/arsnova/event/StateChangeEvent.java b/src/main/java/de/thm/arsnova/event/StateChangeEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..69b55798117cdac601dfb75723f6d7678daf448e
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/event/StateChangeEvent.java
@@ -0,0 +1,45 @@
+package de.thm.arsnova.event;
+
+import de.thm.arsnova.model.Entity;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.core.ResolvableType;
+import org.springframework.core.ResolvableTypeProvider;
+
+import java.util.Optional;
+
+public class StateChangeEvent<E extends Entity, T> extends ApplicationEvent implements ResolvableTypeProvider {
+	private final E entity;
+	private final String stateName;
+	private final T newValue;
+	private final T oldValue;
+
+	public StateChangeEvent(final Object source, final E entity, final String stateName,
+			final T newValue, final T oldValue) {
+		super(source);
+		this.entity = entity;
+		this.stateName = stateName;
+		this.newValue = newValue;
+		this.oldValue = oldValue;
+	}
+
+	public E getEntity() {
+		return entity;
+	}
+
+	public String getStateName() {
+		return stateName;
+	}
+
+	public T getNewValue() {
+		return newValue;
+	}
+
+	public Optional<T> getOldValue() {
+		return Optional.ofNullable(oldValue);
+	}
+
+	@Override
+	public ResolvableType getResolvableType() {
+		return ResolvableType.forClassWithGenerics(getClass(), entity.getClass(), newValue.getClass());
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java b/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java
new file mode 100644
index 0000000000000000000000000000000000000000..7d4993ad65723945489c9f9ae0ecf5268ea1dbd7
--- /dev/null
+++ b/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java
@@ -0,0 +1,75 @@
+package de.thm.arsnova.event;
+
+import de.thm.arsnova.model.Content;
+import de.thm.arsnova.model.Entity;
+import de.thm.arsnova.model.Room;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.context.ApplicationEventPublisherAware;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * StateEventDispatcher publishes additional, more specific events for state changes of entities when
+ * {@link AfterUpdateEvent}s are received.
+ *
+ * @author Daniel Gerhardt
+ */
+@Component
+public class StateEventDispatcher implements ApplicationEventPublisherAware {
+	private ApplicationEventPublisher eventPublisher;
+
+	@EventListener
+	public void dispatchRoomStateEvent(final AfterFullUpdateEvent<Room> event) {
+		final Room newRoom = event.getEntity();
+		final Room oldRoom = event.getOldEntity();
+		publishEventIfPropertyChanged(newRoom, oldRoom, Room::isClosed, "closed");
+		publishEventIfPropertyChanged(newRoom, oldRoom, Room::getSettings, "settings");
+	}
+
+	@EventListener
+	public void dispatchRoomStateEvent(final AfterPatchEvent<Room> event) {
+		final Room room = event.getEntity();
+		final Map<String, Object> changes = event.getChanges();
+		publishEventIfPropertyChanged(room, changes, "closed", "closed");
+		publishEventIfPropertyChanged(room, changes, "settings", "settings");
+	}
+
+	@EventListener
+	public void dispatchContentStateEvent(final AfterFullUpdateEvent<Content> event) {
+		final Content newContent = event.getEntity();
+		final Content oldContent = event.getOldEntity();
+		publishEventIfPropertyChanged(newContent, oldContent, Content::getState, "state");
+	}
+
+	@EventListener
+	public void dispatchContentStateEvent(final AfterPatchEvent<Content> event) {
+		final Content content = event.getEntity();
+		final Map<String, Object> changes = event.getChanges();
+		publishEventIfPropertyChanged(content, changes, "state", "state");
+	}
+
+	private <E extends Entity, T extends Object> void publishEventIfPropertyChanged(
+			final E newEntity, final E oldEntity, final Function<E, T> propertyGetter, final String stateName) {
+		T newValue = propertyGetter.apply(newEntity);
+		T oldValue = propertyGetter.apply(oldEntity);
+		if (!newValue.equals(oldValue)) {
+			eventPublisher.publishEvent(new StateChangeEvent<>(this, newEntity, stateName, newValue, oldValue));
+		}
+	}
+
+	private <E extends Entity> void publishEventIfPropertyChanged(
+			final E entity, final Map<String, Object> changes, final String property, final String stateName) {
+		if (changes.containsKey(property)) {
+			eventPublisher.publishEvent(
+					new StateChangeEvent<>(this, entity, stateName, changes.get(property), null));
+		}
+	}
+
+	@Override
+	public void setApplicationEventPublisher(final ApplicationEventPublisher applicationEventPublisher) {
+		this.eventPublisher = applicationEventPublisher;
+	}
+}
diff --git a/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java b/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java
index e2f2d0272238cc58ce9adad3c6612c20dc755f05..114c0be1039794d74902a8a5d1f07539dbdab92a 100644
--- a/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java
@@ -22,12 +22,12 @@ import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.ObjectReader;
 import de.thm.arsnova.event.AfterCreationEvent;
 import de.thm.arsnova.event.AfterDeletionEvent;
+import de.thm.arsnova.event.AfterFullUpdateEvent;
 import de.thm.arsnova.event.AfterPatchEvent;
-import de.thm.arsnova.event.AfterUpdateEvent;
 import de.thm.arsnova.event.BeforeCreationEvent;
 import de.thm.arsnova.event.BeforeDeletionEvent;
+import de.thm.arsnova.event.BeforeFullUpdateEvent;
 import de.thm.arsnova.event.BeforePatchEvent;
-import de.thm.arsnova.event.BeforeUpdateEvent;
 import de.thm.arsnova.model.Entity;
 import de.thm.arsnova.model.serialization.View;
 import de.thm.arsnova.persistence.CrudRepository;
@@ -130,9 +130,9 @@ public class DefaultEntityServiceImpl<T extends Entity> implements EntityService
 		newEntity.setUpdateTimestamp(new Date());
 
 		prepareUpdate(newEntity);
-		eventPublisher.publishEvent(new BeforeUpdateEvent<>(this, newEntity));
+		eventPublisher.publishEvent(new BeforeFullUpdateEvent<>(this, newEntity, oldEntity));
 		final T updatedEntity = repository.save(newEntity);
-		eventPublisher.publishEvent(new AfterUpdateEvent<>(this, updatedEntity));
+		eventPublisher.publishEvent(new AfterFullUpdateEvent<>(this, updatedEntity, oldEntity));
 		finalizeUpdate(updatedEntity);
 
 		return updatedEntity;
@@ -171,9 +171,9 @@ public class DefaultEntityServiceImpl<T extends Entity> implements EntityService
 		reader.readValue(tree);
 		entity.setUpdateTimestamp(new Date());
 		preparePatch(entity);
-		eventPublisher.publishEvent(new BeforePatchEvent<>(this, entity));
+		eventPublisher.publishEvent(new BeforePatchEvent<>(this, entity, changes));
 		final T patchedEntity = repository.save(entity);
-		eventPublisher.publishEvent(new AfterPatchEvent<>(this, patchedEntity));
+		eventPublisher.publishEvent(new AfterPatchEvent<>(this, patchedEntity, changes));
 
 		return patchedEntity;
 	}
@@ -194,7 +194,7 @@ public class DefaultEntityServiceImpl<T extends Entity> implements EntityService
 			reader.readValue(tree);
 			entity.setUpdateTimestamp(new Date());
 			preparePatch(entity);
-			eventPublisher.publishEvent(new BeforePatchEvent<>(this, entity));
+			eventPublisher.publishEvent(new BeforePatchEvent<>(this, entity, changes));
 		}
 
 		return repository.saveAll(entities);