Search code examples
javaweb-serviceswso2apache-axiswebservice-client

Can I set properties to the MessageContext before invoke the stub in Axis 2 Java


I'm using AXIS 2 to call WS methods using a stub called ChannelConnectServiceStub.

Generating stub and the ConfigurationContext :

public class TestWSClient {

    private void init() throws Exception {

        String                  proxyUrl                    = "http://subdom.dom.com/testpath/TestConnect.asmx";
        ConfigurationContext    ctx                         = ConfigurationContextFactory.createConfigurationContextFromFileSystem("/rootFolder/Axis2/axis2-1.4.1/repository", "/rootFolder/Axis2/axis2-1.4.1/conf/axis2.xml");
        ChannelConnectServiceStub channelConnectServiceStub = new ChannelConnectServiceStub(ctx,proxyUrl);

        ctx.setProperty("testid", "testidval"); // Approach 1
        channelConnectServiceStub._getServiceClient().getServiceContext().setProperty("testid", "testidval"); // Approach 2

    }
}

And I'm using a LogHandler to log the Message requests and responses.

LogHandler :

class LogHandler extends AbstractHandler implements Handler {

    @Override
    public InvocationResponse invoke(MessageContext messageContext) throws AxisFault {

        String testID       = null;
        String invokeStr    = null;
        String axisService  = null;
        String action       = null;

        invokeStr       = messageContext.getEnvelope().toString();
        axisService     = messageContext.getAxisService().getName();
        action          = messageContext.getAxisMessage().getAxisOperation().getInputAction();

        testID = (String) messageContext.getProperty("testid");// Approach 1
        testID = (String) messageContext.getServiceContext().getProperty("testid");// Approach 2

        return InvocationResponse.CONTINUE;
    }

}

I want to pass a property ("testid") from the point that I creating and calling the stub to the LogHandler class. I have mentioned two approaches that I've taken.

Both are passing the value. But the problem is, there are multiple client threads using the same TestWSClient to use the service. So, different values that are setting by different clients are getting interchange when it came to the LogHandler. (But invokeStr, AxisService and action don't have this issue).

  1. Is there any way to pass properties to the MessageContext before the stub is invoked?
  2. Can anybody help to get a property from stub to the LogHandler without interchanging the values in multi-threaded environment.

I tried below one also but failed since operationContext is NULL.

OperationContext operationContext = stub._getServiceClient().getLastOperationContext();
logger.info("operationContext : " + operationContext);

if (operationContext != null) {

    MessageContext outMessageContext = operationContext.getMessageContext("Out");

    if (outMessageContext != null) {
        logger.info("outMessageContext.getEnvelope().toString() : " + outMessageContext.getEnvelope().toString());
        outMessageContext.setProperty("Portal", getPortal());
    }

    MessageContext inMessageContext = operationContext.getMessageContext("In");
    logger.info("inMessageContext : " + inMessageContext);

    if (inMessageContext != null) {
        logger.info("inMessageContext.getEnvelope().toString() : " + inMessageContext.getEnvelope().toString());
        inMessageContext.setProperty("Portal", getPortal());
    }

}

Solution

  • Make sure to get singleton instance of ConfigurationContext.

    when you do setProperty and getProperty from ServiceContext note that you are obtaining a shared copy of Property object per jvm, so instead of "testid" key, use a unique key,

    ex: In client side code after stub initialization instead of,

    channelConnectServiceStub._getServiceClient().getServiceContext()
      .setProperty("testid","testidval");
    

    try

    channelConnectServiceStub._getServiceClient().getServiceContext()
     .setProperty(stub._getServiceClient().getServiceContext().getName(), "testidval");
    

    and to retrieve the property, in loghandler use the same key (the msgContext.getServiceContext().getName() is unique per flow)

    Instead of

    messageContext.getServiceContext().getProperty("testid");

    try

    messageContext.getServiceContext()
     .getProperty(msgContext.getServiceContext().getName());
    

    also note as you are storing values on a jvm shared Property object, to avoid memory growth remove the value once its no longer needed.

    messageContext.getServiceContext()
     .removeProperty(msgContext.getServiceContext().getName();