diff --git a/common/src/main/java/org/red5/server/net/rtmp/event/BaseEvent.java b/common/src/main/java/org/red5/server/net/rtmp/event/BaseEvent.java
index 3efbd24538e39e8cfbd6139002993055a3e4c21d..02dad389efd807600fd6d1e43cc0e9496bbe61e5 100644
--- a/common/src/main/java/org/red5/server/net/rtmp/event/BaseEvent.java
+++ b/common/src/main/java/org/red5/server/net/rtmp/event/BaseEvent.java
@@ -49,7 +49,7 @@ public abstract class BaseEvent implements Constants, IRTMPEvent, Externalizable
     /**
      * Event listener
      */
-    protected IEventListener source;
+    protected transient IEventListener source;
 
     /**
      * Event timestamp
@@ -102,8 +102,10 @@ public abstract class BaseEvent implements Constants, IRTMPEvent, Externalizable
         return type;
     }
 
+    @Deprecated(since = "1.3.26")
     public void setType(Type type) {
-        this.type = type;
+        //this.type = type;
+        throw new UnsupportedOperationException("Type is immutable");
     }
 
     public byte getSourceType() {
@@ -188,6 +190,35 @@ public abstract class BaseEvent implements Constants, IRTMPEvent, Externalizable
      */
     protected abstract void releaseInternal();
 
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        result = prime * result + sourceType;
+        result = prime * result + timestamp;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        BaseEvent other = (BaseEvent) obj;
+        if (type != other.type)
+            return false;
+        if (sourceType != other.sourceType)
+            return false;
+        if (timestamp != other.timestamp)
+            return false;
+        return true;
+    }
+
+    @Override
     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
         type = Type.valueOf(in.readUTF());
         sourceType = in.readByte();
@@ -197,6 +228,7 @@ public abstract class BaseEvent implements Constants, IRTMPEvent, Externalizable
         }
     }
 
+    @Override
     public void writeExternal(ObjectOutput out) throws IOException {
         if (log.isTraceEnabled()) {
             log.trace("writeExternal - type: {} sourceType: {} timestamp: {}", type, sourceType, timestamp);
diff --git a/common/src/main/java/org/red5/server/net/rtmp/event/Invoke.java b/common/src/main/java/org/red5/server/net/rtmp/event/Invoke.java
index 90e79d811363cc9e787966bbd85601cc8870884c..78d5347504a0c8c4603ebbae41d602d516ee1ab3 100644
--- a/common/src/main/java/org/red5/server/net/rtmp/event/Invoke.java
+++ b/common/src/main/java/org/red5/server/net/rtmp/event/Invoke.java
@@ -23,10 +23,12 @@ public class Invoke extends Notify {
 
     private static final long serialVersionUID = -769677790148010729L;
 
+    {
+        dataType = TYPE_INVOKE;
+    }
+
     /** Constructs a new Invoke. */
     public Invoke() {
-        super();
-        dataType = TYPE_INVOKE;
     }
 
     /**
@@ -37,7 +39,6 @@ public class Invoke extends Notify {
      */
     public Invoke(IoBuffer data) {
         super(data);
-        dataType = TYPE_INVOKE;
     }
 
     /**
@@ -48,7 +49,6 @@ public class Invoke extends Notify {
      */
     public Invoke(IPendingServiceCall call) {
         super(call);
-        dataType = TYPE_INVOKE;
     }
 
     /**
@@ -67,12 +67,6 @@ public class Invoke extends Notify {
         return (IPendingServiceCall) call;
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public String toString() {
-        return String.format("Invoke #%d: %s", transactionId, (call != null ? call.toString() : "null"));
-    }
-
     /** {@inheritDoc} */
     @Override
     public boolean equals(Object obj) {
@@ -85,6 +79,12 @@ public class Invoke extends Notify {
         return super.equals(obj);
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public String toString() {
+        return String.format("Invoke #%d: %s", transactionId, (call != null ? call.toString() : "null"));
+    }
+
     /**
      * Duplicate this Invoke message to future injection. Serialize to memory and deserialize, safe way.
      *
diff --git a/common/src/main/java/org/red5/server/net/rtmp/event/Notify.java b/common/src/main/java/org/red5/server/net/rtmp/event/Notify.java
index 2dcef455d4443a0ce9e35a1b15f3423286e14d44..8b0c76eac130eca0c32883f5f8157147232c6304 100644
--- a/common/src/main/java/org/red5/server/net/rtmp/event/Notify.java
+++ b/common/src/main/java/org/red5/server/net/rtmp/event/Notify.java
@@ -61,6 +61,17 @@ public class Notify extends BaseEvent implements ICommand, IStreamData<Notify>,
         super(Type.SERVICE_CALL);
     }
 
+    /**
+     * Create new notification event with given service call
+     *
+     * @param call
+     *            Service call
+     */
+    public Notify(IServiceCall call) {
+        super(Type.SERVICE_CALL);
+        this.call = call;
+    }
+
     /**
      * Create new notification event with given byte buffer
      *
@@ -84,17 +95,6 @@ public class Notify extends BaseEvent implements ICommand, IStreamData<Notify>,
         this.action = action;
     }
 
-    /**
-     * Create new notification event with given service call
-     *
-     * @param call
-     *            Service call
-     */
-    public Notify(IServiceCall call) {
-        super(Type.SERVICE_CALL);
-        this.call = call;
-    }
-
     /** {@inheritDoc} */
     public byte getDataType() {
         return dataType;
@@ -193,6 +193,15 @@ public class Notify extends BaseEvent implements ICommand, IStreamData<Notify>,
             return false;
         }
         Notify other = (Notify) obj;
+        if (getType() != other.getType()) {
+            return false;
+        }
+        if (getTimestamp() != other.getTimestamp()) {
+            return false;
+        }
+        if (getTransactionId() != other.getTransactionId()) {
+            return false;
+        }
         if (getConnectionParams() == null && other.getConnectionParams() != null) {
             return false;
         }
@@ -202,9 +211,6 @@ public class Notify extends BaseEvent implements ICommand, IStreamData<Notify>,
         if (getConnectionParams() != null && !getConnectionParams().equals(other.getConnectionParams())) {
             return false;
         }
-        if (getTransactionId() != other.getTransactionId()) {
-            return false;
-        }
         if (getCall() == null && other.getCall() != null) {
             return false;
         }