2018-02-26 19:00 GMT+09:00 <ma...@apache.org>:

> Author: markt
> Date: Mon Feb 26 10:00:12 2018
> New Revision: 1825351
>
> URL: http://svn.apache.org/viewvc?rev=1825351&view=rev
> Log:
> Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=43866
> Add additional attributes to the Manager to provide control over which
> listeners are called when an attribute is added to the session when it has
> already been added under the same name. This is to aid clustering scenarios
> where setAttribute() is often called to signal that the attribute value has
> been mutated and needs to be replicated but it may not be required, or even
> desired, for the the associated listeners to be triggered. The default
> behaviour has not been changed.
>
> Modified:
>     tomcat/trunk/java/org/apache/catalina/Manager.java
>     tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java
>     tomcat/trunk/java/org/apache/catalina/session/StandardSession.java
>     tomcat/trunk/webapps/docs/changelog.xml
>     tomcat/trunk/webapps/docs/config/manager.xml
>
> Modified: tomcat/trunk/java/org/apache/catalina/Manager.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/
> catalina/Manager.java?rev=1825351&r1=1825350&r2=1825351&view=diff
> ============================================================
> ==================
> --- tomcat/trunk/java/org/apache/catalina/Manager.java (original)
> +++ tomcat/trunk/java/org/apache/catalina/Manager.java Mon Feb 26
> 10:00:12 2018
> @@ -351,4 +351,73 @@ public interface Manager {
>       *         otherwise {@code false}
>       */
>      public boolean willAttributeDistribute(String name, Object value);
> +
> +
> +    /**
> +     * When an attribute that is already present in the session is added
> again
> +     * under the same name and the attribute implements {@link
> +     * javax.servlet.http.HttpSessionBindingListener}, should
> +     * {@link javax.servlet.http.HttpSessionBindingListener#
> valueUnbound(javax.servlet.http.HttpSessionBindingEvent)}
> +     * be called followed by
> +     * {@link javax.servlet.http.HttpSessionBindingListener#
> valueBound(javax.servlet.http.HttpSessionBindingEvent)}?
> +     * <p>
> +     * The default value is {@code false}.
> +     *
> +     * @return {@code true} if the listener will be notified, {@code
> false} if
> +     *         it will not
> +     */
> +    public default boolean getNotifyBindingListenerOnUnchangedValue() {
> +        return false;
> +    }
> +
> +
> +    /**
> +     * Configure if
> +     * {@link javax.servlet.http.HttpSessionBindingListener#
> valueUnbound(javax.servlet.http.HttpSessionBindingEvent)}
> +     * be called followed by
> +     * {@link javax.servlet.http.HttpSessionBindingListener#
> valueBound(javax.servlet.http.HttpSessionBindingEvent)}
> +     * when an attribute that is already present in the session is added
> again
> +     * under the same name and the attribute implements {@link
> +     * javax.servlet.http.HttpSessionBindingListener}.
> +     *
> +     * @param notifyBindingListenerOnUnchangedValue {@code true} the
> listener
> +     *                                              will be called, {@code
> +     *                                              false} it will not
> +     */
> +    public void setNotifyBindingListenerOnUnchangedValue(
> +            boolean notifyBindingListenerOnUnchangedValue);
> +
> +
> +    /**
> +     * When an attribute that is already present in the session is added
> again
> +     * under the same name and a {@link
> +     * javax.servlet.http.HttpSessionAttributeListener} is configured
> for the
> +     * session should
> +     * {@link javax.servlet.http.HttpSessionAttributeListener#
> attributeReplaced(javax.servlet.http.HttpSessionBindingEvent)}
> +     * be called?
> +     * <p>
> +     * The default value is {@code true}.
> +     *
> +     * @return {@code true} if the listener will be notified, {@code
> false} if
> +     *         it will not
> +     */
> +    public default boolean getNotifyAttributeListenerOnUnchangedValue() {
> +        return true;
> +    }
> +
> +
> +    /**
> +     * Configure if
> +     * {@link javax.servlet.http.HttpSessionAttributeListener#
> attributeReplaced(javax.servlet.http.HttpSessionBindingEvent)}
> +     * when an attribute that is already present in the session is added
> again
> +     * under the same name and a {@link
> +     * javax.servlet.http.HttpSessionAttributeListener} is configured
> for the
> +     * session.
> +     *
> +     * @param notifyAttributeListenerOnUnchangedValue {@code true} the
> listener
> +     *                                                will be called,
> {@code
> +     *                                                false} it will not
> +     */
> +    public void setNotifyAttributeListenerOnUnchangedValue(
> +            boolean notifyAttributeListenerOnUnchangedValue);
>  }
>
> Modified: tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/
> catalina/session/ManagerBase.java?rev=1825351&r1=1825350&
> r2=1825351&view=diff
> ============================================================
> ==================
> --- tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java
> (original)
> +++ tomcat/trunk/java/org/apache/catalina/session/ManagerBase.java Mon
> Feb 26 10:00:12 2018
> @@ -193,6 +193,10 @@ public abstract class ManagerBase extend
>
>      private boolean warnOnSessionAttributeFilterFailure;
>
> +    private boolean notifyBindingListenerOnUnchangedValue;
> +
> +    private boolean notifyAttributeListenerOnUnchangedValue = true;
> +
>
>      // ------------------------------------------------------------
> Constructors
>
> @@ -209,6 +213,31 @@ public abstract class ManagerBase extend
>
>      // --------------------------------------------------------------
> Properties
>
> +    @Override
> +    public boolean getNotifyAttributeListenerOnUnchangedValue() {
> +        return notifyAttributeListenerOnUnchangedValue;
> +    }
> +
> +
> +
> +    @Override
> +    public void setNotifyAttributeListenerOnUnchangedValue(boolean
> notifyAttributeListenerOnUnchangedValue) {
> +        this.notifyAttributeListenerOnUnchangedValue =
> notifyAttributeListenerOnUnchangedValue;
> +    }
> +
> +
> +    @Override
> +    public boolean getNotifyBindingListenerOnUnchangedValue() {
> +        return notifyBindingListenerOnUnchangedValue;
> +    }
> +
> +
> +    @Override
> +    public void setNotifyBindingListenerOnUnchangedValue(boolean
> notifyBindingListenerOnUnchangedValue) {
> +        this.notifyBindingListenerOnUnchangedValue =
> notifyBindingListenerOnUnchangedValue;
> +    }
> +
> +
>      /**
>       * Obtain the regular expression used to filter session attribute
> based on
>       * attribute name. The regular expression is anchored so it must
> match the
>
> Modified: tomcat/trunk/java/org/apache/catalina/session/
> StandardSession.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/
> catalina/session/StandardSession.java?rev=1825351&r1=1825350&r2=1825351&
> view=diff
> ============================================================
> ==================
> --- tomcat/trunk/java/org/apache/catalina/session/StandardSession.java
> (original)
> +++ tomcat/trunk/java/org/apache/catalina/session/StandardSession.java
> Mon Feb 26 10:00:12 2018
> @@ -1424,8 +1424,9 @@ public class StandardSession implements
>          // Call the valueBound() method if necessary
>          if (notify && value instanceof HttpSessionBindingListener) {
>              // Don't call any notification if replacing with the same
> value
> +            // unless configured to do so
>              Object oldValue = attributes.get(name);
> -            if (value != oldValue) {
> +            if (value != oldValue || manager.
> getNotifyBindingListenerOnUnchangedValue()) {
>                  event = new HttpSessionBindingEvent(getSession(), name,
> value);
>                  try {
>                      ((HttpSessionBindingListener)
> value).valueBound(event);
> @@ -1440,14 +1441,18 @@ public class StandardSession implements
>          Object unbound = attributes.put(name, value);
>
>          // Call the valueUnbound() method if necessary
> -        if (notify && (unbound instanceof HttpSessionBindingListener) &&
> (unbound != value)) {
> -            try {
> -                ((HttpSessionBindingListener) unbound).valueUnbound(
> -                        new HttpSessionBindingEvent(getSession(), name));
> -            } catch (Throwable t) {
> -                ExceptionUtils.handleThrowable(t);
> -                manager.getContext().getLogger().error(
> -                        sm.getString("standardSession.bindingEvent"), t);
> +        if (notify && unbound instanceof HttpSessionBindingListener) {
> +            // Don't call any notification if replacing with the same
> value
> +            // unless configured to do so
> +            if (unbound != value || manager.
> getNotifyBindingListenerOnUnchangedValue()) {
> +                try {
> +                    ((HttpSessionBindingListener) unbound).valueUnbound
> +                        (new HttpSessionBindingEvent(getSession(),
> name));
> +                } catch (Throwable t) {
> +                    ExceptionUtils.handleThrowable(t);
> +                    manager.getContext().getLogger().error
> +                        (sm.getString("standardSession.bindingEvent"),
> t);
> +                }
>              }
>          }
>
> @@ -1468,12 +1473,14 @@ public class StandardSession implements
>              HttpSessionAttributeListener listener =
> (HttpSessionAttributeListener) listeners[i];
>              try {
>                  if (unbound != null) {
> -                    context.fireContainerEvent("
> beforeSessionAttributeReplaced", listener);
> -                    if (event == null) {
> -                        event = new HttpSessionBindingEvent(getSession(),
> name, unbound);
> +                    if (unbound != value || manager.
> getNotifyAttributeListenerOnUnchangedValue()) {
> +                        context.fireContainerEvent("
> beforeSessionAttributeReplaced", listener);
> +                        if (event == null) {
> +                            event = new HttpSessionBindingEvent(getSession(),
> name, unbound);
> +                        }
> +                        listener.attributeReplaced(event);
> +                        context.fireContainerEvent("
> afterSessionAttributeReplaced", listener);
>                      }
> -                    listener.attributeReplaced(event);
> -                    context.fireContainerEvent("
> afterSessionAttributeReplaced", listener);
>                  } else {
>                      context.fireContainerEvent("beforeSessionAttributeAdded",
> listener);
>                      if (event == null) {
> @@ -1486,7 +1493,10 @@ public class StandardSession implements
>                  ExceptionUtils.handleThrowable(t);
>                  try {
>                      if (unbound != null) {
> -                        context.fireContainerEvent("
> afterSessionAttributeReplaced", listener);
> +                        if (unbound != value ||
> +                                
> manager.getNotifyAttributeListenerOnUnchangedValue())
> {
> +                            context.fireContainerEvent("
> afterSessionAttributeReplaced", listener);
> +                        }
>                      } else {
>                          
> context.fireContainerEvent("afterSessionAttributeAdded",
> listener);
>                      }
>
>
Hi,

In cluster environment,
I think that primary sessions behave as expected.
However, non-primary sessions do not behave as expected.
The if(unbound != value) always returns true.
Therefore, listeners are always notified regardless of the value of
notifyAttributeListenerOnUnchangedValue or
notifyBindingListenerOnUnchangedValue.





> Modified: tomcat/trunk/webapps/docs/changelog.xml
> URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/
> changelog.xml?rev=1825351&r1=1825350&r2=1825351&view=diff
> ============================================================
> ==================
> --- tomcat/trunk/webapps/docs/changelog.xml (original)
> +++ tomcat/trunk/webapps/docs/changelog.xml Mon Feb 26 10:00:12 2018
> @@ -48,6 +48,16 @@
>    <subsection name="Catalina">
>      <changelog>
>        <fix>
> +        <bug>43866</bug>: Add additional attributes to the Manager to
> provide
> +        control over which listeners are called when an attribute is
> added to
> +        the session when it has already been added under the same name.
> This is
> +        to aid clustering scenarios where <code>setAttribute()</code> is
> often
> +        called to signal that the attribute value has been mutated and
> needs to
> +        be replicated but it may not be required, or even desired, for
> the the
> +        associated listeners to be triggered. The default behaviour has
> not been
> +        changed. (markt)
> +      </fix>
> +      <fix>
>          Minor optimization when calling class transformers. (rjung)
>        </fix>
>        <add>
>
> Modified: tomcat/trunk/webapps/docs/config/manager.xml
> URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/
> config/manager.xml?rev=1825351&r1=1825350&r2=1825351&view=diff
> ============================================================
> ==================
> --- tomcat/trunk/webapps/docs/config/manager.xml (original)
> +++ tomcat/trunk/webapps/docs/config/manager.xml Mon Feb 26 10:00:12 2018
> @@ -73,6 +73,23 @@
>          (e.g. with <code>HttpServletRequest.getSession()</code> call)
>          will fail with an <code>IllegalStateException</code>.</p>
>        </attribute>
> +
> +      <attribute name="notifyAttributeListenerOnUnchangedValue"
> required="false">
> +        <p>If an attribute is added to the session and that attribute is
> already
> +        present in the session under the same name will any
> +        <code>HttpSessionAttributeListener</code> be notified that the
> attribute
> +        has been replaced. If not specified, the default value of
> +        <code>true</code> will be used.</p>
> +      </attribute>
> +
> +      <attribute name="notifyBindingListenerOnUnchangedValue"
> required="false">
> +        <p>If an attribute is added to the session, that attribute is
> already
> +        present in the session under the same name and the attribute
> implements
> +        <code>HttpSessionBindingListener</code>, will the listener be
> notified
> +        that the attribute has been unbound and bound again. If not
> specified,
> +        the default value of <code>false</code> will be used.</p>
> +      </attribute>
> +
>      </attributes>
>
>    </subsection>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: dev-h...@tomcat.apache.org
>
> --
> Keiichi.Fujino
> <dev-h...@tomcat.apache.org>

<dev-h...@tomcat.apache.org>

Reply via email to