WCF MTOM/XOP Client Deserialization Error - java

This is one of those SO 'questions' that i've already answered, but am posting b/c there seems to be next to zero information out there based on a week of Googling.
TL;DR: WCF MTOM encoded BasicHttpBinding client to external/3rd part, non-.NET web service chokes on XOP processing of MTOM response - basically MTOM encoder seems to be expecting a base64 payload in binary element, but runs in to the ... directive and fails deserializing SOAP/XML to runtime object, thus throwing error in this question's Title.
Error: End element 'MyBinaryData' from namespace 'http://mynamespace' expected. Found element 'xop:Include' from namespace 'http://www.w3.org/2004/08/xop/'
As previously noted, there's not much out there on this topic, i'm guessing b/c MS wrote most of their WCF documentation based on service development, and not so much client (although there is some, to be fair).
I'm not going to go in to the nitty-gritty initial set up b/c i'm about to answer my own question, but i'll preface the answer by saying that this was much more akin to a default configuration of WCF MTOM than not.
Also, i know WCF is old, boring, and no longer actively developed by MS, but it is still supported and there are plenty of uses for it. I actually i didn't have much of a choice and had to find a way to make this work. This is why i'm sharing my findings with anyone else that has to deal with this kind of headache.

TL;DR: check http headers to see if service response is "Transfer-Encoding: chunked" (streamed) to you and if so, use transferMode="StreamedResponse" in your binding configuration.
So after Googling for days with no help, i spun up Fiddler for http traffic capture - this requires your WCF basic http binding configuration to proxy in to Fiddler (http://localhost:8888 by default, i think) and depending on where your target service resides you may or may not need to configure Fiddler's Gateway settings (corporate proxy, etc.).
This allowed me to see the raw text being sent between my client to/from their service; all payloads were coming in just fine, which meant, in my case, that the MTOM/XOP response from the service was being completely transmitted and that the WCF runtime was not interpreting the response correctly. Another critical thing i saw was that the Transfer-Encoding http header was "chunked" and there was no Content-Length header... this meant that the service was streaming the response, as opposed to a buffered response. Now a little side note: MS's WCF MTOM documentation has a call-out saying that you should always use "Buffered" as your transferMode in your binding configuration... but failed to mention that was really only applicable in Services, not necessarily clients!
So naturally, i simply went in to my config file, found system.serviceModel >> bindings >> basicHttpBinding collection, found my specific binding configuration and set transferMode="StreamedResponse" (because the 3rd party service was streaming my response back to my client).

Related

Axis2/CXF SAOP web service receiving huge inline attachments

I use Java SOAP web-service based on Axis2 1.4.1 to exchange data and attachments since years; no matter so far even if big attachments since the web-service implements MTOM.
This till last week, when a webservice WS client started sending huge attachments (around 1GB) as base64 inline text within the SOAP body (no MTOM no SwA).
I was confident that Axis2 attachment caching feature would solve also in this case, but this is not true and OutOfMemory occurs.
After some attempts my understanding is that attachments are cached to disk (and not kept in memory) only if the WS client sends them as MIME parts.If sent as base64 text within the SOAP body they are kept in memory.
I also tried to replace Axis2 with CXF (I'm prepared to change my WS framework if it is the only solution) but I experimented exactly the same behavior.
I'm wondering if I'm missing something or someone having my same issue found a solution.
I cant't believe that my webservice can manage big attachments only if the client implements MTOM.
Thanks in advance for any possible suggestion.

If i sent the following response to my browser, am I supposed to get any kind of feedback?

For an assignment, I have written a server that services HTML files and I am supposed to use my web browser as a test client. I am also told that if there is a request for a file that doesn't exist i should send the following
HTTP/1.1 404 Not Found\r\n\r\n and if anything else goes wrong
HTTP/1.1 500 Internal Server Error\r\n\r\n"
I have run tests that should cause those to be sent, but nothing occurs in my browser window? Should I be getting any visual feedback from sending such a request?
In an HTML response there should only be one CRLF (carriage return and line feed) after each line. So you can first remove the extra \r\n.
Also on the second line you can send an HTML response back to the client saying what the error was if you want to show an error. This is normally what a typical web server does where it has its default error page if one is not defined. If you are not sending any HTTP headers, then you can insert the HTML body you want to send back such as <h1> No page found</h1> as the second line.
To include an "entity" in an http response
HTTP/1.1 404 Not Found
Content-Type: text/html
Content-Length: 10
01234576789
each line is ended by CRLF. Be sure to count the Content-Length correctly.
I see that this is a learning exercise, and understand that you may have been told to implement the server this way. But bearing that in mind ...
This is the wrong way to implement a web server / service. The right way is to find an existing implementation and build your service on top of that.
You could use a Java EE web container; i.e. something that implements the Servlets spec.
You could use a non-servlet framework (like Grizzly).
You could build on top of a server-side HTTP protocol stack; e.g. using Apache the HttpComponent library.
Building a web server from the ground up is a lot of work if you are going to do it properly. And the chances that you won't do it properly; i.e. you won't implement your service according how the HTTP spec says a server should behave. You will leave things out, do things the wrong way, etc.
Please don't do it. There are already too many broken (i.e. non-compliant) web servers out there. We don't need more.
And if you DO decide to implement HTTP from the ground up, then you (YOU) need to thoroughly read and understand the HTTP spec. And you (YOU) need to do your own basic research on how browsers implement the client side of the spec ... and what you therefore need to do on the server side to make browsers behave "normally".

How do I use Apache Http Components to relay a POST request from a servlet?

I'm a little unfamiliar both with the Servlet API and Apache Http Components.
I need to handle an incoming POST request with unknown data (although probably the result of a form submission) using HttpServlet.doPost() which I've implemented, and request the same posted information from another URL, effectively acting as a relay for the HTTP POST. I then need to convert the response to a String (it will be text/html) and process it further before returning it to the web browser that requested it from me.
Due to my unfamiliarity with these libraries, its not clear to me how to handle issues like the content-type of the posted data, and also avoiding any problems due to neglecting to release resources.
Can anyone provide any pointers on this?
You should start by having a look at HttpClient class from apache API.
It will handle both get and posts as needed and later you could feel its request with the data you receive in your own servlet.

Java HttpServletResponse with blank-value headers?

How can I make a java-based application server reply with an empty-valued response header, like this?
content-length:\r\n
Unfortunately when I call
response.setHeader("Content-Length", len)
where len is either an empty string or null, the response will not include the header.
I've checked the HttpServletResponse and HttpServletResponseWrapper javadocs but couldn't figure out what could be overriden to provide my custom behaviour.
Background
I'm building a testing application that is supposed to emulate badly-behaved HTTP server scenarios. The application is supposed to reply to requests with preset pages and HTTP headers, including malformed ones like the above case.
The application is written in grails.
I'm building a testing application that is supposed to emulate badly-behaved HTTP server scenarios.
In such a case, attempting to get a well-behaving server to mimic such behavior is a bad idea. If you need to mimic a bad server, or a particular set of scenarios you wish to test, then you may do one of the following:
write a custom application that listens on a particular port (using the ServerSocket class) that will respond with malformed HTTP headers. Using HTTP libraries may not help, for libraries may have code to detect erroneous conditions and correct them automatically.
use a HTTP proxy that is capable of intercepting responses and allows for modifications of these responses. You will find several if you Google for "http debugging proxy", but if you haven't heard of any, I would suggest looking at Fiddler, WebScarab or Burp.
You can try a tool like SoapUI or Fiddler with it's Firefox extension. I havent tried setting a malformed header with them but I wouldn't be suprised if you could.
Something not clear for me: your application is written in Grails, but you are discussing of javadocs... Well, I suppose you try to create a bad server in JAVA...
As you said, answering with "Content-Length:\r\n" is not legal for HTTP. You must put an integer value or discard the header. I think setHeader() helps you to avoid to produce an illegal HTTP message.
You can workaround this way creating manually the headers (you can write directly to the socket without using the setHeader blocks).
Other solution is to create a filter (in addition of your servlet) with your own implementation of HttpServletResponse. You will pass this implementation to the servlet.

Using HTTP OPTIONS to retrieve information about REST resources

This problem relates to the Restlet framework and Java
When a client wants to discover the resources available on a server - they must send an HTTP request with OPTIONS as the request type. This is fine I guess for non human readable clients - i.e. in code rather than a browser.
The problem I see here is - browsers (human readable) using GET, will NOT be able to quickly discover the resources available to them and find out some extra help documentation etc - because they do not use OPTIONS as a request type.
Is there a way to make a browser send an OPTIONS/GET request so the server can fire back formatted XML to the client (as this is what happens in Restlet - i.e. the server response is to send all information back as XML), and display this in the browser?
Or have I got my thinking all wrong - i.e. the point of OPTIONS is that is meant to be used inside a client's code and not meant to be read via a browser.
Use the TunnelService (which by default is already enabled) and simply add the method=OPTIONS query parameter to your URL.
(The Restlet FAQ Q19 is a similar question.)
I think OPTIONS is not designed to be 'user-visible'.
How would you dispatch an OPTIONS request from the browser ? (note that the form element only allows GET and POST).
You could send it using XmlHttpRequest and then get back XML in your Javascript callback and render it appropriately. But I'm not convinced this is something that your user should really know about!

Categories