Q:

Redirect from CustomProductDisplayCmd to 404 page if unavailable product

My custom implementation of a ProductDisplayCmd looks like this...
public void performExecute( ) throws ECException {
    super.performExecute();
    (my code here)

Now, if a product is unavailable, the super throws an ECApplicationException with this message:

com.ibm.commerce.exception.ECApplicationException: The catalog entry
  number "253739" and part number "9788703055992" is not valid for the
  current contract.

With a SEO enabled URL, I get redirected to our custom 404 page ("Gee sorry, that product is no longer available. Try one of our fantastic alternatives...")
http://bktestapp01.tm.dom/shop/sbk/bent-isager-nielsen-efterforskerne
With the old-style URL, i instead get an error page due to an untrapped exception.
http://bktestapp01.tm.dom/webapp/wcs/stores/servlet/ProductDisplay?langId=100&storeId=10651&catalogId=10013&club=SBK&productId=253739
Since I can catch the exception, I suppose I have the option of manually redirecting to the 404 page, but is that the way to go? In particular: The exception type does not seem to tell me exactly what is wrong, so I might accidentally make a 404 out of another kind of error.

A:

Here's what I ended up with: Catch the exception from super, then decide if the reason it was thrown is that the product is unavailable. If so, then redirect to the 404 page, else re-throw exception.
Implementation:
public void performExecute( ) throws ECException {
try {
    super.performExecute();
} catch (final ECApplicationException e) {
    // Let's see if the problem is something that should really be causing a redirect
    makeProductHelperAndRedirectTo404IfProductNotAvailable(e);
    // If we get here, noting else was thrown
    log.error("The reason super.performExecute threw an ECException is unknown and so we can't recover. Re-throwing it.");
    throw e;
}

...and in the makeProductblablabla method:
private ProductDataHelper makeProductHelperAndRedirectTo404IfProductNotAvailable(final ECException cause) throws ECSystemException,
        ECApplicationException {
    final ProductDataHelper productHelper;
    try {
        log.trace("Trying to determine if the reason super.performExecute threw an ECException is that the product is unavailable in the store. The execption is attached to this logline.", cause);
        productHelper = makeProductHelper(getProductId());
        if (productHelper != null) {
            if (!productHelper.isActiveInClub()) {
                log.trace("Decided that the reason super.performExecute threw an ECException is that the product is unavailable in the store. The execption is attached to this logline. NB! That exception is DISCARDED", cause);
                final String pn = productHelper.getISBN();
                final ECApplicationException systemException = new ECApplicationException(ECMessage._ERR_PROD_NOT_EXISTING, this.getClass().getName(), "productIsPublished", new Object[]{ pn });
                systemException.setErrorTaskName("ProductDisplayErrorView");
                throw systemException;
            }
        }
        return productHelper;
    } catch (RemoteException e) {
        log.error("I was trying to determine if the reason super.performExecute threw an ECException is that the product is unavailable in the store. The original ECException is attached to this logline. NB! That exception is DISCARDED", cause);
        throw new ECSystemException(ECMessage._ERR_GENERIC, super.getClass().getName(), "performExecute",ECMessageHelper.generateMsgParms(e.getMessage()), e);
    } catch (NamingException e) {
        log.error("I was trying to determine if the reason super.performExecute threw an ECException is that the product is unavailable in the store. The original ECException is attached to this logline. NB! That exception is DISCARDED", cause);
        throw new ECSystemException(ECMessage._ERR_GENERIC, super.getClass().getName(), "performExecute",ECMessageHelper.generateMsgParms(e.getMessage()), e);
    } catch (FinderException e) {
        log.error("I was trying to determine if the reason super.performExecute threw an ECException is that the product is unavailable in the store. The original ECException is attached to this logline. NB! That exception is DISCARDED", cause);
        throw new ECSystemException(ECMessage._ERR_GENERIC, super.getClass().getName(), "performExecute",ECMessageHelper.generateMsgParms(e.getMessage()), e);
    } catch (CreateException e) {
        log.error("I was trying to determine if the reason super.performExecute threw an ECException is that the product is unavailable in the store. The original ECException is attached to this logline. NB! That exception is DISCARDED", cause);
        throw new ECSystemException(ECMessage._ERR_GENERIC, super.getClass().getName(), "performExecute",ECMessageHelper.generateMsgParms(e.getMessage()), e);
    }
}

