News: Lessons learned from getting .NET to REST with Java
On a recent project I had to call Java REST services from a .NET Client. Several problems came up – ranging from authentication to hidden performance issues. I want to share my lessons learned and encourage you to share your own opinions and experiences on this topic. Read the full article at blog.dynatrace.com
- Posted by: Andreas Grabner
- Posted on: August 26 2009 06:44 EDT
- new math? by James Watson on August 26 2009 11:42 EDT
- Re: Lessons learned from getting .NET to REST with Java by James Watson on August 26 2009 11:46 EDT
- Re: Lessons learned from getting .NET to REST with Java by Manolo Gomez on August 26 2009 13:53 EDT
- Re: Lessons learned from getting .NET to REST with Java by Andreas Grabner on August 26 2009 23:34 EDT
- Re: Lessons learned from getting .NET to REST with Java by Bill Burke on August 27 2009 10:32 EDT
- Re: Lessons learned from getting .NET to REST with Java by Nicholas Hrycan on August 30 2009 21:19 EDT
There are two performance penalties here: * an extra roundtrip to the server for every request to the server that is done on a new connection * doubled network utilization. Especially for HTTP POST requests with large content this can easily become a big problemHow do you get double the network utilization? The 401 should happen only rarely. The client doesn't have to wait for the 401, it can send the authentication info right away. And if you are using digest authentication, you just get the nonce value at the beginning and send the authentication info on each request until you get another 401. And since authentication is expected, don't do a post right off the bat. Do a get or a head first and then do your post with the authentication.
Hi James If you use the standard approach of how I used the .NET Framework to send a REST POST request that requires authentication you end up with 2 requests sent by the .NET Framework. Both requests are POST requests including the FULL body and therefore doubling the required network bandwidth. You are correct that - once authenticated and you make additional requests that these don't cause the additional roundtrip. In my scenario my .NET client always only sent one REST request per connection -> therefore I always ran into that problem. Thanks for your insight about alternative approaches. My workaround is definitely only one of several that works here
The next service I called required HTTP POST. It is a service that allows starting a new session recording. From a REST definition perspective this call should probably be a HTTP GET as we are not posting new resources to the server – we are “just” triggering an action.If I understand what you mean by "triggering an action", you should never do that with a GET. That's not REST. GETs should be 'safe' meaning they don't have any side effects. It depends on what the action is but most likely you should be doing a POST.
I have been recently implementing a system in both .NET and Java using REST/JSON for communication and so far, I had no problems, even with large sets of data, but my set up is somewhat different than the one described in the article. The Java application it's basically a fachade to a biometric device which has it's own internal handling protocols. The service was built using Jersey for REST and flexjson for serialization. I got it up and ready in almost no time and works like a charm. Tested in Resin and Tomcat against PHP and .NET clients. The .NET application is a web app built with MonoRails and it consumes data from the Java service. Ii was using WCF initially and it worked but I turned to a simpler HttpWebRequest based solution because I wanted to have finer control over the received JSON, although the service interface retains the WCF attributes (annotations) in case I decide to switch later. It was clunky at first but now it runs very good. I've had no performance problems, even when sending thousands of records over the wire and taking into account that the Java service has to run in an older Pentium 3 Windows 2000 box with less than 512 MB of RAM (don't ask, hehe). As for authentication, I haven't tested it yet but I tend to agree with the head-then-post solution
Thanks Manolo for sharing your experience I agree - James suggestion about the HEAD request sounds like a very good solution. I am wondering if there is anything built-into the .NET Framework that would follow such an approach when knowing that authentication is required?
HttpURLConnection and Apache HTTP Client have the same "performance" problem with initial authentication. They send a non-authenticated request first and wait for a challenge from the server. Apache HTTP Client though does let you do preemptive authentication with both Basic and Digest authentication. I'm wondering if the "interoperability" problem is a Jetty bug as I'm pretty sure I've done authentication challenges with a Java client (with the same headers). In looking at the SErver header, it says you're using Jetty 5.1. You might want to take a look at bumping up to the last 6.x version. -- Bill Burke JBoss http://jboss.org/resteasy http://bill.burkecentral.com
Analyze the actual network traffic between your client and your serverThose are words of wisdom. Sometimes you need to see the low level details.