title: WSSecurityEngine says password was not supplied during callback even though it is provided
body: <p>I'm in the process of creating a client for a web service. I keep getting the following error:</p>
  
  <pre><code>AxisFault
      faultCode: {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}InvalidSecurity
      faultSubcode:
      faultString:
          Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant)
      faultActor: 
      faultNode: 
      faultDetail: {http://xml.apache.org/axis/}
      stackTrace:
          Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant)
  </code></pre>
  
  <p>This is my environment here:</p>
  
  <ul>
  <li>Intellij IDEA IDE</li>
  <li>Apache Axis</li>
  <li>Apache WSS4J 1.5.1</li>
  <li>Apache XML Security 1.4.0</li>
  <li>JDK 1.6</li>
  <li>Max OS X</li>
  </ul>
  
  <p>Although searching on the internet provides a lot of examples of how the security header can be added to the request via XML configuration, my requirement is to do this dynamically via the program. So here is my code:</p>
  
  <pre><code>public class AxisClient implements CallbackHandler {
  
      ServerEnvironment environment;
  
      AxisClient(ServerEnvironment environment) {
          this.environment = environment;
      }
  
      public enum ServerEnvironment {
          LIVE("https://ics2ws.ic3.com/commerce/1.x/transactionProcessor"),
          TEST("https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor");
  
          String url;
  
          ServerEnvironment (String url) {
              this.url = url;
          }
  
          public String getUrl() {
              return url;
          }
      }
  
      public enum Merchant {
          TestMerchant ("testpassword");
  
          private String transactionKey;
  
          Merchant(String transactionKey) {
              this.transactionKey = transactionKey;
          }
  
          public String getTransactionKey() {
              return transactionKey;
          }
      }
  
      public static void main(String[] argv) {
          String ani = "7162502800";
          String zipCode = "14221";
          String ccNum ="5555555555554444";
          String expMonth = "01";
          String expYear = "15";
          String cvv = "123";
          String unitPrice = "9.99";
          String qty = "2";
  
          try {
              new AxisClient(ServerEnvironment.TEST).doAuth(Merchant.TestMerchant, ani, zipCode, ccNum, expMonth, expYear, cvv, String.valueOf(new Date().getTime()), unitPrice, qty);
          }
          catch (Exception e) {
              e.printStackTrace();
          }
      }
  
      public Boolean doAuth(Merchant merchant, String ani, String zipCode, String ccNum, String expMonth, String expYear, String cvv, String id, String unitPrice, String qty) throws Exception {
          Boolean result = false;
  
          RequestMessage request;
          BillTo billTo;
          Card card;
          PurchaseTotals purchaseTotals;
          Item item;
          Item[] items;
          ReplyMessage reply;
  
          try {
              // billing info
              billTo = new BillTo();
              billTo.setPhoneNumber(ani);
              billTo.setPostalCode(zipCode);
  
              // card info
              card = new Card();
              card.setAccountNumber(ccNum);
              card.setExpirationMonth(new BigInteger(expMonth));
              card.setExpirationYear(new BigInteger(expYear));
              card.setCvNumber(cvv);
  
              // currency info
              purchaseTotals = new PurchaseTotals();
              purchaseTotals.setCurrency("USD");
  
              // item
              item = new Item();
              item.setId(new BigInteger(id));
              item.setUnitPrice(unitPrice);
              item.setQuantity(new BigInteger(qty));
  
              // add item to items array
              items = new Item[1];
              items[0] = item;
  
              // create our request
              request = new RequestMessage();
              request.setMerchantID(merchant.toString());
              request.setCcAuthService(new CCAuthService());
              request.getCcAuthService().setRun("true");
  
              // add request specific params
              request.setBillTo(billTo);
              request.setCard(card);
              request.setPurchaseTotals(purchaseTotals);
              request.setItem(items);
  
              reply = post(merchant, request);
  
              if (reply != null) {
                  System.out.println(ReflectionToStringBuilder.toString(reply, ToStringStyle.MULTI_LINE_STYLE));
              }
          }
          catch (Exception e) {
              throw e;
          }
  
          return result;
      }
  
      public EngineConfiguration createConfigurationWithSecurityHeaders(Merchant merchant) throws Exception {
          SimpleProvider result;
  
          Handler securityHandler;
          SimpleChain requestHandler;
          SimpleChain responseHandler;
          Handler pivot;
          Handler transport;
  
          try {
              result = new SimpleProvider();
  
              securityHandler = new WSDoAllSender();
              securityHandler.setOption(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
              securityHandler.setOption(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
              securityHandler.setOption(WSHandlerConstants.PW_CALLBACK_REF, this);
              securityHandler.setOption(WSHandlerConstants.USER, merchant.toString());
              securityHandler.setOption(WSHandlerConstants.MUST_UNDERSTAND, "false");
  
              requestHandler = new SimpleChain();
              requestHandler.addHandler(securityHandler);
  
              responseHandler = new SimpleChain();
              responseHandler.addHandler(securityHandler);
  
              pivot = new HTTPSender();
  
              transport = new SimpleTargetedChain(requestHandler, pivot, responseHandler);
  
              result.deployTransport(HTTPTransport.DEFAULT_TRANSPORT_NAME, transport);
          }
          catch (Exception e) {
              throw e;
          }
  
          return result;
      }
  
      public ReplyMessage post (Merchant merchant, RequestMessage request) throws Exception {
          ReplyMessage result;
  
          TransactionProcessorLocator locator;
          URL endPoint;
          ITransactionProcessorStub stub;
          EngineConfiguration configuration;
  
          try {
              locator = new TransactionProcessorLocator();
  
              // use client config
              configuration = createConfigurationWithSecurityHeaders(merchant);
              locator.setEngineConfiguration(configuration);
              locator.setEngine(new org.apache.axis.client.AxisClient(configuration));
  
              endPoint = new URL(environment.getUrl());
  
              stub = (ITransactionProcessorStub) locator.getportXML(endPoint);
              stub._setProperty(WSHandlerConstants.USER, request.getMerchantID());
              stub._setProperty(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
              stub._setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
              stub._setProperty(WSHandlerConstants.PW_CALLBACK_REF, this);
              stub._setProperty(WSHandlerConstants.MUST_UNDERSTAND, "false");
  
              result = stub.runTransaction(request);
          }
          catch (Exception e) {
              throw e;
          }
  
          return result;
      }
  
      @Override
      public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
  
          for (Callback callback : callbacks) {
  
              System.out.println(ReflectionToStringBuilder.toString(callback, ToStringStyle.MULTI_LINE_STYLE));
  
              if (callback instanceof WSPasswordCallback) {
  
                  WSPasswordCallback passwordCallback = (WSPasswordCallback) callback;
  
                  switch (Merchant.valueOf(passwordCallback.getIdentifer())) {
  
                      case TestMerchant:
                          passwordCallback.setPassword(Merchant.TestMerchant.getTransactionKey());
                          System.out.println(ReflectionToStringBuilder.toString(passwordCallback, ToStringStyle.MULTI_LINE_STYLE));
                          break;
  
                      default:
                          throw new UnsupportedCallbackException(callback, "Unrecognized prompt!");
                  }
              }
              else {
                  throw new UnsupportedCallbackException(callback, "Unrecognized callback!");
              }
          }
      }
  }
  </code></pre>
  
  <p>As you can see from the above, my class implements CallbackHandler and I'm overriding handle() which provides the password for WSPasswordCallback.</p>
  
  <p>Here is the output of the print statement for when I get the callback first:</p>
  
  <pre><code>org.apache.ws.security.WSPasswordCallback@50c713d2[
    identifier=TestMerchant
    password=&lt;null&gt;
    key=&lt;null&gt;
    usage=2
    passwordType=&lt;null&gt;
  ]
  </code></pre>
  
  <p>Here is the output for after setting the password:</p>
  
  <pre><code>org.apache.ws.security.WSPasswordCallback@50c713d2[
    identifier=TestMerchant
    password=testpassword
    key=&lt;null&gt;
    usage=2
    passwordType=&lt;null&gt;
  ]
  </code></pre>
  
  <p>So I'm not really sure why I keep getting that error message. Any help in solving this issue will be greatly appreciated.</p>
  
  <p>Also recommendations for a different approach (axis2, cxf) are welcome.</p>
  
  <p>Here is my full stack trace if it is of any help:</p>
  
  <pre><code>AxisFault
   faultCode: {http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}InvalidSecurity
   faultSubcode: 
   faultString: 
  Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant)
  General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant)
  
   faultActor: 
   faultNode: 
   faultDetail: 
      {http://xml.apache.org/axis/}stackTrace:
  Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant)
  General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant)
  
      at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222)
      at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129)
      at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087)
      at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601)
      at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
      at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2939)
      at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
      at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
      at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
      at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
      at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
      at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
      at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
      at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
      at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
      at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227)
      at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696)
      at org.apache.axis.Message.getSOAPEnvelope(Message.java:435)
      at org.apache.axis.handlers.soap.MustUnderstandChecker.invoke(MustUnderstandChecker.java:62)
      at org.apache.axis.client.AxisClient.invoke(AxisClient.java:206)
      at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
      at org.apache.axis.client.Call.invoke(Call.java:2767)
      at org.apache.axis.client.Call.invoke(Call.java:2443)
      at org.apache.axis.client.Call.invoke(Call.java:2366)
      at org.apache.axis.client.Call.invoke(Call.java:1812)
      at itg.cybersource.axis.ITransactionProcessorStub.runTransaction(ITransactionProcessorStub.java:1284)
      at itg.AxisClient.post(AxisClient.java:208)
      at itg.AxisClient.doAuth(AxisClient.java:132)
      at itg.AxisClient.main(AxisClient.java:75)
  
      {http://xml.apache.org/axis/}hostname:C02GD302DRJL.local
  
  
  Security Data : General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant)
  General security error (WSSecurityEngine: Callback supplied no password for: TestMerchant)
  
      at org.apache.axis.message.SOAPFaultBuilder.createFault(SOAPFaultBuilder.java:222)
      at org.apache.axis.message.SOAPFaultBuilder.endElement(SOAPFaultBuilder.java:129)
      at org.apache.axis.encoding.DeserializationContext.endElement(DeserializationContext.java:1087)
      at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601)
      at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
      at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2939)
      at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
      at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
      at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
      at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
      at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
      at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
      at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
      at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
      at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
      at org.apache.axis.encoding.DeserializationContext.parse(DeserializationContext.java:227)
      at org.apache.axis.SOAPPart.getAsSOAPEnvelope(SOAPPart.java:696)
      at org.apache.axis.Message.getSOAPEnvelope(Message.java:435)
      at org.apache.axis.handlers.soap.MustUnderstandChecker.invoke(MustUnderstandChecker.java:62)
      at org.apache.axis.client.AxisClient.invoke(AxisClient.java:206)
      at org.apache.axis.client.Call.invokeEngine(Call.java:2784)
      at org.apache.axis.client.Call.invoke(Call.java:2767)
      at org.apache.axis.client.Call.invoke(Call.java:2443)
      at org.apache.axis.client.Call.invoke(Call.java:2366)
      at org.apache.axis.client.Call.invoke(Call.java:1812)
      at itg.cybersource.axis.ITransactionProcessorStub.runTransaction(ITransactionProcessorStub.java:1284)
      at itg.AxisClient.post(AxisClient.java:208)
      at itg.AxisClient.doAuth(AxisClient.java:132)
      at itg.AxisClient.main(AxisClient.java:75)
  </code></pre>