-
-
Save mdmyr/6f0e01bf93fd43d93d247c07ef7af853 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
targetNamespace="urn:bes-external-call.informatica.mdm" | |
xmlns:exc="urn:bes-external-call.informatica.mdm"> | |
<xsd:complexType name="ExternalCallRequest"> | |
<xsd:annotation> | |
<xsd:documentation>External Web Service should accept this type as request (message part for soap operation input)</xsd:documentation> | |
</xsd:annotation> | |
<xsd:sequence> | |
<xsd:element name="header" type="exc:Header" maxOccurs="1"/> | |
<xsd:element name="trigger" type="exc:Trigger" maxOccurs="1"/> | |
<xsd:element name="serviceCall" type="exc:ServiceCall" maxOccurs="1"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name=" "> | |
<xsd:annotation> | |
<xsd:documentation>External Web Service should return this type as request (message part for soap operation output)</xsd:documentation> | |
</xsd:annotation> | |
<xsd:choice> | |
<xsd:element name="serviceCall" type="exc:ServiceCall" maxOccurs="1"/> | |
<xsd:element name="serviceError" type="exc:ServiceError" maxOccurs="1"/> | |
</xsd:choice> | |
</xsd:complexType> | |
<xsd:complexType name="Header"> | |
<xsd:annotation> | |
<xsd:documentation>Information about ORS, user, his roles, etc</xsd:documentation> | |
</xsd:annotation> | |
<xsd:sequence> | |
<xsd:element name="orsId" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="user" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="role" type="xsd:string" maxOccurs="unbounded"/> | |
<xsd:element name="reposVersion" type="xsd:string" maxOccurs="1"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="Trigger"> | |
<xsd:annotation> | |
<xsd:documentation>Explains context for external web service call: Business Entity that is being processed by Hub, processing phase.</xsd:documentation> | |
</xsd:annotation> | |
<xsd:sequence> | |
<xsd:element name="businessEntity" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="servicePhase" type="exc:ServicePhase" maxOccurs="1"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:simpleType name="ServicePhase"> | |
<xsd:restriction base="xsd:string"> | |
<xsd:enumeration value="WriteCO.BeforeEverything"/> | |
<xsd:enumeration value="WriteCO.BeforeValidate"/> | |
<xsd:enumeration value="WriteCO.AfterValidate"/> | |
<xsd:enumeration value="WriteCO.AfterEverything"/> | |
<xsd:enumeration value="WriteView.BeforeEverything"/> | |
<xsd:enumeration value="WriteView.BeforeValidate"/> | |
<xsd:enumeration value="WriteView.AfterValidate"/> | |
<xsd:enumeration value="WriteView.AfterEverything"/> | |
<xsd:enumeration value="MergeCO.BeforeEverything"/> | |
<xsd:enumeration value="MergeCO.AfterEverything"/> | |
<xsd:enumeration value="PreviewMergeCO.BeforeEverything"/> | |
<xsd:enumeration value="PreviewMergeCO.AfterEverything"/> | |
<xsd:enumeration value="ReadCO.BeforeEverything"/> | |
<xsd:enumeration value="ReadCO.AfterEverything"/> | |
<xsd:enumeration value="ReadView.BeforeEverything"/> | |
<xsd:enumeration value="ReadView.AfterEverything"/> | |
</xsd:restriction> | |
</xsd:simpleType> | |
<xsd:complexType name="ServiceCall"> | |
<xsd:annotation> | |
<xsd:documentation>This class contains actual Business Entity data and parameters that we passed to service.</xsd:documentation> | |
</xsd:annotation> | |
<xsd:sequence> | |
<xsd:element name="objectXml" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="parameter" type="exc:Parameter" maxOccurs="unbounded"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="ServiceError"> | |
<xsd:sequence> | |
<xsd:element name="code" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="message" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="detailsXml" type="xsd:string" maxOccurs="1"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="Parameter"> | |
<xsd:choice minOccurs="0" maxOccurs="1"> | |
<xsd:element name="stringValue" type="xsd:string"/> | |
<xsd:element name="intValue" type="xsd:int"/> | |
<xsd:element name="doubleValue" type="xsd:double"/> | |
<xsd:element name="dateValue" type="xsd:dateTime"/> | |
<xsd:element name="booleanValue" type="xsd:boolean"/> | |
<xsd:element name="xmlValue" type="xsd:string"/> | |
</xsd:choice> | |
<xsd:attribute name="name" type="xsd:string" use="required"/> | |
</xsd:complexType> | |
</xsd:schema> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<wsdl:definitions name="CustomLogicService" | |
targetNamespace="http://cs.sample.mdm.informatica.com/" | |
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" | |
xmlns:tns="http://cs.sample.mdm.informatica.com/" | |
xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> | |
<wsdl:types> | |
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
targetNamespace="urn:bes-external-call.informatica.mdm" | |
xmlns:exc="urn:bes-external-call.informatica.mdm"> | |
<xsd:complexType name="ExternalCallRequest"> | |
<xsd:sequence> | |
<xsd:element name="header" type="exc:Header" maxOccurs="1"/> | |
<xsd:element name="trigger" type="exc:Trigger" maxOccurs="1"/> | |
<xsd:element name="serviceCall" type="exc:ServiceCall" maxOccurs="1"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="ExternalCallResponse"> | |
<xsd:choice> | |
<xsd:element name="serviceCall" type="exc:ServiceCall" maxOccurs="1"/> | |
<xsd:element name="serviceError" type="exc:ServiceError" maxOccurs="1"/> | |
</xsd:choice> | |
</xsd:complexType> | |
<xsd:complexType name="Password"> | |
<xsd:sequence> | |
<xsd:element name="password" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="encrypted" type="xsd:boolean" maxOccurs="1" default="false"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="Header"> | |
<xsd:sequence> | |
<xsd:element name="orsId" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="user" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="role" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/> | |
<xsd:element name="password" type="exc:Password" minOccurs="0" maxOccurs="1"/> | |
<xsd:element name="payload" type="xsd:string" minOccurs="0" maxOccurs="1"/> | |
<xsd:element name="reposVersion" type="xsd:string" minOccurs="0" maxOccurs="1"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="Trigger"> | |
<xsd:sequence> | |
<xsd:element name="businessEntity" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="servicePhase" type="xsd:string" maxOccurs="1"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="ServiceCall"> | |
<xsd:sequence> | |
<xsd:element name="objectXml" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="parameter" type="exc:Parameter" maxOccurs="unbounded"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="ServiceError"> | |
<xsd:sequence> | |
<xsd:element name="code" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="message" type="xsd:string" maxOccurs="1"/> | |
<xsd:element name="detailsXml" type="xsd:string" maxOccurs="1"/> | |
</xsd:sequence> | |
</xsd:complexType> | |
<xsd:complexType name="Parameter"> | |
<xsd:choice minOccurs="0" maxOccurs="1"> | |
<xsd:element name="stringValue" type="xsd:string"/> | |
<xsd:element name="intValue" type="xsd:int"/> | |
<xsd:element name="doubleValue" type="xsd:double"/> | |
<xsd:element name="dateValue" type="xsd:dateTime"/> | |
<xsd:element name="booleanValue" type="xsd:boolean"/> | |
<xsd:element name="xmlValue" type="xsd:string"/> | |
</xsd:choice> | |
<xsd:attribute name="name" type="xsd:string" use="required"/> | |
</xsd:complexType> | |
</xsd:schema> | |
<xsd:schema targetNamespace="http://cs.sample.mdm.informatica.com/" | |
xmlns:exc="urn:bes-external-call.informatica.mdm"> | |
<xsd:import namespace="urn:bes-external-call.informatica.mdm"/> | |
<xsd:element name="validate" type="exc:ExternalCallRequest"/> | |
<xsd:element name="validateResponse" type="exc:ExternalCallResponse"/> | |
</xsd:schema> | |
</wsdl:types> | |
<wsdl:message name="validate"> | |
<wsdl:part name="parameters" element="tns:validate"/> | |
</wsdl:message> | |
<wsdl:message name="validateResponse"> | |
<wsdl:part name="parameters" element="tns:validateResponse"/> | |
</wsdl:message> | |
<wsdl:portType name="CustomLogicService"> | |
<wsdl:operation name="validate"> | |
<wsdl:input message="tns:validate"/> | |
<wsdl:output message="tns:validateResponse"/> | |
</wsdl:operation> | |
</wsdl:portType> | |
<wsdl:binding name="CustomLogicServicePortBinding" type="tns:CustomLogicService"> | |
<soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> | |
<wsdl:operation name="validate"> | |
<soap:operation soapAction=""/> | |
<wsdl:input> | |
<soap:body use="literal"/> | |
</wsdl:input> | |
<wsdl:output> | |
<soap:body use="literal"/> | |
</wsdl:output> | |
</wsdl:operation> | |
</wsdl:binding> | |
<wsdl:service name="CustomLogicService"> | |
<wsdl:port name="CustomLogicServicePort" binding="tns:CustomLogicServicePortBinding"> | |
<soap:address location="http://localhost:8080/bes-external-call/customLogicService"/> | |
</wsdl:port> | |
</wsdl:service> | |
</wsdl:definitions> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.informatica.mdm.sample.cs; | |
import java.util.Map; | |
import com.informatica.mdm.cs.CallContext; | |
import com.informatica.mdm.cs.client.CompositeServiceClient; | |
import com.informatica.mdm.spi.cs.StepException; | |
import com.informatica.mdm.spi.externalcall.CustomLogic; | |
import com.informatica.mdm.spi.externalcall.CustomLogicFactory; | |
import com.informatica.mdm.spi.externalcall.ServicePhase; | |
import com.informatica.mdm.spi.externalcall.Trigger; | |
import com.informatica.mdm.spi.externalcall.ExternalCallRequest; | |
import commonj.sdo.DataObject; | |
import commonj.sdo.helper.HelperContext; | |
public class CustomLogicFactoryImpl implements CustomLogicFactory { | |
public static final String PERSON = "Person"; | |
private static final CustomLogic EMPTY_LOGIC = new EmptyLogic(); | |
private CompositeServiceClient besClient; | |
public (CompositeServiceClient besClient) { | |
this.besClient = besClient; | |
} | |
@Override | |
public CustomLogic create(ExternalCallRequest externalCallRequest) throws StepException { | |
throw new StepException("CallContext is required!"); | |
} | |
@Override | |
public CustomLogic create(ExternalCallRequest externalCallRequest, CallContext callContext) throws StepException { | |
// we interested in "Person" Business Entity only and can handle just few servcie phases | |
Trigger trigger = externalCallRequest.getTrigger(); | |
String businessEntity = trigger.getBusinessEntity(); | |
ServicePhase phase = trigger.getServicePhase(); | |
switch (phase) { | |
case WRITE_CO_BEFORE_VALIDATE: | |
if (PERSON.equals(businessEntity)) { | |
return new ValidatePerson(besClient, callContext); | |
} | |
break; | |
case PREVIEW_MERGE_CO_BEFORE_EVERYTHING: | |
case MERGE_CO_BEFORE_EVERYTHING: | |
if (PERSON.equals(businessEntity)) { | |
return new MergePerson(); | |
} | |
break; | |
default: | |
// | |
} | |
return EMPTY_LOGIC; // this one will do nothing | |
} | |
private static class EmptyLogic implements CustomLogic { | |
public static final DataObject OBJECT = null; | |
@Override | |
public DataObject process(HelperContext helperContext, DataObject dataObject, Map<String, Object> map, | |
Map<String, Object> map1) throws StepException { | |
return OBJECT; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.informatica.mdm.sample.cs; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.util.Properties; | |
import javax.xml.transform.Source; | |
import javax.xml.ws.Provider; | |
import javax.xml.ws.Service.Mode; | |
import javax.xml.ws.ServiceMode; | |
import javax.xml.ws.WebServiceProvider; | |
import com.informatica.mdm.cs.client.CompositeServiceClient; | |
import com.informatica.mdm.spi.externalcall.CustomLogicFactory; | |
import com.informatica.mdm.spi.externalcall.ExternalCallProcessor; | |
import com.siperian.sif.client.EjbSiperianClient; | |
import com.siperian.sif.client.SiperianClient; | |
/** | |
* Web service implementation. | |
* It must accept {urn:bes-external-call.informatica.mdm}ExternalCallRequest as operation input | |
* and return {urn:bes-external-call.informatica.mdm}ExternalCallResponse as output | |
*/ | |
@WebServiceProvider( | |
targetNamespace = "http://cs.sample.mdm.informatica.com/", | |
serviceName = "CustomLogicService", | |
portName = "CustomLogicServicePort", | |
wsdlLocation = "WEB-INF/wsdl/custom-logic-service.wsdl" | |
) | |
@ServiceMode(Mode.PAYLOAD) | |
public class CustomLogicService implements Provider<Source> { | |
@Override | |
public Source invoke(Source request) { | |
CompositeServiceClient compositeServiceClient = createCompositeServiceClient(); | |
CustomLogicFactory customLogicFactory = new CustomLogicFactoryImpl(compositeServiceClient); | |
String appName = "<trusted user>"; // replace with proper application user name | |
// create processor instance ond let it do the job. | |
// all we need to provide is a custom logic factory implementation. | |
ExternalCallProcessor externalCallProcessor = | |
new ExternalCallProcessor(compositeServiceClient, appName, customLogicFactory); | |
return externalCallProcessor.invoke(request); | |
} | |
private static CompositeServiceClient createCompositeServiceClient() { | |
InputStream resourceAsStream = CustomLogicService.class.getResourceAsStream("/bes-client.properties"); | |
Properties config = new Properties(); | |
try { | |
config.load(resourceAsStream); | |
} catch (IOException e) { | |
throw new RuntimeException(e); | |
} | |
return CompositeServiceClient.newCompositeServiceClient(config); | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.informatica.mdm.sample.cs; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.List; | |
import java.util.Map; | |
import com.informatica.mdm.cs.CallContext; | |
import com.informatica.mdm.cs.api.CompositeServiceException; | |
import com.informatica.mdm.cs.client.CompositeServiceClient; | |
import com.informatica.mdm.sdo.cs.base.ValidationError; | |
import com.informatica.mdm.sdo.cs.base.ValidationErrors; | |
import com.informatica.mdm.spi.cs.StepException; | |
import com.informatica.mdm.spi.externalcall.CustomLogic; | |
import commonj.sdo.DataObject; | |
import commonj.sdo.helper.DataFactory; | |
import commonj.sdo.helper.HelperContext; | |
import mdm.informatica.cs_ors.ReadEntity; | |
/** | |
* This is piece of logic for validating "Person" Business Entity. | |
* All we do here is force user to provide at least one Address for the Person. | |
*/ | |
public class ValidatePerson implements CustomLogic { | |
private CompositeServiceClient besClient; | |
private CallContext callContext; | |
public ValidatePerson(CompositeServiceClient besClient, CallContext callContext) { | |
this.besClient = besClient; | |
this.callContext = callContext; | |
} | |
@Override | |
public DataObject process(HelperContext helperContext, DataObject inputSdo, | |
Map<String, Object> inParams, | |
Map<String, Object> outParams) throws StepException { | |
try { | |
// make sure "Person" SDO has at least one "Address" item | |
List<?> list = inputSdo.getList("Person/Addresses/item"); | |
if ((list == null) || list.isEmpty()) { | |
DataFactory dataFactory = helperContext.getDataFactory(); | |
String personId = inputSdo.getString("Person/rowidObject"); | |
if(personId != null) { // check if address already exist | |
DataObject readEntity = dataFactory.create(ReadEntity.class); | |
DataObject personFilter = readEntity.createDataObject("parameters").createDataObject("coFilter").createDataObject("object"); | |
personFilter.setString("name", "Person"); | |
personFilter.createDataObject("key").setString("rowid", personId); | |
DataObject addressFilter = personFilter.createDataObject("object"); | |
addressFilter.setString("name", "Addresses"); | |
addressFilter.createDataObject("pager").setInt("recordsToReturn", 1); | |
DataObject readEntityReturn = besClient.process(callContext, readEntity); | |
List existingList = readEntityReturn.getList("object/Person/Addresses/item"); | |
if(existingList != null && !existingList.isEmpty()) { | |
return null; | |
} | |
} | |
List<ValidationError> errorList = new ArrayList<>(); | |
ValidationError error = (ValidationError) dataFactory.create(ValidationError.class); | |
error.setCode("CUSTOM-00001"); | |
error.setMessage("Person must have at least one Address"); | |
error.setField(Collections.singletonList("Person.Addresses")); | |
errorList.add(error); | |
ValidationErrors errors = (ValidationErrors) dataFactory.create(ValidationErrors.class); | |
errors.setError(errorList); | |
throw new StepException((DataObject) errors, "SIP-50022"); | |
} | |
} catch (CompositeServiceException e) { | |
throw new StepException(e); | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment