Ejemplo n.º 1
0
 /**
  * Writes the given value only if it is serializable. If not, null is written.
  *
  * @since 5.0.7
  */
 public static void smartWrite(ObjectOutputStream s, Object val) throws IOException {
   final boolean bser =
       val instanceof java.io.Serializable || val instanceof java.io.Externalizable;
   s.writeObject(bser ? val : null);
   if (!bser && val != null && logio.debugable())
     logio.debug("Skip not-serializable object: " + val);
 }
Ejemplo n.º 2
0
  /** Returns the static method defined in an element, or null if failed. */
  /*package*/ static MethodInfo getMethodInfo(Element el) {
    final String clsnm = IDOMs.getRequiredAttributeValue(el, "class");
    final String sig = IDOMs.getRequiredAttributeValue(el, "signature");
    final Class cls;
    try {
      cls = Classes.forNameByThread(clsnm);
    } catch (ClassNotFoundException ex) {
      log.error("Class not found: " + clsnm + ", " + el.getLocator());
      return null; // to report as many errors as possible
    }

    try {
      final Method mtd = Classes.getMethodBySignature(cls, sig, null);
      if ((mtd.getModifiers() & Modifier.STATIC) == 0) {
        log.error("Not a static method: " + mtd);
        return null;
      }

      final Object[] args = new Object[mtd.getParameterTypes().length];
      for (int j = 0; j < args.length; ++j) args[j] = el.getAttributeValue("arg" + j);

      return new MethodInfo(mtd, args);
    } catch (ClassNotFoundException ex) {
      log.realCauseBriefly(
          "Unable to load class when resolving " + sig + " " + el.getLocator(), ex);
    } catch (NoSuchMethodException ex) {
      log.error("Method not found in " + clsnm + ": " + sig + " " + el.getLocator());
    }
    return null;
  }
Ejemplo n.º 3
0
 /**
  * rollback the current session.
  *
  * @param exec the exection to clean up.
  * @param ex the StaleObjectStateException being thrown (and not handled) during the execution
  */
 private void rollback(Execution exec, Throwable ex) {
   try {
     if (HibernateUtil.currentSession().getTransaction().isActive()) {
       log.debug("Trying to rollback database transaction after exception:" + ex);
       HibernateUtil.currentSession().getTransaction().rollback();
     }
   } catch (Throwable rbEx) {
     log.error("Could not rollback transaction after exception! Original Exception:\n" + ex, rbEx);
   }
 }
Ejemplo n.º 4
0
 public void addRequests(Collection requests) {
   for (Iterator it = requests.iterator(); it.hasNext(); ) {
     final AuRequest request = (AuRequest) it.next();
     try {
       request.activate();
       if (!isObsolete(request)) addRequest(request);
     } catch (ComponentNotFoundException ex) { // ignore it
       // ignore it since a long request might remove a timer
       // while clients already queues onTimer generated by the timer
       if (log.debugable()) log.debug("Ignore request: " + ex.getMessage());
     }
   }
 }
 protected void importMergedRegions(Sheet poiSheet, SSheet sheet) {
   // merged cells
   // reference RangeImpl.getMergeAreas()
   int nMerged = poiSheet.getNumMergedRegions();
   final SheetImpl sheetImpl = (SheetImpl) sheet;
   for (int i = nMerged - 1; i >= 0; --i) {
     final CellRangeAddress mergedRegion = poiSheet.getMergedRegion(i);
     // ZSS-1114: any new merged region that overlapped with previous merged region is thrown away
     final CellRegion r =
         new CellRegion(
             mergedRegion.getFirstRow(),
             mergedRegion.getFirstColumn(),
             mergedRegion.getLastRow(),
             mergedRegion.getLastColumn());
     final CellRegion overlapped = sheetImpl.checkMergedRegion(r);
     if (overlapped != null) {
       _logger.warning(
           "Drop the region "
               + r
               + " which is overlapped with existing merged area "
               + overlapped
               + ".");
       continue;
     }
     sheetImpl.addDirectlyMergedRegion(r);
   }
 }
