Chapter D - Fault Handling

Posted at 2010. 8. 12. 13:27 | Posted in Oracle Solution/PO Processing
반응형
Introduction

에러가 발생했을때 처리하는 법을 알아보겠습니다.



Test service unavailability

원격 에러(remote fault) 에 대한 에러 처리 정책을 정의하는 법을 알아봅시다.

먼저 validationForCC 웹서비스를 잠시 내려봅시다.

JDeveloper의 Application Server Navigator에서 validationForCC(Composite)를 내릴 수 있습니다.





※ Application Server Navigator가 안보인다면 View 메뉴에 있습니다.



※ EM(Enterprise Manager)에서도 내릴 수 있습니다.



이제 POProcessing를 테스트 합시다.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:ns1="http://xmlns.oracle.com/ns/order">
        <ns1:PurchaseOrder>
            <ns1:CustID>1111</ns1:CustID>
            <ns1:ID>2222</ns1:ID>
            <ns1:productName>iPod shuffle</ns1:productName>
            <ns1:itemType>Electronics</ns1:itemType>
            <ns1:price>145</ns1:price>
            <ns1:quantity>30</ns1:quantity>
            <ns1:status>Initial</ns1:status>
            <ns1:ccType>Mastercard</ns1:ccType>
            <ns1:ccNumber>1234-1234-1234-1234</ns1:ccNumber>
        </ns1:PurchaseOrder>
    </soap:Body>
</soap:Envelope>

메시지 흐름 추적 실행을 해보면 에러가 발생했습니다.



getStatusByCC 웹서비스를 호출해야 하는데 웹서비스가 꺼져있어서 나는 에러 입니다.



remoteFault를 확인할 수 있습니다.





Add policy-based fault handler to do manual recovery

사용자 복구를 위한 기본 정의를 추가해봅시다.

아래 두 파일을 POProcessing 프로젝트 폴더에 복사합니다.

 



JDeveloper의 Application Navigator에서 새로고침을 누르면 복사된 파일이 나타납니다.



fault-policies.xml 파일은 에러에 따른 처리를 정의하는 파일이고, fault-bindings.xml 파일은 이 정의를 적용시키는 역할을 합니다.

fault-policies.xml 파일을 열어서 편집합니다.

Step D.2.2.2 주석 바로 아래에 아래의 내용을 추가합니다.

      <!-- Step D.2.2.2: Add your fault handler for remote fault here: -->
      <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension" name="bpelx:remoteFault">
        <condition>
            <action ref="ora-human-intervention" />
        </condition>
      </faultName>

모두 저장 후 배치 합니다.

EM 에서 다시 테스트 후 메시지 흐름 추적 실행을 해보면 getStatusByCC는 에러가 나있고, approveLargeOrder(BPEL Process)는 실행 중인 것을 확인할 수 있습니다.

그리고 오류 메시지 부분에 복구라는 부분이 생겼습니다.



감사 추적을 보면 아래와 같은 부분이 나옵니다.



BPEL Process의 흐름을 보면 invokeCCStatusService 액티브에서 노란색 오로라를 뿜고 있습니다.

이 Invoke 부분에서 remote fault이 발생하여 사용자가 수동으로 처리를 해주기를 기다리고 있는 것입니다.



※ 여기서도 확인할 수 있습니다.



이제 validationForCC composite를 다시 살립시다.



위의 상태에서 "복구"를 누르거나 BPEL Process 추적 창에서 복구탭을 누르거나(방법은 좀 있는듯...) 해서 복구 탭으로 이동합니다.

에러 메시지 선택 후 복구 버튼을 클릭합니다.



예 클릭



정상적으로 에러가 없이 됐으면 아래와 같이 오류 메시지 목록에 아무것도 없습니다.



흐름 추적을 보변 2번째 복구(1번은 처음 실행시에 난 에러)에서 처리가 되어서 정상 처리가 끝까지 된 것을 확인할 수 있습니다.





Handle faults in BPEL

먼저 Database에서 작업을 하나 해줘야합니다. soademo/soademo로 들어가서 create_validate_cc.sql 스크립트를 실행해주세요.



CreditCardValidation Application - validationForCC Project - composite.xml 파일을 열어 편집합니다.

Database Adapter를 추가합니다.



Service name: validateCC



JNDI Name: eis/DB/soademoDatabase



Call a Stored Procedure or Function을 선택합니다.



Browse 버튼을 클릭합니다.



VALIDATECC를 선택합니다.



선택된 프로시저 확인 후 Next 클릭



Next



Finish



RouteReques(Mediator)와 validateCC(Database Adapter)를 연결합니다.



