1

We are using Apache CXF for hosting webservice. I have a basic question

Is it possible to get the soap message/payload inside actual webservice method? This webservice will save the values passed to it in database and at the same time we want to save the actual XML request/repsonse(payload) in database.

I have tried Handlers/Interceptors, I'm able to see the SOAP message there. But I want the XML payload in webservice method so that I can preform necessary action and save the payload to database.

WhyJava
  • 110
  • 3
  • 10
  • Please, check this answer, seems the problem is the same: http://stackoverflow.com/questions/11038313/how-to-get-incoming-outgoing-soap-xml-in-a-simple-way-using-apache-cxf – Igor K Jan 02 '14 at 16:00
  • Thanks for the help but I don't want interceptors because incoming interceptors pick up the payload before reaching the service methos. I want to get the XML payload in the service method itself. Any help on this would be very helpful. – WhyJava Jan 03 '14 at 06:46
  • No way to do it except Interceptors. By default, CXF discards everything as it's consumed. Here is the same answer on CXF forum: http://cxf.547215.n5.nabble.com/How-to-get-the-raw-or-XML-Payload-Inbound-Message-td5735401.html – Igor K Jan 03 '14 at 08:41

2 Answers2

3

it's been a long time since this question was asked but in case anyone would have the same issue:

the idea is to use the spring context as it's larger than the interceptor context

you need to register progrmmatically the XML request as a spring bean and then get it in your web service method

PS: both your interceptor and web service implementor must implement the ApplicaionContextAware interface

here is what I did and it worked for me:

in your interceptor :

@Component

public class XmlInInterceptor extends AbstractPhaseInterceptor<Message> implements ApplicationContextAware{

private static final String BEAN_NAME = "yourBeanName";

private ConfigurableApplicationContext context;

private DefaultSingletonBeanRegistry registry;

public XmlInInterceptor() {
    super(Phase.PRE_PROTOCOL);
}

 @Override
public void handleMessage(final Message message) throws Fault {

    try {
        // get the SOAP message as String
        final SOAPMessage soapMessage = message.getContent(SOAPMessage.class);

        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        soapMessage.writeTo(byteArrayOutputStream);

        final String encoding = (String) message.get(Message.ENCODING);
        final String xmlRequest = new String(byteArrayOutputStream.toByteArray(), encoding);

        //here is the fun part: here where you need to register the bean in runtime 

        SingletonBeanRegistry registry = context.getBeanFactory();

         // you must check if the bean is already registered and destroy it
         // otherwise the registerSingleton will fail 

        if(registry.containsSingleton(BEAN_NAME)){
            registry.destroySingleton(BEAN_NAME);
        }

        registry.registerSingleton(BEAN_NAME, xmlRequest);

    } catch (final Exception e) {

        logger.error(e.getMessage(), e);
        throw new Fault(e);
    }
}

public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {

    context = (ConfigurableApplicationContext) applicationContext;
    registry = (DefaultSingletonBeanRegistry) context.getBeanFactory();

}

in your web service method:

public class MyWebServiceImpl implements MyWebService, ApplicationContextAware {

 @Override
public Response myWebMethod(MyParams params) {

    //get the XML request as classic spring bean access
    final String xmlRequesteXML = applicationContext.getBean("xmlRequest", String.class);

//custom code here

}

public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {
    this.applicationContext =  applicationContext;      
    }
}
bolbol
  • 77
  • 10
  • Is it thread safe? I think no. Because if we have 1k requests the same time - what bean will have been taken in the service method? – nllsdfx Jul 03 '18 at 09:04
0

I think it's not possible. But you can use aspectj to catch the call of this method and after that you can get the SOAP Message