Ejemplo n.º 6
0
  /** @param wapp the Web application (or null if not available yet) */
  private void sessionTimeout(
      HttpServletRequest request, HttpServletResponse response, WebApp wapp, String dtid)
      throws ServletException, IOException {
    final String sid = request.getHeader("ZK-SID");
    if (sid != null) response.setHeader("ZK-SID", sid);

    final AuWriter out = AuWriters.newInstance().open(request, response, 0);

    if (!getAuDecoder(wapp).isIgnorable(request, wapp)) {
      final String deviceType = getDeviceType(request);
      URIInfo ui =
          wapp != null ? (URIInfo) wapp.getConfiguration().getTimeoutURI(deviceType) : null;
      String uri = ui != null ? ui.uri : null;
      out.write(new AuConfirmClose(null)); // Bug: B50-3147382
      final AuResponse resp;
      if (uri != null) {
        if (uri.length() != 0) uri = Encodes.encodeURL(getServletContext(), request, response, uri);
        resp = new AuSendRedirect(uri, null);
      } else {
        String msg = wapp.getConfiguration().getTimeoutMessage(deviceType);
        if (msg != null && msg.startsWith("label:")) {
          final String key;
          msg = Labels.getLabel(key = msg.substring(6), new Object[] {dtid});
          if (msg == null) log.warning("Label not found, " + key);
        }
        if (msg == null) msg = Messages.get(MZk.UPDATE_OBSOLETE_PAGE, dtid);
        resp = new AuObsolete(dtid, msg);
      }
      out.write(resp);
    }

    out.close(request, response);
  }
Ejemplo n.º 7
0
  /**
   * Recovers the desktop if possible. It is called if {@link #getDesktop} returns null.
   *
   * <p>The default implementation will look for any failover manager ({@link FailoverManager}) is
   * registered, and forward the invocation to it if found.
   *
   * @return the recovered desktop, or null if failed to recover
   * @since 5.0.3
   */
  protected Desktop recoverDesktop(
      Session sess,
      HttpServletRequest request,
      HttpServletResponse response,
      WebAppCtrl wappc,
      String dtid) {
    final FailoverManager failover = wappc.getFailoverManager();
    if (failover != null) {
      Desktop desktop = null;
      final ServletContext ctx = getServletContext();
      try {
        if (failover.isRecoverable(sess, dtid)) {
          desktop = WebManager.getWebManager(ctx).getDesktop(sess, request, response, null, true);
          if (desktop == null) // forward or redirect
          throw new IllegalStateException("sendRediect or forward not allowed in recovering");

          wappc
              .getUiEngine()
              .execRecover(new ExecutionImpl(ctx, request, response, desktop, null), failover);
          return desktop; // success
        }
      } catch (Throwable ex) {
        log.error("Unable to recover " + dtid, ex);
        if (desktop != null) ((DesktopCtrl) desktop).recoverDidFail(ex);
      }
    }
    return null;
  }
Ejemplo n.º 8
0
  private static final boolean load(String flnm) {
    final InputStream strm = ContentTypes.class.getResourceAsStream(flnm);
    if (strm == null) return false;

    BufferedReader in = null;
    // NOTE: we cannot use Properties.load because there might be replicated
    // mapping (e.g., jpg=images/jpg, jpg=images/jpeg)
    try {
      in = new BufferedReader(new InputStreamReader(strm));
      String line;
      while ((line = in.readLine()) != null) {
        final int j = line.indexOf('=');
        if (j < 0) {
          final int k = Strings.skipWhitespaces(line, 0);
          if (k < line.length() && line.charAt(k) != '#')
            log.warning("Ignored error;  illgal format: " + line);
          continue;
        }

        final String format = line.substring(0, j).trim();
        final String ctype = line.substring(j + 1).trim();
        if (format.length() == 0 || ctype.length() == 0) {
          log.warning("Ignored error;  illgal format: " + line);
          continue;
        }

        _fmt2ct.put(format, ctype);
        _ct2fmt.put(ctype, format);
      }
    } catch (IOException ex) {
      log.warning("Ingored error: Unable to read " + flnm, ex);
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException e) {
        }
      }
      try {
        strm.close();
      } catch (Throwable ex) {
      }
    }
    return true;
  }
Ejemplo n.º 9
0
 /** Writes only serializable elements of the specified collection. */
 public static <T> void smartWrite(ObjectOutputStream s, Collection<T> col) throws IOException {
   if (col != null) {
     final boolean debug = logio.debugable();
     for (T val : col) {
       if ((val instanceof Serializable) || (val instanceof Externalizable)) {
         try {
           s.writeObject(val);
         } catch (java.io.NotSerializableException ex) {
           logio.error("Unable to serialize item: " + val);
           throw ex;
         }
       } else if (val != null && debug) {
         logio.debug("Skip not-serializable item: " + val);
       }
     }
   }
   s.writeObject(null);
 }
