Hi Kostis,

Thank you so much for your time.

I'm using axis2-1.4.1. I took the subrevision 940897 of axis2 and I
found the following changes that looked interesting:

description.OutInAxisOperation.handleResponse:
    335: 

        // rampart handlers change the envelope and set the decrypted envelope
        // so need to check the new one else resenvelope.hasFault() become 
false.
        resenvelope = responseMessageContext.getEnvelope();

            

engine.AxisEngine.checkMustUnderstand
    67: 

        if (clientHandlerUnderstandsHeader(headerBlock, msgContext)) {
            continue;
        }


+ the comment lines that you said: 
    661:

    /**
     * Answer if an application handler (such as a JAXWS application handler) 
has registered that 
     * it understands this header. Note that the handlers do this registration 
only on the 
     * service-requester side.  That is because on the service-provider side 
the handlers have
     * not been instantiated at this point so can not be queried yet. 
     * @param headerBlock Contains the SOAP header to check
     * @param messageContext Contains the inbound message context
     * @return true if this header QName is registered as being understood or 
false otherwise.
     */
    private static boolean clientHandlerUnderstandsHeader(SOAPHeaderBlock 
headerBlock, 
            MessageContext messageContext) {
        boolean headerUnderstood = false;
        // Get the property off the outbound context, if it exists and contains 
this header
        // then it is understood
        QName headerQName = headerBlock.getQName();
        Set understoodHeaders = getUnderstoodClientHeaders(messageContext);
        if (understoodHeaders != null && understoodHeaders.size() > 0) {
            headerUnderstood = understoodHeaders.contains(headerQName);
        }
        return headerUnderstood;
    }
    
    /**
     * Get the collection of Header QNames that are registered as being 
understood.
     * This assumes that a Set of QNames which indicates what headers are 
"understood" by
     * this particular client through the client's programming model (i.e. 
application
     * handlers) has been defined and stored on the outbound MessageContext 
under the
     * client.UnderstoodHeaders property. 
     * @param msgContext The inbound message context
     * @return a Set of Header QNames that have been registered as understood, 
or null if
     * none have been registered.
     */
    private static Set getUnderstoodClientHeaders(MessageContext msgContext) {
        Set returnQN = null;
        // The client sets the property on the JAX-WS Request Message Context, 
which will be copied
        // to the Axis2 outbound message context.
        OperationContext opCtx = msgContext.getOperationContext();
        MessageContext outboundMC = null;
        try {
            outboundMC = 
opCtx.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
        }
        catch (AxisFault af) {
            // Ignore this; it means that there wasn't an outbound message for 
this operation.
        }
        if (outboundMC != null) {
            returnQN = 
                (Set) outboundMC.getProperty("client.UnderstoodHeaders");
        }
        return returnQN;
    }


I modified AxisEngine.java and OutInAxisOperation with these changes and
I removed my "invoke" method, but .. unfortunately this didn't helped
because, from getUnderstoodClientHeaders.AxisEngine:

(Set) outboundMC.getProperty("client.UnderstoodHeaders") equals null



Here is my request header (outboundMC envelope):


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/";>
  <soapenv:Header>
    <eb:MessageHeader xmlns:eb="http://www.ebxml.org/namespaces/messageHeader"; 
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"; 
SOAP-ENV:mustUnderstand="1" eb:version="2.0">
      <eb:ConversationId>[email protected]:1010</eb:ConversationId>
      <eb:From>
        <eb:PartyId type="urn:x12.org:IO5:01">100.100.100.100:1010</eb:PartyId>
      </eb:From>
      <eb:To>
        <eb:PartyId type="urn:x12.org:IO5:01">test.webservices.com</eb:PartyId>
      </eb:To>
      <eb:CPAId>TEST</eb:CPAId>
      <eb:Service eb:type="testXML">Session</eb:Service>
      <eb:Action>SessionCreateRQ</eb:Action>
      <eb:MessageData>
        <eb:MessageId>[email protected]:1010</eb:MessageId>
        <eb:Timestamp>2010-12-08T16:37:55Z</eb:Timestamp>
      </eb:MessageData>
    </eb:MessageHeader>
    <wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext"; 
soapenv:mustUnderstand="0">
      <wsse:UsernameToken>
        <wsse:Username>userTest</wsse:Username>
        <wsse:Password>passwdTest</wsse:Password>
        <Organization>orgTest</Organization>
        <Domain>defaultTest</Domain>
      </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>
        ...
</soapenv:Envelope>