RouteReques(Mediator)를 더블 클릭하여 편집합니다.

getCreditValidation으로 가는 조건을 입력합니다.



not(starts-with($in.request/inp1:creditcardStatusRequest/inp1:CCNumber, '2'))

카드번호 맨 앞자리가 '2'로 시작하지 않는 조건입니다.



validateCC로 가는 조건도 입력합니다.

starts-with($in.request/inp1:creditcardStatusRequest/inp1:CCNumber, '2')

카드번호 맨 앞자리가 '2'로 시작하는 조건입니다.

validateCC로 가는 Transform 맵핑을 설정합니다.







validateCC에서 리턴받는 Transform 맵핑을 설정합니다.







모두 저장후 배치 합니다.

카드번호가 2로 시작하는 데이터를 입력합니다.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:ns1="http://xmlns.oracle.com/ns/order">
        <ns1:PurchaseOrder>
            <ns1:CustID>1111</ns1:CustID>
            <ns1:ID>2222</ns1:ID>
            <ns1:productName>iPod shuffle</ns1:productName>
            <ns1:itemType>Electronics</ns1:itemType>
            <ns1:price>145</ns1:price>
            <ns1:quantity>30</ns1:quantity>
            <ns1:status>Initial</ns1:status>
            <ns1:ccType>Mastercard</ns1:ccType>
            <ns1:ccNumber>2234-1234-1234-1234</ns1:ccNumber>
        </ns1:PurchaseOrder>
    </soap:Body>
</soap:Envelope>

binding fault 에러가 발생했습니다.



BPEL 내에서 binding fault 에러를 제어 해봅시다.

approverLargeOrder(BPEL Process)를 편집합니다.



assignCCNumber(Assign) 액티브와 invokeCCStatusService(Invoke) 액티브 사이에 Scope 액티브를 추가합니다.



이름 부분을 더블 클릭 후 checkCC로 변경합니다.



Scope 액티브를 펼칩니다.



invokeCCStatusService(Invoke) 액티브를 Scope 액티브 안으로 넣습니다.



Scope 내의 아이콘중에 Add Catch Branch 아이콘을 클릭합니다.



추가된 Catch Branch를 펼칩니다.



Catch 아이콘을 더블 클릭합니다.



Browse Faults 버튼을 클릭합니다.



System Faults > bindingFault 을 선택합니다.



Fault Variable을 자동 생성합니다.



OK를 클릭합니다.



OK를 클릭합니다.



catch 영역 안에 Switch 액티브를 추가합니다.



<case> 의 조건을 입력합니다.



<case> 영역에 Assign 액티브를 추가합니다.



이름을 Assign_UNKNOWNCC로 변경 후 아이콘을 더블 클릭합니다.



From은 'UNKNOWN CC' 입력, To는 invokeCCStatusService_execute_OutputVariable - reply - creditcardStatus를 선택합니다.



<otherwise> 영역에 Throw 액티브를 추가합니다.



이름을 Throw_Binding_Fault로 변경 후 아이콘을 더블 클릭합니다.



Fault QName은 System Faults > bindingFault 선택 후 Fault Variable 오른쪽에 Browse Fault Variables.. 버튼을 클릭합니다.



catch 설정할 때 만들었던 FaultVar를 선택합니다.



OK 클릭



fault-policies.xml 파일을 열어 아래 내용을 추가합니다. (Step D.2.4.20 주석 아래에)

      <!-- Step D.2.4.20: Add your fault handler for binding fault here: -->
      <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension" name="bpelx:bindingFault">
        <condition>
          <!-- Let the component handle this specific binding fault -->
          <test>$fault.code="20001"</test>
          <action ref="ora-rethrow-fault" />
        </condition>
      </faultName>

다시 카드번호가 '2'로 시작하는 데이터로 테스트 해보겠습니다.

getStatusByCC 서비스에서 에러는 났지만 approveLargeOrder(BPEL Process)는 정상적으로 완료 되었습니다.



감사 추적을 살펴보면 invokeCCStatusService 액티브에서 오류가 발생했고 catch 영역에서 에러를 처리했습니다.



BPEL에서 Scope는 Java의 try catch 역할도 합니다.



Using A Custom Java Fault Handler

이번에는 사용자가 직접 Java로 작성한 에러 처리를 적용해보겠습니다.

※ 에러처리에 사용할 예제 java 소스(jar)가 웹로직 서버 도메인의 lib 폴더에 있어야 합니다. 서버 실행중에 적용했다면 재시작!!

그리고 C:\po\log 폴더(웹로직 서버가 구동중인 컴퓨터입니다!!! 주의!)가 존재야 합니다.