Ejemplo n.º 10
0
  private void register0(Object locator) {
    if (locator == null) throw new NullPointerException("locator");

    synchronized (_locators) {
      if (!_locators.add(locator))
        log.warning("Replace the old one, because it is replicated: " + locator);
    }

    reset(); // Labels might be loaded before, so...
  }
Ejemplo n.º 11
0
  private void reportError(String message, Employee employee) {
    StringBuilder sb =
        new StringBuilder(message)
            .append(Messages.getString("EmployeeController.5"))
            .append(employee);
    final String error = sb.toString();

    UiUtils.showMessage(error);
    log.error(error);
  }
Ejemplo n.º 12
0
 public void destroy() {
   for (Iterator it = _aues.values().iterator(); it.hasNext(); ) {
     final AuExtension aue = (AuExtension) it.next();
     try {
       aue.destroy();
     } catch (Throwable ex) {
       log.warningBriefly("Unable to stop " + aue, ex);
     }
   }
 }
Ejemplo n.º 13
0
 /**
  * Writes only serializable elements of the specified array.
  *
  * <p>To read back, use {@link #smartRead(ObjectInputStream, Collection)}.
  *
  * @since 3.0.0
  */
 public static <T> void smartWrite(ObjectOutputStream s, T[] ary) throws IOException {
   if (ary != null) {
     final boolean debug = logio.debugable();
     for (int j = 0; j < ary.length; ++j) {
       final T val = ary[j];
       if ((val instanceof Serializable) || (val instanceof Externalizable)) {
         try {
           s.writeObject(val);
         } catch (java.io.NotSerializableException ex) {
           logio.error("Unable to serialize item: " + val);
           throw ex;
         }
       } else if (val != null && debug) {
         logio.debug("Skip not-serializable item: " + val);
       }
     }
   }
   s.writeObject(null);
 }
Ejemplo n.º 14
0
 private static String getDeviceType(HttpServletRequest request) {
   final String agt = request.getHeader("user-agent");
   if (agt != null && agt.length() > 0) {
     try {
       return Devices.getDeviceByClient(agt).getType();
     } catch (Throwable ex) {
       log.warning("Unknown device for " + agt);
     }
   }
   return "ajax";
 }
Ejemplo n.º 15
0
 @Override
 public void run() {
   while (!_exit) {
     try {
       nextIteration();
     } catch (Exception ex) {
       _log.error(ex);
       exit();
     }
   }
 }
Ejemplo n.º 16
0
/**
 * Utilities to clean up resources when the application is stopping. Currenly, when a ZK application
 * is stopping, ZK will invoke {@link #cleanup}. Thus you can register an implementation of {@link
 * Cleanup} to release the resources.
 *
 * <p>Notice that this utility is introduced mainly to resolve the memory lead issue if an
 * application is hot re-deployed. A typical example is to stop any pooled threads.
 *
 * <h3>How to use:</h3>
 *
 * <p>First, register the cleanup with {@link #add}.
 *
 * <p>Second, invoke {@link #cleanup} when necessary, such as when the application is stopping.
 *
 * @author tomyeh
 * @since 3.6.5
 */
public class Cleanups {
  private static final Log log = Log.lookup(Cleanups.class);
  private static final List _cleanups = new LinkedList();

  /**
   * Registers a cleanup.
   *
   * @return true if it is added successfully, or false if the cleanup has been regsitered before.
   */
  public static boolean add(Cleanup cleanup) {
    if (cleanup == null) throw new IllegalArgumentException();

    synchronized (_cleanups) {
      if (_cleanups.contains(cleanup)) return false;
      return _cleanups.add(cleanup);
    }
  }
  /**
   * Un-registers a cleanup.
   *
   * @return true if it is removed successfully, or false if not registered before.
   */
  public static boolean remove(Cleanup cleanup) {
    synchronized (_cleanups) {
      return _cleanups.remove(cleanup);
    }
  }

