title: Any way to send %2b (encoded plus sign) in query arg with java.net.URI?
body: <p>I can't seem to find this mentioned explicitly, but it seems that you can't send an escaped plus sign ("%2b") as a query arg value if you're using java.net.URI, since the query arg is escaped.</p>
  
  <pre><code>// bad: http://example.com/foo?a=%252b
  new URI("http", null, "example.com", 80, "/foo", "a=%2b", null);
  </code></pre>
  
  <p>Tried an actual "+" character, but that gets sent as-is, so the server will interpret it as a space.</p>
  
  <pre><code>// bad: http://example.com/foo?a=+
  new URI("http", null, "example.com", 80, "/foo", "a=+", null);
  </code></pre>
  
  <p>So I guess you just have to do the percent-encoding of the query arg keys and values yourself and use the single-argument URI constructor that doesn't escape? Maybe let URI escape the "path", since the rules are tricky (eg, the "+" character means a plus character, not a space, when in the path):</p>
  
  <pre><code>// good: http://example.com/foo?a=%2b
  new URI(new URI("http", null, "example.com", 80, "/foo", null, null).toASCIIString() + "?a=%2b");
  </code></pre>
  
  <p>Also, the docs claim you can create a URI like this and it will be identical to the source URI:</p>
  
  <pre><code>URI u = ...;
  URI identical = new URI(u.getScheme(),
          u.getUserInfo(),
          u.getPath(), u.getQuery(),
          u.getFragment());
  </code></pre>
  
  <p>but that's not true when it contains %2b</p>
  
  <pre><code>URI u = new URI("http://example.com:80/foo?a=%2b");
  URI identical = ...; // not identical! http://example.com:80/foo?a=+
  </code></pre>
  
  <p>Frustrating, I guess that's why everyone uses apache commons or spring classes instead?</p>
  
  <p>PS: <a href="http://docs.oracle.com/javase/6/docs/api/java/net/URI.html">http://docs.oracle.com/javase/6/docs/api/java/net/URI.html</a> references a URI constructor that does not exist in "the following identities also hold" section. It needs to remove the "authority" parameter.</p>