OpenFeign / feign

Feign makes writing java http clients easier
Apache License 2.0
9.49k stars 1.93k forks source link

Support of SoapHeader #1005

Open snajberk opened 5 years ago

snajberk commented 5 years ago

Hi,

It would be great, if there could be some support of SoapHeaders when you are using Feign for legacy Soap calls. I just recently came to legacy API, where it was mandatory.

And having something like this would be absolutely amazing as headers might be marshalled objects.

@RequestLine("POST /getObject")
@Headers({
  "SOAPAction: getObject",
  "Content-Type: text/xml"
})
MyJaxbObjectResponse getObject(@SoapHeader MyJaxbHeader header, MyJaxbObjectRequest request);

Second best thing would be method annotation where you could define per method interceptor @SoapHeader(MyJaxbHeaderInterceptor.class)

The simplest solution (which I chose as it is the simplest one and it fit my need) would be to add interceptor in builder (to encoder).

I created copy of SoapEncoder SoapEncoderWithHeader(JAXBContextFactory jaxbContextFactory, MyJaxbHeaderInterceptor headerInterceptor) and I only had to add following two lines in encode method:

Marshaller headerMarshaller = jaxbContextFactory.createMarshaller(interceptor.getHeaderClass());
headerMarshaller.marshal(interceptor.createHeader(), soapMessage.getSOAPHeader());
ygorovitch commented 4 years ago

Hi, I have the same need.

taboubim commented 4 years ago

Hi, We have the same need here too !!! we need to pass security params in the header!! thanks

kdavisk6 commented 4 years ago

I suspect in the short term, you could extend the SOAPEncoder to append any custom values to the Envelope mimicking the desired behavior. I am leary however, of overloading @Headers to be context sensitive this way. That annotation is for Request headers and I think it should stay that way.

If we want to go the annotation route, we may custom Contract that can support those values. We are open to any potential suggestions and/or solutions.

osslite commented 4 years ago

Hi, we have the same needs. Using old systems connecting by soap and feign is great for this job

elesdoar commented 4 years ago

Try extending a SOAPEncoder class:

import feign.Headers;
import feign.RequestTemplate;
import feign.jaxb.JAXBContextFactory;
import feign.soap.SOAPEncoder;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.stream.Stream;

public class CustomSOAPEncoder extends SOAPEncoder {
    public CustomSOAPEncoder(JAXBContextFactory jaxbContextFactory) {
        super(jaxbContextFactory);
    }

    @Override
    public void encode(Object object, Type bodyType, RequestTemplate template) {
        super.encode(object, bodyType, template);
        Method method = template.methodMetadata().method();
        try {
            Headers headers = method.getDeclaredAnnotation(Headers.class);
            Stream.of(headers.value())
                .forEach(h -> {
                    String[] header = h.split(":");
                    if(header.length == 2) {
                        template.header(header[0], header[1].trim());
                    }
                });
        } catch (Exception ignored) {}
    }
}
CakeSpork commented 4 years ago

@elesdoar that would add HTTP headers, but not a in the Soap Envelope

Laess3r commented 3 years ago

I just created a PR for an easy solution. This enables any kind of modification to the SOAPMessage before it's finally encoded. An example is found in the javadoc.

https://github.com/OpenFeign/feign/pull/1503

odiego commented 2 years ago

Nice! Thanks for the PR.