  /** Invokes all cleanups registered with {@link #add}. */
  public static void cleanup() {
    final List cleanups;
    synchronized (_cleanups) {
      cleanups = new ArrayList(_cleanups);
    }

    for (Iterator it = cleanups.iterator(); it.hasNext(); ) {
      final Cleanup cleanup = (Cleanup) it.next();
      try {
        cleanup.cleanup();
      } catch (Throwable ex) {
        log.error("Failed to invoke " + cleanup);
      }
    }
  }
  /**
   * The interface to implement for each cleanup. It is used with {@link Cleanups#add}.
   *
   * @since 3.6.5
   */
  public static interface Cleanup {
    /** Cleanups the thread local variables. */
    public void cleanup();
  }
}
Ejemplo n.º 17
0
  private static final String getNotFound(int code, Locale locale) {
    if (code == NULL_CODE) return ""; // special code

    try {
      log.error(
          "Message code not found: "
              + Integer.toHexString(code)
              + " not in "
              + locale
              + ":"
              + Aide.getBundleInfo(code));

      final String hexcode = Integer.toHexString(code);
      final String s = getFromBundle(MCommon.MESSAGE_CODE_NOT_FOUND, locale);
      return s != null
          ? MessageFormats.format(s, new Object[] {hexcode}, locale)
          : "Unknown message code: " + hexcode;
    } catch (Exception ex) {
      log.realCauseBriefly(ex);
      return "Unknown message code: " + Integer.toHexString(code);
    }
  }
Ejemplo n.º 18
0
  /**
   * Clones the specified object. Use clone() if Cloeable. Otherwise, try to serialize/deserialize
   * it by use of MarshalledObject.
   *
   * <p>If o is null, null is returned.
   *
   * @exception SystemException if failed to clone
   */
  public static final Object clone(Object o) {
    if (o == null) return o;

    try {
      final Class<?> kls = o.getClass();
      if (kls.isArray()) return ArraysX.clone(o);

      if (o instanceof Cloneable) {
        try {
          return kls.getMethod("clone").invoke(o);
        } catch (NoSuchMethodException ex) {
          if (log.debugable()) log.debug("No clone() for " + kls);
        }
      }

      // :TODO: MarshalledObject is said with very bad performance, change it
      // if exists other good deep clone method.
      return new MarshalledObject<Object>(o).get();
    } catch (Exception ex) {
      throw SystemException.Aide.wrap(ex);
    }
  }
Ejemplo n.º 19
0
 /**
  * Writes only serializable entries of the specified map. Non-serializable attributes are ignored.
  */
 public static <K, V> void smartWrite(ObjectOutputStream s, Map<K, V> map) throws IOException {
   if (map != null) {
     final boolean debug = logio.debugable();
     for (Map.Entry<K, V> me : map.entrySet()) {
       final K nm = me.getKey();
       final V val = me.getValue();
       if (((nm instanceof Serializable) || (nm instanceof Externalizable))
           && (val == null || (val instanceof Serializable) || (val instanceof Externalizable))) {
         try {
           s.writeObject(nm);
           s.writeObject(val);
         } catch (java.io.NotSerializableException ex) {
           logio.error("Unable to serialize entry: " + nm + '=' + val);
           throw ex;
         }
       } else if (nm != null && debug) {
         logio.debug("Skip not-serializable entry: " + nm + '=' + val);
       }
     }
   }
   s.writeObject(null); // denote end-of-map
 }
Ejemplo n.º 20
0
 private void handleFailedModal(int oldmode, boolean oldvisi) {
   try {
     if (Executions.getCurrent().getAttribute("javax.servlet.error.exception") != null) {
       // handle it specially if it is used for dispalying err
       setMode(HIGHLIGHTED);
     } else {
       setMode(oldmode); // restore
       setVisible(oldvisi);
     }
   } catch (Throwable ex) {
     log.realCauseBriefly("Causing another error", ex);
   }
 }
Ejemplo n.º 21
0
  public void call(Object base, Method method) {
    Class<?>[] paramTypes = method.getParameterTypes();
    java.lang.annotation.Annotation[][] parmAnnos = method.getParameterAnnotations();
    Object[] params = new Object[paramTypes.length];

    try {
      for (int i = 0; i < paramTypes.length; i++) {
        params[i] = resolveParameter(parmAnnos[i], paramTypes[i]);
      }

      method.invoke(base, params);
    } catch (InvocationTargetException invokEx) {
      // Ian YT Tsai (2012.06.20), while InvocationTargetException,
      // using original exception is much meaningful.
      Throwable c = invokEx.getCause();
      if (c == null) c = invokEx;
      _log.error(c);
      throw UiException.Aide.wrap(c);
    } catch (Exception e) {
      _log.error(e);
      throw UiException.Aide.wrap(e);
    }
  }