The interesting part is the message is send properly and I receive the
response with no problems, but when is checked for the mustUndestand
from request.. bum! error!
Maybe you have some ideas, because I'm out of them.. if not, at least I
give it a try :)

Thanks again and have a wonderful day.
Adela



On Tue, 2010-12-07 at 16:25 +0200, Kostis Anagnostopoulos wrote: 

> Hi Adela,
> 
> The problem was due to the behavior of axis-1.4's
> org.apache.axis2.description.OutInAxisOperation class.
> 
> In particular, at method:
>   handleResponse(MessageContext): line ~355
> the soap-envelop were not updated after having invoked the
> AxisEngine.receive(responseMessageContext),
> and instead the previous envelop was reused, as it had been fetched
> from the last invocation to:
>   responseMessageContext.getEnvelope().
> 
> But it is within the AxisEngine.receive() invocation that the
> overriden-handler substitutes the IN-msg.
> 
> To fix it, i had to copy the respective code from trunk 1.5, rev 940897
> (there you can find the comment of axis2 developers complaining about
> the same issue),
> and depend against a patched axis2-kernel-1.4.jar.
> 
> I tried explained all this in a follow-up message:
>   http://www.mail-archive.com/[email protected]/msg00627.html
> but got no reply from the devs.
> 
> Check the axis2 version you are using.
> 
> 
> Now, i paste my code below, which performs siebel session-id authentication,
> see 
> http://download.oracle.com/docs/cd/E14004_01/books/SSDev/SSDev_Architecture13.html
> with the following notes:
> * Code does not compile, just erased my specific parts and copy-pasted here,
> * it performs various checks on the exchange-messages to decide
> whether to engage its functionality,
> and maybe i should have replaced some of them with configurations on
> the axis2.conf file, but i did not know how to do it,
> * one of those checks is to keep a retransmission-count as properties
> on operation-context, to avoid infinite re-transmissions,
> * the SiebelAuthManager class is my utility class for adding the extra
> headers, and housekeeping the session-ids
> * while its most tricky method
> SiebelAuthManager.transferMsgContextFromTo() is also included below,
> * the code is complicated since i coded it as i discovered problems, i
> would be happy if you simplify it and re-submit it here.
> 
> 
> /*
> This program is free software; you can redistribute it and/or modify
>    it under the terms of the GNU General Public License as published by
>    the Free Software Foundation; version 2 of the License.
> 
>    This program is distributed in the hope that it will be useful,
>    but WITHOUT ANY WARRANTY; without even the implied warranty of
>    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>    GNU General Public License for more details.
> */
> public class SiebelAuthHandler extends AbstractHandler {
> 
>     final Logger logger = LoggerFactory.getLogger(this.getClass());
> 
>     public InvocationResponse invoke(final MessageContext msgc) throws
> AxisFault {
>         try {
>             // Phase-dispatch and configuration check.
>             //
>             final int flow = msgc.getFLOW();
>             if (flow == MessageContext.OUT_FLOW)
>                 return invokeOut(msgc);
>             //// NO, OUT-FAULT is used only on ws-servers.
>             //else if (flow == MessageContext.OUT_FAULT_FLOW)
>             //    return invokeOutFault(msgc);
>             else if (flow == MessageContext.IN_FAULT_FLOW)
>                 return invokeInFault(msgc);
>             else if (flow == MessageContext.IN_FLOW)
>                 return invokeIn(msgc);
>             else
>                 logger.warn(
>                         "{} Configuration Error: The Siebel handler
> installed in illegal flow({})\n  Expected one of OUT, IN_FAULT, IN.",
>                         msgc.getLogIDString(), new Integer(flow));
>         } catch(final RuntimeException ex) {
>             logger.error( "{} Unexpected error on Siebel handler: {}",
>                     new Object[] {msgc.getLogIDString(), ex.getMessage(), 
> ex});
>             throw ex;
>         } catch(final AxisFault ex) {
>             logger.info( "{} Normal axis-fault on Siebel handler: {}",
>                     msgc.getLogIDString(), ex.getMessage());
>             // No logging, application client-code will feel it!
>             throw ex;
>         }
> 
>         return InvocationResponse.CONTINUE;
>     }
> 
>     private SiebelAuthManager getSiebelAuthMan(final MessageContext omsgc) {
>         final SiebelAuthManager authman =
> 
> SiebelAuthManager.getSiebelAuthManager(omsgc.getConfigurationContext());
>         return authman;
>     }
> 
>     private boolean isSiebelWs(final SiebelAuthManager authman, final
> String remoteAddr, final MessageContext msgc, final String msgBody) {
>         logger.debug("{} {} ws-URL: \n  {}", new Object[]
> {msgc.getLogIDString(), msgBody, remoteAddr});
>         return authman.isSiebelWs(msgc, remoteAddr);
>     }
> 
>     public InvocationResponse invokeOut(final MessageContext omsgc) {
>         final SiebelAuthManager authman = getSiebelAuthMan(omsgc);
> 
>         // Engage only for Siebel WS urls
>         //
>         if (!isSiebelWs(authman, omsgc.getTo().getAddress(), omsgc,
> "OUT-msg detected to"))
>             return InvocationResponse.CONTINUE;
> 
>         final OperationContext opc = omsgc.getOperationContext();
> 
>         // Limit to max-retransmissions.
>         //
>         // Actually should never reach this point,
>         // the fault-in handler must have stopped it earlier.
>         //
>         // The limit is +1 for display purposes.
>         //
>         final int retrans = authman.getSessionRetransmissions(opc);
>         final int maxRetrans = authman.maxSessionRetransmissions;
>         if (retrans > maxRetrans) {
>             if (maxRetrans >= 0)
>                 logger.warn("{} Maximum({}) number of Siebel
> retransmissions({}) exceeded, but IN_FAULT handler should had stoped
> earlier! \n"
>                         + "  Ignoring msg, and sending it  without
> Siebel headers",
>                         new Object[] {
>                                 omsgc.getLogIDString(),
>                                 new Integer(maxRetrans),
>                                 new Integer(retrans)
>                         });
>             else
>                 logger.info("{} The Siebel is disabled by a negative {}. \n"
>                         + "  Ignoring msg, and sending it without
> Siebel headers",
>                         omsgc.getLogIDString(),
> SiebelAuthManager.PKEY_MAX_RETRANSMISSIONS);
> 
>             return InvocationResponse.CONTINUE;
>         }
> 
>         // On *exact* retrans-limit, add explicitly user/pswd headers
> (no session-id).
>         //
>         final boolean isLastRetrans = retrans == maxRetrans;
>         final Boolean isSidAdded = authman.addAuthHeaders(omsgc, 
> isLastRetrans);
> 
>         if (isSidAdded != null)
>             logger.info("{} Inserted Siebel headers for {} to OUT-msg
> with retransmissions-count({}){}.",
>                     new Object[] {
>                             omsgc.getLogIDString(),
>                             isSidAdded.booleanValue()? "SESSION-ID":
> "USER/PSWD",
>                             new Integer(retrans),
>                             isLastRetrans? ", last attempt":""
>             });
>         else
>             logger.info("{} No Siebel headers inserted to OUT-msg with
> retransmissions-count({}){}.",
>                     new Object[] {
>                             omsgc.getLogIDString(),
>                             new Integer(retrans),
>                             isLastRetrans? ", last attempt":""
>             });
> 
>         return InvocationResponse.CONTINUE;
>     }
> 
>     public InvocationResponse invokeInFault(final MessageContext
> imsgc) throws AxisFault {
>         final SiebelAuthManager authman = getSiebelAuthMan(imsgc);
> 
>         // Engage only for siebel-auth-denied soap-faults.
>         //
>         if (!isSiebelWs(authman, imsgc.getTo().getAddress(), imsgc,
> "IN-FAULT detected from"))
>             return InvocationResponse.CONTINUE;
>         if (!authman.isSiebelAuthDeniedFault(imsgc))
>             return InvocationResponse.CONTINUE;
> 
>         final OperationContext opc = imsgc.getOperationContext();
>         final MessageContext omsgc =
> opc.getMessageContext(WSDL2Constants.MESSAGE_LABEL_OUT);
> 
>         // Limit to max-retransmissions.
>         //
>         // The limit is +1 for display purposes.
>         //
>         final int maxRetrans = authman.maxSessionRetransmissions;
>         final int retrans = authman.getSessionRetransmissions(opc);
>         if (retrans > maxRetrans) {
>             logger.error(
>                     "{} Maximum({}) number of Siebel
> retransmissions-count({}) exceeded! \n  Throwing original fault to
> user-code.",
>                     new Object[] {imsgc.getLogIDString(), new
> Integer(maxRetrans), new Integer(retrans)});
>             return InvocationResponse.CONTINUE;
>         }
> 
>         final int newRetrans = retrans + 1;
>         logger.debug("{} Re-transmitting original OUT-msg to siebel
> with retransmissions-count({}).",
>                 imsgc.getLogIDString(), new Integer(newRetrans));
> 
>         // Reset original OUT message and
>         // (others currently might not use it).
>         //
>         omsgc.setCurrentHandlerIndex(0);
>         omsgc.setCurrentPhaseIndex(0);
> 
>         // Retransmit original OUT message synchronously, and
>         // mark retransmissions count on new operation-context.
>         //
>         final OperationClient oc =
> opc.getAxisOperation().createClient(opc.getServiceContext(),
> imsgc.getOptions());
>         final OperationContext nopc = oc.getOperationContext();
>         authman.markSessionRetransmissions(nopc, newRetrans);
>         oc.addMessageContext(omsgc.extractCopyMessageContext()); //???
>         //oc.addMessageContext(omsgc);
>         oc.execute(true);
> 
>         logger.debug("{} Received response for re-transmitted
> auth-failed soap-msg",
>                 imsgc.getLogIDString(), new Integer(newRetrans));
> 
>         // Copy soap-env into current IN msg and re-run handler-chain.
>         //
>         final MessageContext newimsgc =
> oc.getMessageContext(WSDL2Constants.MESSAGE_LABEL_IN);
>         authman.transferMsgContextFromTo(newimsgc, imsgc);
>         logger.info("{} Replaced original Siebel-fault with
> retrans-count({}), with soap-{} with retrans-count({}).",
>                 new Object[] {
>                         imsgc.getLogIDString(),
>                         new Integer(retrans),
>                         newimsgc.isFault()? "fault": "reponse",
>                         new Integer(newRetrans)});
> 
>         // Reset IN message to start handler-chain all over.
>         //
>         imsgc.setCurrentHandlerIndex(0);
>         imsgc.setCurrentPhaseIndex(0);
> 
>         return InvocationResponse.CONTINUE;
>     }
> 
>     public InvocationResponse invokeIn(final MessageContext imsgc) {
>         final SiebelAuthManager authman = getSiebelAuthMan(imsgc);
> 
>         // Engage only for Siebel WS urls.
>         //
>         if (!isSiebelWs(authman, imsgc.getTo().getAddress(), imsgc,
> "IN-msg detected from"))
>             return InvocationResponse.CONTINUE;
> 
>         final boolean isReclaimed = authman.reclaimSessionId(imsgc, false);
>         if (isReclaimed)
>             logger.info("{} Reclaimed Siebel session-id from IN-msg.",
> imsgc.getLogIDString());
> 
>         return InvocationResponse.CONTINUE;
>     }
> 
>     public void flowComplete(final MessageContext omsgc) {
>         // Reclaim session-id only on client-errors.
>         //
>         if (omsgc.getFailureReason() != null) {
>             final SiebelAuthManager authman = getSiebelAuthMan(omsgc);
> 
>             // Engage only for Siebel WS urls.
>             //
>             if (!isSiebelWs(authman, omsgc.getTo().getAddress(),
> omsgc, "OUT(?)-error-msg detected from"))
>                 return;
> 
>             final boolean isReclaimed = authman.reclaimSessionId(omsgc, true);
> 
>             if (isReclaimed)
>                 logger.info("{} Reclaimed Siebel session-id on
> flow-phase({}) (should be OUT-msg(2)...).",
>                         omsgc.getLogIDString(), new Integer(omsgc.getFLOW()));
>         }
>     }
> 
> }
> 
> 
> SiebelAuthManager.transferMsgContextFromTo() method:
> -------------------------------------------------
>     /**
>      * Transfers whatever it cans from the 'from' msg to the 'to',
>      * including its envelope and attachments.
>      * <p>
>      * Copied from MessageContext.extractCopyMessageContext().
>      * @throws AxisFault
>      */
>     void transferMsgContextFromTo(final MessageContext from, final
> MessageContext to) throws AxisFault {
>         //---------------------------------------------------------
>         // various simple fields
>         //---------------------------------------------------------
> 
>         //to.setFLOW(FLOW);
> 
>         // kana: Prevents "The MessageContext does not have an
> associated SOAPFault" IAE.
>         to.setProcessingFault(from.isProcessingFault());
>         to.setFailureReason(from.getFailureReason()); // Added by kana.
>         to.setPaused(from.isPaused());
>         to.setOutputWritten(from.isOutputWritten());
>         to.setNewThreadRequired(from.isNewThreadRequired());
>         to.setDoingREST(from.isDoingREST());
>         to.setDoingMTOM(from.isDoingMTOM());
>         to.setDoingSwA(from.isDoingSwA());
>         to.setResponseWritten(from.isResponseWritten());
>         to.setServerSide(from.isServerSide());
> 
>         to.setLastTouchedTime(from.getLastTouchedTime());
> 
>         //---------------------------------------------------------
>         // message
>         //---------------------------------------------------------
>         // NOTE: kana: In order to replace the soap-env on axis2-1.4.1,
>         // a patched
> org.apache.axis2.description.OutInAxisOperationClient is required!
>         // See my post on axis2 user-list:
>         // 
> http://markmail.org/search/list:org.apache.ws.axis-user#query:list%3Aorg.apache.ws.axis-user+page:1+mid:e6hf5mun7kuhrlsb+state:results
>         to.setEnvelope(from.getEnvelope());
>         to.setAttachmentMap(from.getAttachmentMap());
>         to.setIsSOAP11Explicit(from.isSOAP11());
> 
>         //---------------------------------------------------------
>         // ArrayList executionChain
>         //     handler and phase related data
>         //---------------------------------------------------------
>         //to.setExecutionChain(executionChain);
> 
>         // the setting of the execution chain is actually a reset
>         // so copy the indices after putting in the execution chain
>         //to.setCurrentHandlerIndex(currentHandlerIndex);
>         //to.setCurrentPhaseIndex(currentPhaseIndex);
> 
>         //---------------------------------------------------------
>         // LinkedList executedPhases
>         //---------------------------------------------------------
>         //to.setExecutedPhasesExplicit(executedPhases);
> 
>         //---------------------------------------------------------
>         // options
>         //---------------------------------------------------------
>         //to.setOptionsExplicit(options);
> 
>         //---------------------------------------------------------
>         // axis operation
>         //---------------------------------------------------------
>         //to.setAxisOperation(null);
> 
>         //---------------------------------------------------------
>         // operation context
>         //---------------------------------------------------------
>         //to.setOperationContext(null);
> 
>         //---------------------------------------------------------
>         // axis service
>         //---------------------------------------------------------
>         //to.setAxisService(null);
> 
>         //-------------------------
>         // serviceContextID string
>         //-------------------------
>         to.setServiceContextID(to.getServiceContextID() + "<--" +
> from.getServiceContextID());
> 
>         //-------------------------
>         // serviceContext
>         //-------------------------
>         //to.setServiceContext(null);
> 
>         //---------------------------------------------------------
>         // serviceGroup
>         //---------------------------------------------------------
>         //to.setServiceGroupContext(null);
> 
>         //-----------------------------
>         // serviceGroupContextId string
>         //-----------------------------
>         //to.setServiceGroupContextId(serviceGroupContextId);
> 
>         //---------------------------------------------------------
>         // axis message
>         //---------------------------------------------------------
>         //to.setAxisMessage(axisMessage); // kana: is this necessary  ???????
> 
>         //---------------------------------------------------------
>         // configuration context
>         //---------------------------------------------------------
>         //to.setConfigurationContext(configurationContext);
> 
>         //---------------------------------------------------------
>         // session context
>         //---------------------------------------------------------
>         //to.setSessionContext(sessionContext);
> 
>         //---------------------------------------------------------
>         // transport
>         //---------------------------------------------------------
> 
>         //------------------------------
>         // incomingTransportName string
>         //------------------------------
>         //to.setIncomingTransportName(incomingTransportName);
> 
>         //to.setTransportIn(transportIn);
>         //to.setTransportOut(transportOut);
> 
>         //---------------------------------------------------------
>         // properties
>         //---------------------------------------------------------
>         // Only set the local properties (i.e. don't use getProperties())
>         //to.setProperties(properties);
> 
>         //---------------------------------------------------------
>         // special data
>         //---------------------------------------------------------
> 
>         //to.setSelfManagedDataMapExplicit(selfManagedDataMap);
> 
>         //---------------------------------------------------------
>         // done
>         //---------------------------------------------------------
>     }
> 
> Kostis
> 
> 
> On Tue, Dec 7, 2010 at 2:17 PM, Adela Ciobra <[email protected]> wrote:
> > Hi Kostis,
> >
> > I have the same issue like you had with re-transmitting the soap message
> > if you redefine the invoke method, did you found some solution? If 'yes'
> > hope you will be kind with me and share it :)
> >
> > Thanks in advance,
> > Adela
> >
> >

Reply via email to