2016-07-08 5 views
3

SOAP 요청을 처리하는 데있어 새로운 기능이있어서 here으로 표시된 Workday의 SOAP API를 사용하려고합니다. 나는 gradle/ant 스크립트를 사용하여 Spring 튜토리얼을 기반으로 WSDL에서 클래스를 생성했다. hereAuthenticaion Spring SOAP to Workday

이제 클래스가 생성되었으므로 필요한 함수에 액세스 할 수있다. 문제는 내 요청을 인증하는 방법을 모른다는 것입니다.

import org.springframework.oxm.jaxb.Jaxb2Marshaller; 
import org.springframework.ws.client.core.support.WebServiceGatewaySupport; 
import workday_Staffing.wsdl.GetWorkersRequestType; 
import workday_Staffing.wsdl.GetWorkersResponseType; 

public class StaffingClient extends WebServiceGatewaySupport { 

    public StaffingClient() { 
     Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller(); 
     jaxb2Marshaller.setContextPath("workday_Staffing.wsdl"); 
     setMarshaller(jaxb2Marshaller); 
     setUnmarshaller(jaxb2Marshaller); 
    } 

    public void makeWorkdayRequest() { 

     // make the request - missing some authentication here 
     GetWorkersRequestType request = new GetWorkersRequestType(); 
     GetWorkersResponseType workersResponseType = (GetWorkersResponseType) getWebServiceTemplate() 
      .marshalSendAndReceive(request); 
    } 
} 

대답 here 좋은 리드 것 같아하지만 난 클라이언트를 구축하고 인증을 추가하는 방법을 누락 :

이것은 내가 지금까지있는 것입니다.

도움이 될 것입니다.

답변

2

WS-Security Credentials에 대한 SOAPHandler를 통해 인증 조각이 누락 된 것 같습니다. FYI, 이것은 Spring이 아니지만 API의 v16에서 작동하는 코드입니다.

메모리 레인을 내려 주셔서 감사합니다.

단계

  1. 근무 사용자 이름과 세입자
  2. 설정
  3. 웹 서비스 클라이언트 포트
  4. 을 설정 웹 서비스 클라이언트 스텁 (예 HumanResourcesService)를 설정 근무 암호 설정 WorkdayCredentials 핸들러를 port, workday user @ tenant 및 workday password에 대한 참조와 함께 클라이언트 스텁에 추가하십시오.
  5. 는 요청 문맥
  6. 설정 요청 문맥의 근무의 웹 서비스 엔드 포인트 (wdEndPoint 참조)
  7. GetWorkersRequestType
  8. 가 선택적으로 요청
  9. 에 대한 몇 가지 매개 변수를 설정 가져 오기 응답
  10. 응답 데이터 가져 오기를 받기

루틴

  • GetWorkers
  • WorkdayCredentials

GetWorkers 코드

package com.workday.demo; 

import java.util.GregorianCalendar; 
import java.util.Iterator; 
import java.util.Map; 
import java.math.BigDecimal; 

import javax.xml.datatype.DatatypeConfigurationException; 
import javax.xml.datatype.DatatypeFactory; 
import javax.xml.datatype.XMLGregorianCalendar; 
import javax.xml.ws.BindingProvider; 

import com.workday.human_resources.*; 

public class GetWorkers { 

    public static void main(String[] args) { 

     try { 

      // Enter user/password and endpoint information for Proof of Concept 
      final String wdUser = "[email protected]"; 
      final String wdPassword = "zzz"; 

      // final String wdEndpoint = 
      // "https://e2-impl-cci.workday.com/ccx/service/exampleTenant/Human_Resources/v16"; 
      final String wdEndpoint = "https://impl-cc.workday.com/ccx/service/exampleTenant/Human_Resources/v16"; 

      System.out.println("Starting..."); 

      // Create the Web Service client stub 
      HumanResourcesService service = new HumanResourcesService(); 
      HumanResourcesPort port = service.getHumanResources(); 

      // Add the WorkdayCredentials handler to the client stub 
      WorkdayCredentials.addWorkdayCredentials((BindingProvider) port, wdUser, wdPassword); 

      // Assign the Endpoint URL 
      Map<String, Object> requestContext = ((BindingProvider) port).getRequestContext(); 
      requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wdEndpoint); 

      // Define the paging defaults 
      final int countSize = 200; 
      int totalPages = 1; 
      int currentPage = 1; 

      // Set the current date/time 
      GregorianCalendar cal = new GregorianCalendar(); 
      XMLGregorianCalendar xmlCal = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal); 

