5

So here's the scenario: We have PeopleSoft and want to send messages back and forth from salesforce. Unfortunately PeopleSoft doesn't have a tool like wsimport which consumes a wsdl and generates classes for you. There is something that consumes wsdl's, but all it does it generate stub message objects. A developer would still have to write the code to manually generate the xml message string.

I obviously don't want to do all of that. So I know that java can be called from within PeopleSoft. I also know I could send messages just using the generated classes, but I would like to use the message monitoring features built in to PeopleSoft.

So a possible solution that I am thinking of will:

  1. call the webservice method in java (without sending out the message)
  2. Grab the xml
  3. send the xml via peoplesoft mechanisms
  4. grab the response xml
  5. pass the response xml back into the response java class
  6. Use java classes to grab values within the xml

Am I crazy or is this possible?

p.s. i am a newbie java developer

Here's my handler class to grab the xml, but need some way to preventing message being sent out.

public class LoggingHandler implements SOAPHandler<SOAPMessageContext> {
 // change this to redirect output if desired
private static PrintStream out = System.out;
private String xmlOut = null;

public Set<QName> getHeaders() {
    return null;
}

public boolean handleMessage(SOAPMessageContext smc) {
    logToSystemOut(smc);
    return true;
}

public boolean handleFault(SOAPMessageContext smc) {
    logToSystemOut(smc);
    return true;
}

// nothing to clean up
public void close(MessageContext messageContext) {
}

public String getXmlOut() {
    return xmlOut;
}

/*
 * Check the MESSAGE_OUTBOUND_PROPERTY in the context
 * to see if this is an outgoing or incoming message.
 * Write a brief message to the print stream and
 * output the message. The writeTo() method can throw
 * SOAPException or IOException
 */
private void logToSystemOut(SOAPMessageContext smc) {
    Boolean outboundProperty = (Boolean)
        smc.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);


    SOAPMessage message = smc.getMessage();
    try {
        ByteArrayOutputStream baOut = new ByteArrayOutputStream();
        message.writeTo(baOut);
        xmlOut = new String(baOut.toByteArray());


    } catch (Exception e) {
        out.println("Exception in handler: " + e);
    }
}

}
willard
  • 252
  • 3
  • 10

3 Answers3

2

There is a systematic way of doing so in Java web services, JAX-WS. Just apply interceptor pattern using SOAP Handler. The handler class will intercept the message in handleMessage(SOAPMessageContext mc) method, do whatever you want to do with XML body of SOAP Envelope. and stop SOAPMessage further processing.

Then, you can treat the XML as you like (e.g. sending via peoplesoft mechanism). And when response come back from peoplesoft, bypass the outbound handler chain ... (I really have to look how to by pass a chain). I am just rolling the idea, you have to make POC. I never did so, otherwise I would have share code. But this is absolutely doable.

Asif Shahzad
  • 843
  • 2
  • 11
  • 21
  • If you are writing new web service endpoint, prefer Provider based mechanism instead SEI JAX-WS mechanism, as SEI is for higher abstraction and you want to work with generated XML. – Asif Shahzad Feb 07 '12 at 11:11
  • i've implemented a handler class by looking at examples, but not sure how I can stop the soap message from further processing. Any hints on that? Here's my handler class: ` public boolean handleMessage(SOAPMessageContext smc) { logToSystemOut(smc); return true; } private void logToSystemOut(SOAPMessageContext smc) { SOAPMessage message = smc.getMessage(); try { ByteArrayOutputStream baOut = new ByteArrayOutputStream(); message.writeTo(baOut); xmlOut = new String(baOut.toByteArray()); } }` – willard Feb 08 '12 at 14:41
  • 1. I think you are calling service from PeopleSoft, which are exposed by SalesForce. So you should define Handler at client side, because you want to intercept SOAP message the client side runtime generate (so that you can pass via PeopleSoft mechanism). The way you have defined handler is used to define handlers at server side. Client side handlers are defined differently. see http://bit.ly/zGerml to get an idea. – Asif Shahzad Feb 08 '12 at 20:13
  • 2. In the handler you have defined, you are not checking whether you are processing outbound msg or inbound. You are interested to get XML of outbound message initially (at PeopleSoft side), so simply add if((Boolean) lmc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY)) {... }. – Asif Shahzad Feb 08 '12 at 20:14
  • 3. Further processing of the handlers can be terminated by returning 'false' from handleMessage(..). But the main issue is, you are not only interested to stop further processing. You want to pause further processing, to get response through another way, and then resume the processing from some inbound message. No idea, how it can be done :( Its very tricky + interesting. – Asif Shahzad Feb 08 '12 at 20:20
  • I am ok with stopping processing. I would just need a way to get the raw xml back into the generated response object so I can read my values from there. Thanks for all your responses! – willard Feb 09 '12 at 17:18
1

One of the solutions might be to replace the SocketFatory of JAX-WS. Roughly it will look like this:

javax.net.SocketFactory socketFactory = new MySocketFactory();
Service service = Service.create(new URL(wsdl), new QName(namespace, servicename));
Dispatch<SOAPMessage> dispatch = service.createDispatch(methodToBeCalled, SOAPMessage.class, Service.Mode.MESSAGE);
dispatch.getRequestContext().put(com.sun.xml.ws.developer.JAXWSProperties.SSL_SOCKET_FACTORY, socketFactory);
// or ((BindingProvider) Service.getPort(SEIInterface.class)).getRequestContext().put(...);

And in MySocketFactory you are free to create sockets that will pipe the message to another channel.

dma_k
  • 10,431
  • 16
  • 76
  • 128
1

When you say that you only need the XML, are you talking about the SOAP message or just the request/response types? I'm not sure if your are talking about the second case, but if you only wanted the XML, why not using JAXB directly?

If that's the case, you could extract the schemas from the WSDL, generate your types (let's say you have RequestA and ResponseA for an operation "A" in the WSDL) and use JAXB's marshaller/unmarshaller to serialize/parse the XML. Then send it through the protocol that you want.

Denian
  • 737
  • 2
  • 8
  • 17
  • Directly using JAXB will take a lot of effort, as we not only need XML representation of messages but also complete SOAP message as well, so that service endpoint can understand. And secondly, when JAX-WS runtime also do this, then should not we explore/reuse it, instead of reinventing the wheel. – Asif Shahzad Feb 08 '12 at 20:29