private SOAPMessage actionToSoap(RpcInvokeAction action) throws Exception {
    useFirstElementPrefix = true;

    SOAPMessage message = messageFactory.createMessage();
    actionData =
        WsRpcActionUtil.getWsRpcActionData(((SimpleRpcInvokeAction) action).getProperties());

    SOAPEnvelope env = message.getSOAPPart().getEnvelope();
    env.addNamespaceDeclaration(ACTION_PREFIX, actionData.getMethodInputNameSpace());

    setFields(action.getFields(), env.getBody());

    if (actionData.getSoapAction().length() > 0) {
      message.getMimeHeaders().addHeader("SOAPAction", actionData.getSoapAction());
    }

    // Base auth headers from http://www.whitemesa.com/soapauth.html#S322
    /*
     * all auth standarts: http://www.soapui.org/testing-dojo/best-practices/authentication.html
     */
    if (props.getPassword() != null
        && props.getUserName() != null
        && !props.getUserName().trim().equals("")) {
      SOAPHeaderElement auth =
          message
              .getSOAPHeader()
              .addHeaderElement(
                  new QName("http://soap-authentication.org/basic/2001/10/", "BasicAuth", "h"));
      auth.setMustUnderstand(true);
      auth.addChildElement("Name").setValue(props.getUserName());
      auth.addChildElement("Password").setValue(props.getPassword());
    }

    logMessage("Request message:", message);

    return message;
  }
  private void setFields(List<RpcField> fields, SOAPElement actionElement) throws SOAPException {
    boolean elementFormDefault = actionData.getElementFormDefaultUse().equals("true");

    for (RpcField field : fields) {
      if (field.getDirection() == Direction.OUTPUT) {
        continue;
      }

      if (field.getName().equals(WsRpcActionUtil.FORCED_CHILD)) {
        continue;
      }

      SOAPElement element;
      switch (getFieldType(field)) {
        case simple:
          RpcFlatField flatField = (RpcFlatField) field;
          element =
              elementFormDefault
                  ? actionElement.addChildElement(flatField.getOriginalName(), ACTION_PREFIX)
                  : actionElement.addChildElement(flatField.getOriginalName());
          FieldUtil.writePrimitiveField((RpcFlatField) field, element);
          break;
        case structure:
          SimpleRpcStructureField structureField = (SimpleRpcStructureField) field;
          String soapElement = structureField.getOriginalName();

          element =
              (elementFormDefault || useFirstElementPrefix)
                  ? actionElement.addChildElement(soapElement, ACTION_PREFIX)
                  : actionElement.addChildElement(soapElement);
          useFirstElementPrefix = false;
          if (structureField.getExpandedElements() != null) {
            for (String expected : structureField.getExpandedElements()) {
              element =
                  elementFormDefault
                      ? element.addChildElement(expected, ACTION_PREFIX)
                      : element.addChildElement(expected);
            }
          }
          setFields(structureField.getChildrens(), element);
          break;
        case list:
          SimpleRpcStructureListField listField = (SimpleRpcStructureListField) field;
          if (listField.getOriginalName() != null) {
            if (!listField.getOriginalName().equals("")) {
              String listOriginalName = listField.getOriginalNameForList();
              actionElement =
                  (elementFormDefault || useFirstElementPrefix)
                      ? actionElement.addChildElement(listOriginalName, ACTION_PREFIX)
                      : actionElement.addChildElement(listOriginalName);
              useFirstElementPrefix = false;
            }
          }
          List<RpcFields> childrens = listField.getChildrens();
          for (int i = 0; i < childrens.size(); i++) {
            element =
                (elementFormDefault || useFirstElementPrefix)
                    ? actionElement.addChildElement(listField.getOriginalName(), ACTION_PREFIX)
                    : actionElement.addChildElement(listField.getOriginalName());
            useFirstElementPrefix = false;
            setFields(childrens.get(i).getFields(), element);
          }
          break;
      }
    }
  }