0

I am trying to call a URL from Java code in the following way:

userId = "Ankur";
template = "HelloAnkur";
value= "ParamValue";
String urlString = "https://graph.facebook.com/" + userId + "/notifications?template=" +
    template + "&href=processThis.jsp?param=" + value + "&access_token=abc123";

I have the following problems in this:

  1. When I do println(urlString), I see that the urlString only has the value upto and before the first ampersand (&). That is, it looks as: https://graph.facebook.com/Ankur/notifications?template=HelloAnkur and rest of it all (which should have been &href=processThis.jsp?param=ParamValue&access_toke=abc123) gets cut off. Why is that and how can I get and keep the full value in urlString? Does & needs to be escaped in a Java String, and if yes, how to do it?
  2. Notice that I am trying to pass a (relative) URL as a parameter value in this query (the value of href as processThis.jsp?param=ParamValue. How can I pass this type of value of href without mixing it up with the query of this URL (urlString), which only has three parameters template, href and access_token? That is, how can I hide or escape ? and =? Further, what would I need to do if value was Param Value (with a space)?
  3. Notice that the template has the value HelloAnkur (with no space). But if I wanted it to have space, as in Hello Ankur, how would I do it? Should I write it as Hello%20Ankur or Hello Ankur would be fine?
  4. I need the solution in such a way that URL url = new URL(urlString) can be created, or url can be created via URI. Please describe your answer up to this point as creating a safe URL is not straight forward in Java.

Thanks!

Ankur
  • 233
  • 3
  • 11
  • I don't use Java, but there's this link that talks about URLEncoding in Java, which is what you need for your URI I think: http://stackoverflow.com/questions/10786042/java-url-encoding – dKen Jun 06 '13 at 16:21
  • 1
    @dKen I tried this, it did not work for me. My first problem here is that the URL `String` gets truncated at the first `&`, and I don't know why. Your reference talks about encoding the query parameters' values. That is my later problem. – Ankur Jun 06 '13 at 19:53

1 Answers1

1

(this is going to become a classic)

Use URI Templates (RFC 6570). Using this implementation (disclaimer: mine), you can avoid all encoding problems altogether:

// Immutable, can be reused as many times as you wish
final URITemplate template = new URITemplate("https://graph.facebook.com/{userId}"
    + "/notifications?template={template}"
    + "&href=processThis.jsp?param={value}"
    + "&access_token=abc123");

final Map<String, VariableValue> vars = new HashMap<String, VariableValue>();

vars.put("userId", new ScalarValue("Ankur"));
vars.put("template", new ScalarValue("HelloAnkur"));
vars.put("value", new ScalarValue("ParamValue");

// Build the expanded string
final String expanded = template.expand(vars);

// Go with the string

Note that URI templates not only allow scalar values, but also arrays (the RFC calls these "lists" -- implemented as ListValue in the above) and maps (the RFC calls these "associative arrays" -- implemented as MapValue in the above).

Community
  • 1
  • 1
fge
  • 119,121
  • 33
  • 254
  • 329
  • How can I use your implementation -- will I have to import a package so that URITemplate can be recognized? Will I have to download something or can I copy-paste the code in some way in my project? BTW, I am using Eclipse and my code is deployed on Google App Engine. I would appreciate if you could provide directions. Thanks. – Ankur Jun 06 '13 at 19:30
  • Do you use maven in your project? – fge Jun 06 '13 at 19:31
  • I forgot: you can just download it from Maven central, see [here](http://mvnrepository.com/artifact/com.github.fge/uri-template/0.3). Note: Guava is also needed as a dependency. Other jars (testng, jackson-coreutils) are only needed for tests – fge Jun 06 '13 at 19:34
  • No, I don't use Maven or Guava. (I don't know what it is, and how it can be used with Eclipse and Google App Engine). – Ankur Jun 06 '13 at 19:56
  • No need for maven especially. But you'll need to download Guava. Follow the links to it in the link above. – fge Jun 06 '13 at 19:58
  • I saw the link. To understand you clearly, should I download the jar file from http://repo1.maven.org/maven2/com/google/guava/guava/r09/guava-r09.jar? Where do I save this file after that -- in the war directory? What will I have to download to get your implementation? To get the class `URITemplate`, what will I need to import? – Ankur Jun 06 '13 at 20:04
  • No, not r09, 14.0.1! As to my jar, you must also download http://repo1.maven.org/maven2/com/github/fge/uri-template/0.3/uri-template-0.3.jar -- the fact that `r09` appears first is a bug in the site, `r09` is a _very_ early version of Guava. – fge Jun 06 '13 at 20:07
  • Ok, I have downloaded both the files (Guava 14.0.1 and your jar file). Where do I save them? – Ankur Jun 06 '13 at 20:14
  • (I figured out how to include the jars, they just needed to be included in the Java build path as external jars) The method `URITemplate template = new URITemplate("https://graph.facebook.com/{userId}" + "/notifications?template={template}" + "&href=processThis.jsp?param={value}" + "&access_token=abc123");` is throwing `URITemplateParseException`. Any idea what can be done about this? – Ankur Jun 08 '13 at 01:14
  • Please tell the full error message: there must be the offset where it has failed, and the reason why – fge Jun 08 '13 at 01:16
  • FWIW, the code in my answer compiles and runs fine (save for a missing parenthesis which I have added) – fge Jun 08 '13 at 01:23
  • I got a message (`from getMessage()`) that no `suitable parser found (at offset 110)`. – Ankur Jun 08 '13 at 03:14
  • Open an issue on github (https://github.com/fge/uri-template/issues), and please put the relevant code with the full stack trace – fge Jun 08 '13 at 03:17
  • BTW, here is the actual code I have written: `template = new URITemplate("https://graph.facebook.com/{userId}" + "/notifications?template={template}" + "&href={href}" + "&access_token=12345601748147|hCLK3wsvBUMSafANub0HSFD0C9s");` Note that there is `|` character in `access_token`. Do you think this could cause problems? – Ankur Jun 08 '13 at 03:18
  • Yes, it will cause problems! It is not a valid literal character in a URI. The message is therefore normal. Make that access token a variable (as the user ID, etc). – fge Jun 08 '13 at 03:24
  • Thank you! It solved my problem completely. It is working like a charm! – Ankur Jun 08 '13 at 03:56
  • @Ankur you're welcome :) And in this "REST API" crazy age of ours, I surmise this library will be more and more used as time goes... – fge Jun 08 '13 at 03:59
  • I am an infrequent programmer in Java, so I am surprised to discover that there is no easy and straight forward way of calling a URL in the language. Your API will have uses in many more situations. – Ankur Jun 08 '13 at 05:03