Can I redirect to a valid Wicket page when attempt

2019-07-16 12:48发布

问题:

Introduction

If a user of my Apache Wicket web application (which runs on GAE/J) attempts to visit a non-existent page, for example:

http://[MyURL]/admin/PageSubscribeX

the web framework logs the following warning:

org.apache.wicket.core.util.lang.WicketObjects resolveClass: Could not resolve class [[...].admin.PageSubscribeX]
java.lang.ClassNotFoundException: [...].admin.PageSubscribeX
    at com.google.appengine.runtime.Request.process-78915baf06af5f31(Request.java)
    at java.lang.Class.forName(Class.java:133)
    at org.apache.wicket.application.AbstractClassResolver.resolveClass(AbstractClassResolver.java:108)
    at org.apache.wicket.core.util.lang.WicketObjects.resolveClass(WicketObjects.java:71)
    at org.apache.wicket.core.request.mapper.AbstractComponentMapper.getPageClass(AbstractComponentMapper.java:139)
    at org.apache.wicket.core.request.mapper.PackageMapper.parseRequest(PackageMapper.java:148)
    ...
    at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:458)
    at java.lang.Thread.run(Thread.java:679)

and GAE/J responds with an error 404 page and the text Error: NOT_FOUND.

I know that currently with GAE/J I "cannot customize the 404 response page when no servlet mapping is defined for a URL".

My question

Is there any way I can specify a Wicket page for the response when no servlet mapping is defined for a URL? Alternatively, is there some servlet mapping I can define to map "all URLs not found" to a Wicket page of my choice?

My software environment is:

  • Wicket: 6.2.0
  • GAE/J: 1.7.3
  • Java: 1.6.0_37.

A failed attempt

Following the comments of @biziclop, I have tried the following, but this failed. All I got was my error page PageError showing every time....

My code in my WebApplication#init() was:

ICompoundRequestMapper crmRoot = getRootRequestMapperAsCompound();
URLNotFoundMapper mapperURLNotFound = new URLNotFoundMapper(null,
 PageError.class);
crmRoot.add(mapperURLNotFound);
setRootRequestMapper(crmRoot);

My new mapper URLNotFoundMapper was

/**
 * This mapper class is intended to be the mapper of last resort, to be used
 * if all other mappers cannot handle the URL of the current request.
 * <br/>
 * This mapper will cause a defined (error) page to be shown.
 */
public class URLNotFoundMapper extends BookmarkableMapper
{
  private IRequestMapper m_rmRoot = null;
  private Class<? extends IRequestablePage> m_classPage = null;

  /**
   * Constructor.
   * @param rmRoot
   *   The application's previous root request mapper.
   *   If this is <code>null</code> then it is ignored.
   * @param clError
   *   The class of the page which should handle erroneous requests.
   *   This must not be <code>null</code>.
   */
  public URLNotFoundMapper(IRequestMapper rmRoot,
   final Class<? extends IRequestablePage> clError)
  {
    m_rmRoot = rmRoot;
    m_classPage = clError;
  }

  /**
   * Use this mapper as the last option.
   * So let all other mappers try to handle the request first.
   * @param request
   *   The request.
   * @return
   *   The score of the application's previous root request mapper.
   */
  @Override
  public int getCompatibilityScore(Request request)
  {
    return Integer.MIN_VALUE;
  }

  /**
   * This method returns an <code>IRequestHandler</code> for the bookmarkable
   * error page.
   * @param request
   * @return
   *   An <code>IRequestHandler</code> capable of processing a bookmarkable
   *   request.
   *
   */
  @Override
  public IRequestHandler mapRequest(Request request)
  {
    IRequestHandler rhResult = null;
    if (m_rmRoot != null)
      rhResult = m_rmRoot.mapRequest(request);

    if (rhResult != null)
      rhResult = null;    // Another mapper can handle this
    else
    {
      rhResult = processBookmarkable(m_classPage, null);
    }

    return rhResult;
  }

  @Override
  public Url mapHandler(IRequestHandler requestHandler)
  {
    Url urlResult = null;
    if (m_rmRoot != null)
      urlResult = m_rmRoot.mapHandler(requestHandler);

    if (urlResult != null)
      urlResult = null;    // Another mapper can handle this
    else
    {
      PageInfo info = new PageInfo();
      UrlInfo urlInfo = new UrlInfo(new PageComponentInfo(info, null),
       m_classPage, null);
      urlResult = buildUrl(urlInfo);
    }

    return urlResult;
  }

  /**
   * @return
   *   The URL info for the bookmarkable error page.
   */
  @Override
  protected UrlInfo parseRequest(Request request)
  {
    UrlInfo uiResult = null;
    uiResult = new UrlInfo(null, m_classPage, null);
    return uiResult;
  }
}

回答1:

you need to configure the 404 http error in your webapp, take a look here

The questioner's extract from the link above is:

<error-page>
  <error-code>404</error-code>
  <location>/[URI portion to point to a customer error page]</location>
</error-page>