Ejemplo n.º 22
0
  /** Invokes all cleanups registered with {@link #add}. */
  public static void cleanup() {
    final List cleanups;
    synchronized (_cleanups) {
      cleanups = new ArrayList(_cleanups);
    }

    for (Iterator it = cleanups.iterator(); it.hasNext(); ) {
      final Cleanup cleanup = (Cleanup) it.next();
      try {
        cleanup.cleanup();
      } catch (Throwable ex) {
        log.error("Failed to invoke " + cleanup);
      }
    }
  }
Ejemplo n.º 23
0
 /**
  * Eliminates single and double quotations to avoid JavaScript injection. It eliminates all
  * quotations. In other words, the specified string shall NOT contain any quotations.
  *
  * <p>It is used to avoid JavaScript injection. For exmple, in DSP or JSP pages, the following
  * codes is better to escape with this method. <code><input value="${c:eatQuot(param.some)}"/>
  * </code>
  *
  * @since 3.5.2
  */
 public static String eatQuot(String s) {
   final int len = s != null ? s.length() : 0;
   StringBuffer sb = null;
   for (int j = 0; j < len; ++j) {
     final char cc = s.charAt(j);
     if (cc == '\'' || cc == '"') {
       if (sb == null) {
         log.warning("JavaScript Injection? Unexpected string detected: " + s);
         sb = new StringBuffer(len);
         if (j > 0) sb.append(s.substring(0, j));
       }
     } else if (sb != null) sb.append(cc);
   }
   return sb != null ? sb.toString() : s;
 }
Ejemplo n.º 24
0
 /** Invokes a static method. */
 /*package*/ String invoke(MethodInfo mi) {
   final Provider provider = getProvider();
   final Class[] argTypes = mi.method.getParameterTypes();
   final Object[] args = mi.arguments;
   if (provider != null)
     for (int j = 0; j < args.length; ++j)
       if (ServletRequest.class.isAssignableFrom(argTypes[j])) args[j] = provider.request;
       else if (ServletResponse.class.isAssignableFrom(argTypes[j])) args[j] = provider.response;
       else if (ServletContext.class.isAssignableFrom(argTypes[j])) args[j] = getServletContext();
   try {
     Object o = mi.method.invoke(null, args);
     return o instanceof String ? (String) o : "";
   } catch (Throwable ex) { // log and eat ex
     log.error("Unable to invoke " + mi.method, ex);
     return "";
   }
 }
Ejemplo n.º 25
0
 private static Extension getExtension() {
   if (_ext == null) {
     synchronized (BindUiLifeCycle.class) {
       if (_ext == null) {
         String clsnm = Library.getProperty("org.zkoss.bind.tracker.impl.extension");
         if (clsnm != null) {
           try {
             _ext = (Extension) Classes.newInstanceByThread(clsnm);
           } catch (Throwable ex) {
             log.realCauseBriefly("Unable to instantiate " + clsnm, ex);
           }
         }
         if (_ext == null) _ext = new DefaultExtension();
       }
     }
   }
   return _ext;
 }
Ejemplo n.º 26
0
  // called by Provider
  InputStream getResourceAsStream(HttpServletRequest request, String path, boolean locate)
      throws IOException, ServletException {
    if (locate)
      path = Servlets.locate(_webctx.getServletContext(), request, path, _webctx.getLocator());

    if (_cache.getCheckPeriod() >= 0) {
      // Due to Web server might cache the result, we use URL if possible
      try {
        URL url = _webctx.getResource(path);
        if (url != null) return url.openStream();
      } catch (Throwable ex) {
        log.warningBriefly("Unable to read from URL: " + path, ex);
      }
    }

    // Note: _webctx will handle the renaming for debugJS (.src.js)
    return _webctx.getResourceAsStream(path);
  }