      // Loop over all of the pages in the web service response 
      while (totalPages >= currentPage) { 
       // Create a "request" object 
       GetWorkersRequestType request = new GetWorkersRequestType(); 

       // Set the WWS version desired 
       request.setVersion("v10"); 

       // Set the date/time & page parameters in the request 
       ResponseFilterType responseFilter = new ResponseFilterType(); 
       responseFilter.setAsOfEntryDateTime(xmlCal); 
       responseFilter.setAsOfEffectiveDate(xmlCal); 
       responseFilter.setPage(BigDecimal.valueOf(currentPage)); 
       responseFilter.setCount(BigDecimal.valueOf(countSize)); 
       request.setResponseFilter(responseFilter); 

       // Set the desired response group(s) to return 
       WorkerResponseGroupType responseGroup = new WorkerResponseGroupType(); 
       responseGroup.setIncludeReference(true); 
       request.setResponseGroup(responseGroup); 

       // Submit the request creating the "response" object 
       GetWorkersResponseType response = port.getWorkers(request); 

       // Display all Workers 
       Iterator<WorkerType> i = response.getResponseData().getWorker() 
         .iterator(); 
       while (i.hasNext()) { 
        WorkerType worker = i.next(); 
        { 
         System.out.println(worker.getWorkerReference() 
           .getDescriptor()); 
        } 
       } 

       // Update page number 
       if (totalPages == 1) { 
        totalPages = response.getResponseResults().getTotalPages() 
          .intValue(); 
       } 
       currentPage++; 
      } 

     } catch (ProcessingFaultMsg e) { 
      e.printStackTrace(); 
     } catch (ValidationFaultMsg e) { 
      e.printStackTrace(); 
     } catch (DatatypeConfigurationException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

WorkdayCredentials 코드

package com.workday.demo; 

import java.util.List; 

import javax.xml.soap.SOAPElement; 
import javax.xml.soap.SOAPException; 
import javax.xml.soap.SOAPHeader; 
import javax.xml.soap.SOAPMessage; 
import javax.xml.ws.BindingProvider; 
import javax.xml.ws.handler.Handler; 
import javax.xml.ws.handler.MessageContext; 
import javax.xml.ws.handler.soap.SOAPHandler; 
import javax.xml.ws.handler.soap.SOAPMessageContext; 
import javax.xml.namespace.QName; 
import java.util.Set; 

/** 
* This class creates a handler that will add the WS-Security username and 
* password to the to the SOAP request messages for a client side proxy. 
* 
*/ 
public class WorkdayCredentials implements SOAPHandler<SOAPMessageContext> { 

    /** Namespace for the SOAP Envelope. */ 
    private static String SOAPENVNamespace = "http://schemas.xmlsoap.org/soap/envelope/"; 

    /** The prefix that will be used for the SOAP Envelope namespace. */ 
    private static String SOAPENVPrefix = "soapenv"; 

    /** Namespace for the WS-Security SOAP header elements. */ 
    private static String WSSENamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; 

    /** The prefix that will be used for the WS-Security namespace. */ 
    private static String WSSEPrefix = "wsse"; 

    /** 
    * The WS-Security URI that specifies that the password will be transmitted 
    * as plain text. 
    */ 
    private static String WSSEPasswordText = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"; 

    /** 
    * The user name that will be sent in the WS-Security header on the SOAP 
    * request message. This is of the form [email protected] 
    */ 
    private String username; 

    /** 
    * The password that will be sent in the WS-Security header on the SOAP 
    * request message. 
    */ 
    private String password; 

    /** 
    * This method created an instance of the WorkdayCredentials class and adds 
    * it as a handler to the bindingProvider supplied. 
    * 
    * @param bindingProvider 
    *   The client stub to which the handler will be added. The most 
    *   convenient way to obtain the required bindingProvvider is to 
    *   call one of the getPort methods on the Service class for the 
    *   Web service and then cast the returned object to a 
    *   BindingProvider. 
    * @param username 
    *   The id and tenant name for the user. This is of the form 
    *   [email protected] 
    * @param password 
    *   The password for the system user. 
    */ 
    @SuppressWarnings("unchecked") 
    public static void addWorkdayCredentials(BindingProvider bindingProvider, 
      String username, String password) { 
     List<Handler> handlerChain = bindingProvider.getBinding().getHandlerChain(); 
     handlerChain.add(new WorkdayCredentials(username, password)); 
     bindingProvider.getBinding().setHandlerChain(handlerChain); 
    } 

    /** 
    * Creates a WorkdayCredentials handler and initialises the member 
    * variables. In most cases, the addWorkdayCredentials static method should 
    * be used instead. 
    * 
    * @param username 
    *   The id and tenant name for the user. This is of the form 
    *   [email protected] 
    * @param password 
    *   The password for the system user. 
    */ 
    public WorkdayCredentials(String username, String password) { 
     this.username = username; 
     this.password = password; 
    } 

    /** 
    * Returns null as this handler doesn't process any Headers, it just adds 
    * one. 
    */ 
    public Set<QName> getHeaders() { 
     return null; 
    } 

    /** 
    * Adds WS-Security header to request messages. 
    */ 
    public boolean handleMessage(SOAPMessageContext smc) { 
     Boolean outboundProperty = (Boolean) smc 
       .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 
     if (outboundProperty.booleanValue()) { 
      addWSSecurityHeader(smc, username, password); 
     } 
     return true; 
    } 

    /** 
    * Returns true, no action is taken for faults messages. 
    */ 
    public boolean handleFault(SOAPMessageContext smc) { 
     return true; 
    } 

    public void close(MessageContext messageContext) { 
    } 

    /** 
    * Adds a WS-Security header containing a UsernameToken to a SOAP message. 
    * 
    * @param smc 
    *   The SOAPMessageContent to which the WS-Security header will be 
    *   added. 
    * @param username 
    *   The WS-Security username. 
    * @param password 
    *   The WS-Security password. 
    * 
    * @throws java.lang.RuntimeException 
    *    This exception will be thrown if a SOAPException occurs when 
    *    modifying the message. 
    */ 
    private void addWSSecurityHeader(SOAPMessageContext smc, String username, 
      String password) throws java.lang.RuntimeException { 

     try { 
      // Get the SOAP Header 
      SOAPMessage message = smc.getMessage(); 
      SOAPHeader header = message.getSOAPHeader(); 
      if (header == null) { 
       // Create header as it doesn't already exist 
       message.getSOAPPart().getEnvelope().addHeader(); 
       header = message.getSOAPHeader(); 
      } 

      // Add WS-Security SOAP Header 
      SOAPElement heSecurity = header.addChildElement("Security", 
        WSSEPrefix, WSSENamespace); 
      heSecurity.addAttribute(message.getSOAPPart().getEnvelope() 
        .createName("mustUnderstand", SOAPENVPrefix, 
          SOAPENVNamespace), "1"); 

      // Add the Usernametoken element to the WS-Security Header 
      SOAPElement heUsernameToken = heSecurity.addChildElement(
        "UsernameToken", WSSEPrefix, WSSENamespace); 

      // Add the Username element to the UsernameToken Element 
      heUsernameToken.addChildElement("Username", WSSEPrefix, 
        WSSENamespace).addTextNode(username); 

      // Add the Password element to the UsernameToken Element 
      SOAPElement hePassword = heUsernameToken.addChildElement(
        "Password", WSSEPrefix, WSSENamespace); 
      hePassword.addAttribute(message.getSOAPPart().getEnvelope() 
        .createName("Type"), WSSEPasswordText); 
      hePassword.addTextNode(password); 

     } catch (SOAPException e) { 
      throw new RuntimeException(
        "Failed to add WS-Security header to request", e); 
     } 
    } 
} 
+0

안녕, 답장을 보내 주셔서 고맙습니다. 최신이 아닌 API 중 v16을 사용한다고하셨습니다. 이 작업을 수행하는 새로운 방법이 있습니까? 아니면 단순히 URL에서 API 버전을 변경해야합니까? 또한,'Jaxb2Marshaller'를 사용하여 당신을 보지 못합니다. 왜? –

+0

26.2와 같은 최신 버전의 API를 사용해야합니다. Workday는 일반적으로 API를 지원하며 이전 버전을 잠시 지원합니다.새로운 것을 개발할 때 최신 안정 버전의 API를 사용하는 것이 가장 좋습니다. 이 예제 코드가 작동하려면 Axis2 wsdl2java를 실행하여 v16, 26.2 또는 현재 버전과 일치하는 새 클래스를 생성해야합니다. 임차인에게이 기능을 사용해보십시오. 왜 Jaxb2Marshaller가 아닌가요? 그건 봄의 일부이고 내보기는 그렇지 않습니다. – dbh