4

For a project for my company, I have to send emails containing embedded URLs, which the user will be prompted to follow.

For example, a person registers on the website, and then the Struts2 application sends an email to that person in which there is a URL to confirm the subscription.

So far, the form submission, and sending the email (from inside the action), work just fine. The problem on which I'm stuck is that I can't find a way to generate the URL I'd like to embed in the mail body.

I must be doing it the wrong way, but I was thinking about something like what follows:

public String send() throws Exception {
    StringBuffer body = new StringBuffer();

    HashMap<String, String> params = new HashMap<String, String>();
    params.put("id", "xxxxxyyyyyaaaaa");

    body.append("Veuillez vous rendre ici :");
    body.append(UrlManager.getUrlForAction("action", params));

    SendMail sendMail = new SendMail();
    sendMail.send("me@me.fr", "Information", body.toString());

    return SUCCESS;
}

where there would be a UrlManager (something that could be made available by the framework) with a method getUrlForAction() that gets an action and its parameters as input and that outputs a String containing the corresponding URL (like http://mysite.mycompany.com/confirm?id=xxxxxyyyyyaaaaa).

Does anyone have any ideas or pointers on how to do that?

EDIT:

I tried using UrlProvider, but I get a null pointer exception on the determineActionUrl call. Maybe I'm using it the wrong way.

HashMap<String,Object> params = new HashMap<String,Object>();
params.put("id", data.getMd5());

UrlProvider up = new ComponentUrlProvider(
                            new Component(ServletActionContext.getValueStack(ServletActionContext.getRequest())),
                            ServletActionContext.getRequest().getParameterMap());
downloadUrl = up.determineActionURL("confirm", "/", "GET",
                                    ServletActionContext.getRequest(),
                                    ServletActionContext.getResponse(),
                                    params,
                                    "http", true, true, true, true);
Roman C
  • 49,761
  • 33
  • 66
  • 176
  • can you be more specific in terms of " can't find a way to generate the URL". Have you tried the above code you posted yourself ? if you have tried it, do you get any error. " I was thinking about something like what follows" is not good enough. Try it and see what errors or problems you encounter. – grepit Jul 03 '13 at 13:44
  • Did you write that `UrlManager` or `SendMail`? It couldn't be found in Struts2 framework. – Roman C Jul 03 '13 at 13:57
  • Yes, I "wrote" both. Actually, SendMail is just a helper I wrote for my project, but UrlManager is just not real. It's more what I'd like it to be and work, like UrlHelper which is close to what I want but doesn't actually do what I need, say generate the example url. UrlHelper omits the port in use (here 8080 for dev machine), and adds ".action" to the URL. – Fabrice AGNELLO Jul 03 '13 at 14:14
  • @CPU100, the above code won't do it, since my best try was to use UrlHelper which didn't give the result I'm expecting (it omits the port, adds ".action" to the url, etc.) even if I have configured struts to have no action extension, and set the port to 8080 (struts.http.port=8080). – Fabrice AGNELLO Jul 03 '13 at 14:18
  • @FabriceAGNELLO How did you use UrlHelper? Edit the question and share your experience. Also provide what's wrong with default UrlHelper? – Roman C Jul 03 '13 at 14:55

2 Answers2

2

You need to create the properties (dependencies) in your action

@Inject
public void setActionMapper(ActionMapper actionMapper) {
  this.actionMapper = actionMapper;
}

private UrlHelper urlHelper;

@Inject
public void setUrlHelper(UrlHelper urlHelper) {
  this.urlHelper = urlHelper;
}

then in the action you could write something like

Map<String, Object> parameters = new HashMap<>();
ActionMapping mapping = new ActionMapping("action", "namespace", "", parameters);
String uri = actionMapper.getUriFromActionMapping(mapping);
String url  = urlHelper.buildUrl(uri, ServletActionContext.getRequest(), ServletActionContext.getResponse(), parameters, "http", true, false, true, false);
Roman C
  • 49,761
  • 33
  • 66
  • 176
  • 1
    Roman, the injection part was what I was missing. doing as you tell is working plain fine, so the issue is closed. thanks a lot. – Fabrice AGNELLO Jul 03 '13 at 18:00
0

You may take a look at Struts' UrlProvider.determineActionURL, which does what you need.

UPDATE Indeed I needed to use this method some weeks ago and I remember some NPE's rising around... At the end, I was able to write the following code (adapted from my app):

String getMyActionUrl() throws Exception {

    ActionInvocation invocation = (ActionInvocation) ActionContext
            .getContext().get(ActionContext.ACTION_INVOCATION);

    org.apache.struts2.components.URL url = new org.apache.struts2.components.URL(invocation.getStack(), getServletRequest(),
            getServletResponse());
    url.addParameter("parameterToBeDeleted", null);
    url.addParameter("newParam", newValue);
    url.setActionMapper(new DefaultActionMapper());
    url.setUrlHelper(new DefaultUrlHelper());

    String myUrl = url
            .getUrlProvider()
            .determineActionURL(
                    "MyActionName",
                    invocation.getProxy().getNamespace(),
                    invocation.getProxy().getMethod(),
                    getServletRequest(),
                    getServletResponse(),
                    getServletRequest().getParameterMap(),
                    "http",
                    true, true, false, false);

    return myUrl;

}

Notes:

  • MyActionName is here as a String -- not a great maintanable code. Make sure it matches the name you give to the action (which may differ from the name of the Action class handling calls to that action).

  • http is hardcoded. Change if needed.

orique
  • 1,295
  • 1
  • 27
  • 36
  • I'll try to find how to use this method, but it looks pretty similar to UrlHelper which does not completely address the issue. Maybe I'll be more lucky with this one. – Fabrice AGNELLO Jul 03 '13 at 14:23
  • I have edited my initial post. I get a NullPointerException using (probably the wrong way) the UrlProvider.determineActionURL method. Do you have a clue on what's wrong ? – Fabrice AGNELLO Jul 03 '13 at 14:45
  • @FabriceAGNELLO Updated answer. HTH :) – orique Jul 03 '13 at 15:02
  • 1
    I finally tried the solution given by Roman C., and it works like a charm. Your solution seems to be fine as well, but I will stay on the Roman's solution.Thanks anyway for your help. – Fabrice AGNELLO Jul 03 '13 at 18:04