fault-policies.xml 파일을 아래와 같이 수정합니다.

      <!-- Step D.2.4.20: Add your fault handler for binding fault here: -->
      <faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension" name="bpelx:bindingFault">
        <condition>
          <!-- Let the component handle this specific binding fault -->
          <test>$fault.code="20001"</test>
          <!-- <action ref="ora-rethrow-fault" /> -->
          <action ref="my-java-handler" />
        </condition>
      </faultName>

모두 저장 후 다시 배치. 카드 번호가 '2'로 시작하는 데이터로 테스트 해보겠습니다.

잘 처리 되었습니다.



soa console 에는 아래와 같이 출력됩니다.

MyFaultHanlder: Handle Fault
MyFaultHanlder: Properties
MyFaultHanlder: =================================================================
MyFaultHanlder: logFileName = myfaulthandler.log
MyFaultHanlder: logFileDir = c:\po\log

c:\po\log\myfaulthandler.log 파일을 열어보면 아래와 같습니다.

Fault Details
===============================================================
Fault Type ................ bpel
Poilcy ID ................. POProcessingFaults
Faulted Partner Link ...... getGreditCardStatus
Port Type ................. {http://oracle.com/sca/soapservice/CreditCardValidation/validationForCC/getStatusByCC}getGreditCardStatus



Handle Mediator Faults

Mediator에서 나는 에러를 처리해봅시다.

fault-policies,xml 을 아래와 같이 편집합니다. (Step D.2.6.1 주석 아래에 추가)

      <!-- Step D.2.6.1: Add your fault handler for mediator faults here: -->
      <faultName xmlns:medns="http://schemas.oracle.com/mediator/faults" name="medns:mediatorFault">
        <condition>
          <action ref="my-mediator-fault-handler" />
        </condition>
      </faultName>

Action을 하나 더 추가합니다. (Step D.2.6.2 주석 아래 추가)

      <!-- Step D.2.6.2: Add the Action definition for handling mediator fauls using custom java here:-->
      <Action id="my-mediator-fault-handler">
        <javaAction className="soatraining.faulthandling.MyFaultHandler"
            defaultAction="ora-terminate" propertySet="myMediatorProps">
            <returnValue value="OK" ref="ora-human-intervention" />
        </javaAction>
      </Action>

새로운 JavaAction에 사용되는 프로퍼티를 세팅합니다. (Step D.2.6.3 주석 아래 추가)

      <!-- Step D.2.6.3?: Add new property set for MyFaultHandler for logging Mediator faults here:-->
      <propertySet name="myMediatorProps">
        <property name="logFileName">mediator-faults.log</property>
        <property name="logFileDir">c:\po\log</property>
      </propertySet>

routePO(Mediator)를 수정합니다.



WriteApprovalResults 로 가는 라우팅을 병렬(Parallel)로 변경합니다.



Yes를 클릭합니다.



모두 저장 후 재배치합니다.

에러를 내기 위헤서 파일이 저장되는 폴더(C:\Temp)를 읽기 전용(쓰기 불가능)으로 만들겠습니다.

윈도우(Windows)의 경우
  - 읽기전용 설정
    > attrib +r c:\temp
  - 읽기전용 해제
    > attrib -r c:\temp
리눅스(Linux)의 경우
  - 읽기전용 설정
    $ chmod -w /temp
  - 읽기전용 해제
    $ chmod +w /temp 

이제 EM(Enterprise Manager)에서 테스트를 해봅시다.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body xmlns:ns1="http://xmlns.oracle.com/ns/order">
        <ns1:PurchaseOrder>
            <ns1:CustID>1111</ns1:CustID>
            <ns1:ID>2121</ns1:ID>
            <ns1:productName>Bluetooth Headset</ns1:productName>
            <ns1:itemType>Electronics</ns1:itemType>
            <ns1:price>49.99</ns1:price>
            <ns1:quantity>1</ns1:quantity>
            <ns1:status>Initial</ns1:status>
            <ns1:ccType>Mastercard</ns1:ccType>
            <ns1:ccNumber>8765-8765-8765-8765</ns1:ccNumber>
        </ns1:PurchaseOrder>
    </soap:Body>
</soap:Envelope>

메시지 흐름 추적을 보면 에러가 났습니다.



감사 추적을 보면 WriteApprovalResults.Write 부분에서 에러가 난것을 볼 수 있습니다.



C:\Temp 폴더의 읽기 전용을 해제 한뒤, 복구를 해봅시다.



예 클릭



복구 작업이 성공적으로 완료되었습니다.



다시 메시지 흐름 추적을 보면 재시도한 흔적(?)을 확인할 수 있습니다.







반응형
//