Question

My problem is similar to: JAX-WS SoapHandler with large messages: OutOfMemoryError and JAXWS Soap Handler Large MTOM Attachments

I am using tomcat, the Metro-Runtime-Configuration, and when I want to add a header in my HandlerChain it gives me a OutOfMemory exception.

public boolean handleMessage(SOAPMessageContext smc) {
    if (Boolean.TRUE.equals(smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY))) {
        SOAPMessage sm = smc.getMessage(); // <- OutOfMemory
        ...

In the first link Ahmed writes that I was able to write code that handles the raw data stream in 3 out of the 4 cases. Fortunately the three cases included the two we were mostly interested in: to/from the server. but he doesn't provide a code snippet for that.

Things I tried:

The OutOfMemory occurs in JDK7 AbstractMessageImpl#readAsSOAPMessage which I wasn't able to override. Is it possible to override that class using a custom bootstrap? And how to do so? I was able to "override" the Integer-class, but the AbstractMessageImpl was not taken.

Changing the runtime to Apache CXF did not work with my generated JAX-WS RI Clients (Cannot create a secure XMLInputFactory)

Is there another possibility to use another provider/runtime? And if not, how can I override JDK7's AbstractMessageImpl#readAsSOAPMessage?

OR: is it possible to configure the order of MTOM and the handler chains? A MTOM'ed message shouldn't throw a OutOfMemory, is that right?

Thanks in advance crappi

Was it helpful?

Solution

This problem is also found in the ticket reports here: https://java.net/jira/browse/WSIT-1081

I solved this problem by not using a handler but adding a header when creating a port like this:

Web-Service-Creation

WebServiceEndpoint endpoint = w.getWebServiceEndpointPort(new MTOMFeature());
Map<String, Object> ctxt = ((BindingProvider) endpoint).getRequestContext();
// Enable HTTP chunking mode, otherwise HttpURLConnection buffers
ctxt.put("com.sun.xml.ws.transport.http.client.streaming.chunk.size", 8192);
WSBindingProvider bp = (WSBindingProvider) endpoint;
bp.setOutboundHeaders(Headers.create(JAXBContext.newInstance(WSSecurityHeader.class), 
                      new WSSecurityHeader()));

Since Header-creation is not provided with methods, JAXB is used for complex header types.

WSSecurityHeader.java

@XmlRootElement(name = "Security")
public class WSSecurityHeader {

    @XmlElement(name = "UsernameToken")
    public WSSecurityUsernameToken usernameToken = new WSSecurityUsernameToken();
    ...
}

Disadvantages

The client needs many libraries that this code is working: JAXB, JAX-WS, StreamBuffer, Policy, Stax-Ex, gmbal-api-only, which is horrible for just adding a header. (Especially if you are working with a fat client without maven support)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top