3

For authentication with services such as Facebook, we redirect to Facebook, they do their authentication stuff, then they redirect back. Once they've redirected back, our code runs which does some things, then displays a response page. Which response page gets displayed depends on any number of things.

What we are doing now is:

class RedirectTargetPage extends WebPage {
    @Override public void onBeforeRender() {
        String getParam = getRequest().getQueryParameters()
            .getParamterValue("get-param");
        ......
        if (...) setResponsePage(PageOne.class);
        else if (...) setResposnePage(PageTwo.class);
        else ... // etc
    }
}

we then use urlFor(Class<Page>) to find the URL to this page, pass it to Facebook, Facebook redirects back to us after authentication, everything works well.

However, this isn't really a page? I mean it's just a piece of code sitting behind a URL which, at the end, calls setResponsePage. It seemed to me that what I was writing was just something that handled requests, it seemed I could create a IRequestHandler instead and get a URL to it using urlFor(IRequestHandler) with something like:

class RedirectTarget implements IRequestHandler {
    @Override public void respond(IRequestCycle requestCycle) {
        String getParam = requestCycle.getRequest().getQueryParameters()
            .getParameterValue("get-param");
        ....
        if (...) requestCycle.setResposnePage(..)
    }
}

Alas, urlFor(new RedirectTarget()) delivers null! What's going wrong? What can I do? Overriding onBeforeReder works but it doesn't seem elegant....

Adrian Smith
  • 17,236
  • 11
  • 71
  • 93

4 Answers4

0

While you could make RedirectTargetPage a page by loading different components based on the same conditions you now use to define which redirect page will be used, you should be able to go the IRequesthandler way too.

From the JavaDoc:

Returns the rendered URL for the request handler or null if the handler couldn't have been rendered.

It seems that your handler can't be rendered for some reason. Have you stepped through urlFor to see where it goes wrong?

Nicktar
  • 5,548
  • 1
  • 28
  • 43
0

You can use a custom request mapper for that:

public class FacebookResponseMapper implements IRequestMapper {

  @Override
  public int getCompatibilityScore(Request request) {
    if (getPage(request.getUrl()) != null) {
      return Integer.MAX_VALUE;
    }
    return 0;
  }

  @Override
  public IRequestHandler mapRequest(Request request) {
    Class<? extends Page> page = getPage(request.getUrl());
    if (page != null){
      return new RenderPageRequestHandler(new PageProvider(page));
    }

    return null;
  }

  /**
   * Get a page for the given url.
   */
  protected Class<? extends Page> getPage(Url url) {
    if (!url.getPath().startsWith("from-facebook") {
      return null;
    }

    // detect proper page depending on url parameters
    ...
  }

  @Override
  public Url mapHandler(IRequestHandler requestHandler) {
    return null;
  }
}

Register it in your application:

getRootRequestMapperAsCompound().add(new FacebookResponseMapper());
svenmeier
  • 5,681
  • 17
  • 22
0

I have the same problem and also used a custom implementation of IRequestHandler. I'm not sure if this was a good idea, though, because such handlers are mounted per instance and not per type as pages are.

So, unlike pages, you mount single instances of a request handler, e.g.:

mount(new MountMapper("path", CustomHandler.get()));

The get() method retrieves a singleton instance of CustomHandler. You can then produce links like so:

CharSequence relativeUrl = RequestCycle.get().urlFor(CustomHandler.get());
String link = RequestCycle.get().getUrlRenderer().renderFullUrl(Url.parse(relativeUrl));

This worked for me.

However, I don't see how I can specify query parameters when generating the link. With pages, you'd create a new instance of the page with its own specific map of parameters but since we have to use the one instance that is mounted, only, this doesn't work.

Wolfgang
  • 2,367
  • 23
  • 29
0

I may misunderstand, but why do you need all that extra non-page stuff?

Your going to be doing something with the users, why not send them to the page they want to go to directly and use a named parameter to direct them?

Example:

@MountPath(value = "/handlerpage/${fromparam}")
public class MyHandlerPage extends WebPage {
    public MyHandlerPage(PageParameters parameters) {
    super(parameters);
    final StringValue fromParam = parameters.get("fromparam");
        // Do my thing with page depending on the param.
    }
}

This would allow you to skip all the funky request handlers code. You can even set it up with option params if you need to.

Brill Pappin
  • 4,692
  • 1
  • 36
  • 36