4

I am using a Java server that exposes a RESTful API on the following URL:

http://localhost:8080/my-server/

The docs recommend using curl for submitting simple PUT requests (file uploads), and strongly recommend users to use the exact same arguments as provided in the examples. All of the examples look like this:

curl -X PUT -f -u admin:password --data-binary @/absolute/path/file/to/upload/file.ext "http://localhost:8080/my-server/file.ext"

This server will not work with FTP or any other normal transfer protocol.

I found this question on SO where the answer-er recommended using java.net.URL and its companion java.net.URLConnection instead of trying to work with curl/libcurl.

I've never even ran a curl command before, so I am asking anyone who knows both curl and Java if URL/URLConnection (or any other Java framework) can be used instead of curl for my specific problem here. If not, then I will have to write a component that executes commands from the local command-line/terminal, and then execute the above curl command inside that component, and that just feels ugly/nasty.

If I can accomplish the same thing in a Java network API, I would prefer to do it that way.

And, if it can be done in Java, how would I use URL/URLConnection to set up the exact same command arguments as the example I provided? Specifically:

  • -X
  • PUT
  • -f
  • -u admin:password
  • --data-binary
  • -@absolute/path/...

Thanks in advance for any insight here or nudges in the right direction!

Community
  • 1
  • 1
IAmYourFaja
  • 55,468
  • 181
  • 466
  • 756

3 Answers3

6

I believe this is more-or-less equivalent using Java and :

try {
    Credentials credentials = new UsernamePasswordCredentials("admin", "password");  //-u admin:password
    DefaultHttpClient httpClient = new DefaultHttpClient();
    httpClient.getCredentialsProvider().setCredentials(AuthScope.ANY, credentials);
    HttpPut put = new HttpPut("http://localhost:8080/my-server/file.ext");  //-X PUT
    put.setEntity(new FileEntity(new File("/absolute/path/file/to/upload/file.ext"), "image/png"));  //@ - absolute path
    httpClient.execute(put);
} catch(Exception e) {
    //-f, fail silently
}
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Wow, thanks Tomasz (and +1 for the code example!). Real quick, can you explain to me how the arguments I listed map to your code (besides the `-u user:password`, thats pretty self-explanatory). Particularly interested in `-X`, `-f`, `--data-binary`, and the `@absolute` identifier. Thanks again for a great response! – IAmYourFaja Feb 28 '12 at 18:22
  • 1
    `-X` means next parameter is protocol (`PUT`), `-f` does not print error pages if the server returns them, `--data-binary` disables automatic newline conversions, and the `@` means that the data come from a file path instead of being given on the command line. – mihi Feb 28 '12 at 18:48
  • @AdamTannon: *mihi* did a great job in explaining these options, I added comments to my code sample as well. – Tomasz Nurkiewicz Feb 28 '12 at 18:52
1

curl is a command line unix utility that you just need to pass options to. Using java.net, or apache httpclient will require you writing code which uses those packages to talk to your rest service. It's not hard to do, and you certainly can fulfill the requirements of your service, but it's not as easy as just using curl.

Rick Mangi
  • 3,761
  • 1
  • 14
  • 17
  • Thanks Rick - I found [this](http://www.javalobby.org/java/forums/t53333.html) article on running terminal commands from a Java app. If I go this route, will running a similar implementation to that author's code execute curl for me (provided I have curl installed locally)? Or am I off-base here? – IAmYourFaja Feb 28 '12 at 18:20
  • It will, but if you're doing this from code I would recommend using httpclient as Tomasz recommended above. That's going to be much more flexible and less error-prone. – Rick Mangi Feb 28 '12 at 19:30
0

If you are doing some quick 'n' dirty manual testing, learning curl is the way to go because of its ubiquity.

But it's not worth the effort to try to integrate it into Java (calling other processes from Java is fraught with pitfalls; see here http://kylecartmell.com/?p=9) so if your connection is part of an integration test or something, using plain Java is much cleaner and more portable. It's also easier to debug what's going on when things fail.

man curl is your friend for figuring out those options, but to get you started:

HttpURLConnection bla = (HttpURLConnection) new URL("http://localhost:8080/my-server/").openConnection();
bla.setRequestMethod("PUT");
bla.connect();  
// Now read the inputstream / write the outputstream 
// per the linked answer in the original question 
artbristol
  • 32,010
  • 5
  • 70
  • 103