Ejemplo n.º 27
0
  /**
   * Adds an AU extension and associates it with the specified prefix.
   *
   * <p>If there was an AU extension associated with the same name, the the old AU extension will be
   * replaced.
   *
   * <p>If you want to add an Au extension, even before DHtmlUpdateServlet is started, use {@link
   * #addAuExtension(WebApp, String, AuExtension)} instead.
   *
   * @param prefix the prefix. It must start with "/", but it cannot be "/" nor "/web" (which are
   *     reserved).
   * @param extension the AU extension (never null).
   * @return the previous AU extension associated with the specified prefix, or null if the prefix
   *     was not associated before.
   * @see #addAuExtension(WebApp,String,AuExtension)
   * @since 5.0.0
   */
  public AuExtension addAuExtension(String prefix, AuExtension extension) throws ServletException {
    checkAuExtension(prefix, extension);

    if (_aues.get(prefix) == extension) // speed up to avoid sync
    return extension; // nothing changed

    extension.init(this);

    // To avoid using sync in doGet(), we make a copy here
    final AuExtension old;
    synchronized (this) {
      final Map ps = new HashMap(_aues);
      old = (AuExtension) ps.put(prefix, extension);
      _aues = ps;
    }
    if (old != null)
      try {
        old.destroy();
      } catch (Throwable ex) {
        log.warningBriefly("Unable to stop " + old, ex);
      }
    return old;
  }
Ejemplo n.º 28
0
  /**
   * Gets a message based on the specified code. If not found, returns an error message to denote
   * it.
   *
   * <p>If fmtArgs is not null, {@link org.zkoss.text.MessageFormats#format} is called to format the
   * message. However, unlike MessageFormat's default behavior, all null objects are treated as an
   * empty string rather than "null".
   *
   * <p>It also recognizes {@link org.zkoss.lang.Objects#UNKNOWN}.
   *
   * @param code the code
   * @param fmtArgs the argument lists to format the message
   * @param locale the locale of the message to load
   * @return the message; never be null
   */
  public static String get(int code, Object[] fmtArgs, Locale locale) {
    try {
      String s = getFromBundle(code, locale);
      if (s == null) return getNotFound(code, locale);

      if (fmtArgs != null && fmtArgs.length > 0) {
        final Object[] args = new Object[fmtArgs.length];
        final Formatter formatter = _formatter;
        for (int j = 0; j < fmtArgs.length; ++j) {
          final Object arg = fmtArgs[j];
          if (formatter != null) args[j] = formatter.format(arg);
          else if (arg == null || arg == Objects.UNKNOWN) args[j] = "";
          else if (arg instanceof Object[]) args[j] = Objects.toString(arg);
          else args[j] = arg;
        }
        s = MessageFormats.format(s, args, locale);
      }
      return s;
    } catch (Exception ex) {
      log.realCause(ex);
      return getNotFound(code, locale);
    }
  }
Ejemplo n.º 29
0
 // -- ExecutionCleanup --//
 public void cleanup(Execution exec, Execution parent, List errs) {
   if (parent == null) { // the root execution of a servlet request
     try {
       if (errs == null || errs.isEmpty()) {
         // Commit and cleanup
         log.debug("Committing the database transaction: " + exec);
         HibernateUtil.currentSession().getTransaction().commit();
       } else {
         final Throwable ex = (Throwable) errs.get(0);
         if (ex instanceof StaleObjectStateException) {
           // default implementation does not do any optimistic concurrency
           // control; it simply rollback the transaction.
           handleStaleObjectStateException(exec, (StaleObjectStateException) ex);
         } else {
           // default implementation log the stacktrace and then rollback
           // the transaction.
           handleOtherException(exec, ex);
         }
       }
     } finally {
       HibernateUtil.closeSession(); // always close it
     }
   }
 }
Ejemplo n.º 30
0
 /**
  * Default StaleObjectStateException handler. This implementation does not implement optimistic
  * concurrency control! It simply rollback the transaction.
  *
  * <p>Application developer might want to extends this class and override this method to do other
  * things like compensate for any permanent changes during the conversation, and finally restart
  * business conversation. Or maybe give the user of the application a chance to merge some of his
  * work with fresh data... what can be done here depends on the applications design.
  *
  * @param exec the exection to clean up.
  * @param ex the StaleObjectStateException being thrown (and not handled) during the execution
  */
 protected void handleStaleObjectStateException(Execution exec, StaleObjectStateException ex) {
   log.error("This listener does not implement optimistic concurrency control!");
   rollback(exec, ex);
 }