Showing posts with label EAI. Show all posts
Showing posts with label EAI. Show all posts

Asynchronous Workflow With Real User Login


Background


A common requirement amongst many Siebel customers, is to have the ability to run an asynchronous workflow under the real user's login.

This issue is highlighted in the following Oracle support web document, and is representative of the problems faced by many customers.

NOTE:494815.1 Setting CREATED_BY to the user that invoked the workflow process asynchronously

The customer stated that they have an asynchronous workflow, and wanted to know if it was possible to set the creator login of a server request. The solution offered by the support personnel was to run the work flow in synchronous mode.

Asynchronous workflows are used in Siebel to offload work from the user session to perform background processing, however that leaves an undesired effect of stamping the record with SADMIN. This behavior obscures information about the creator, updater, and prevents audit trail from being utilized.

Workflows can be run synchronously as suggested in the Oracle support web document above, but it has the rather unwanted effect of blocking the UI.

Fortunately, for customers who can't accept running background tasks synchronously, there is a viable solution, but it requires a little bit of effort.

Requirement


To re-affirm the requirement, we are going to walk through a solution that allows any workflow or business service in Siebel to be run asynchronously, under the actual users credentials, and without actually supplying the password!

If we step back, and look at the problem from an architectural perspective, we know that when the user logs into the Application and executes any type of code such as eScript, or workflow, it will run synchronously under the users application object manager, and it will operate under the users own credentials.

The only supported method to run code and avoid blocking the UI, is to run code under a background process, however any code that is run in the background will operate under SADMIN by default.

The first challenge is to find a supported method to execute code in a background session under the current users credentials. Experienced Siebel Integrators in the audience can probably guess, that we can achieve this with any Siebel API that supports SSO, or utilize the inbuilt impersonation capability of certain Siebel components.

The two most suitable choices are:
1. Siebel WS
2. Siebel JDB

I've highlighted these particular interfaces, because both provide APIs that can be invoked from a background session, and has the potential to allow arbitrary code to be dispatched, and run under a different set of credentials. As an added benefit, both of these APIs can be built to support load balancing for high availability.

With a suitable SSO API identified, we have the necessary key piece required to solve the above problem.

Solution Overview


The diagram below shows an overview of this proposed solution.

1. The user triggers an asynchronous task from the current user session, and is allowed to continue with their work in the application

2. In the background, A WFProcMgr component on the server executes the process, and calls a bespoke service called "JLE Session Transport Service" that acts as a wrapper for the transport.

3. A synchronous call is invoked over the transport, using the Siebel API identified above

4. The Siebel API instantiates a new session on behalf of the real user, executes the destination business service, and returns the results back to the background process.

Siebel API


An important implementation aspect worth considering upfront, is designing a transport agnostic API for the Siebel developer. The developer should be able to specify the desired subsystem, and the service should abstract the low level transport requirements, and perform the necessary acrobatics to make the call.

The following diagram shows how a facade is used for invoking the actual SSO interface.


A standard Siebel business service is defined, so it can be substituted in any existing workflow, or hooked into any existing Siebel trigger. The designer now has to implement the adapter code, and build the interface to communicate with the relevant SSO interface.

The implementation of interfaces to these Siebel APIs are out of scope of this article, as it requires different spectrum's of design, involve advanced integration, and require environment dependencies to exist, but the key considerations are provided below for customers who are interested in building this capability.

Depending on which SSO API is chosen, you may require an Integration specialist to implement a WS/BS dispatch wrapper, or a Siebel EAI/Java specialist to implement the Siebel-JDB bridge.

Please consult with your Siebel Integration Architect for more localized implementation advice.

Input Arguments


To support a plug and play design, I propose that all input arguments and child properties passed into this service would be dispatched to the remote business, in the same way as any other business service in Siebel including workflows.

This design allows us to go into tools, and retrofit this capability to any business service, without redevelopment effort. It is also deliberately designed to avoid hierarchy changes required for the correct invocation of the destination business service.

To control the dispatch, lets define a custom child hierarchy, which contains 3 key elements.

1. The user login to impersonate
2. The destination business service to dispatch to
3. The destination business method name

The diagram below illustrates the property set structure, with the required information to dispatch the call



This special PropertySet can sit at any index, however it should be removed before it is dispatched to the remote business service, in-case there is logic that is sensitive to property sets with specific indexes.

PropertySet Serialization


PropertySets are a Siebel proprietary representation of objects that only exist in memory. In order to send a PropertySet out of Siebel, and receive it back in, it has to be serialized, de-serialized, and potentially encoded to match transport constraints.

XML is usually used to transfer data between different systems, and Siebel provides methods to convert the PropertySet to XML, and back, however a more efficient method is to utilize Siebel's own PropertySet to text encoding format, or a utilise a custom JSON parsing engine in eScript. This minimizes the size of the message, results in less IO, and ensures that request is sent as efficiently as possible.

Error Handling


This is the most critical aspect of the design, as every component in the design has to be proactive in handling, and bubbling errors back up the chain.

The caller is effectively making a synchronous request/response call between two sessions. Errors at the end of the chain in the impersonated session, has to be propagated through the transport, to the calling session, which has the responsibility to handle and log any errors.

It is imperative that each component have guards in place to handle environmental, transport, and general unhanded exception scenarios, which could cause the call to fail.

This can happen for a variety of reasons including

Component is offline
Component Maxed Task
Connection timeouts
Failed authentication
Out of resource

The Siebel JDB interface has OOTB capability with extra options for configuring, settings such as retry, and timeouts, to counter some of the above issues. Customers choosing the Siebel WS API will have to consider implementing the appropriate mechanisms to guard against transient errors.

Load Testing


Both the Siebel WS, Siebel JDB options can be configured for load balancing through virtual server definitions. This capability allows this solution to scale easily. In practice this only works natively for the WS option, the JDB interface seems to only get load balanced if sessions are spawned from the thread. An as alternative, the load balancing responsibility for the JDB interface can be offloaded to the SRProc component.

Its important to understand the current expected load, and forecast the expected number of tasks that are needed. Every invocation can potentially spawn a new session, which could effectively double the amount of threads that the system has to spawn, along with the increased resource utilization, so it would prudent to involve your performance test team, and environment specialists to ensure that the application is tuned to handle the extra load.

Maintaining Impersonation


One last consideration in this design, is that once the user dispatches the work flow to be picked up in the background, no part of the invocation chain is allowed dispatch to another server process.

The impact is that the developer needs to ensure that all work flows are run inside the impersonated object manager. If a server request is initiated, that would then dispatch to a server thread, breaking the impersonation for that particular thread.

Conclusion


The above capability was designed and delivered for a customer who needed to meet regulatory audit requirements, to capture the identity of the users when they performed bulk CRUD operations across the application.

In the past customers who needed to meet this requirement would have chosen to take a hit in performance, and kill the user experience, while expensive background operations are forced to run in the foreground, or resort to creating extra columns across entities in the application to separately capture the identity of the user.

With a little bit of effort, Siebel customers now have the option of creating a custom impersonation component, that can run asynchronous tasks under a real user.

Advanced Siebel Integration - A SOA Review



A recent Oracle SOA review into one of my customers Siebel Integration capability, rated it as highly advanced. The innovative systems, processes, and tools that were put in place, evolved immensely over the years, and enabled the customer to build, deploy, test and maintain their interfaces quickly and with little effort.

In this organization, the Siebel team provided the front line EAI development, and supported a large portfolio of services across numerous touch points and multiple transport types including MQ, WS, File, HTTP. While adhering to architectural principles such as SOA, P2P, Pub/Sub, this Siebel system plays the role as a consumer, subscriber, publisher, and router of services.

The environment mix, architecture, and scale may differ in your organization, but there are some fundamental challenges that all Siebel Projects face.

High Level Challenges

- Simplify and standardize Integration
- Reduce Integration expenditure
- Agility and Time to market

Simplify and standardize Integration

From a high level, there are a variety of messaging requirements that we may encounter, including Request/Response, Notification, Async callbacks, Pub/sub, then we have various transports to handle, which may include HTTP, Message queues, file formats. We then have to choose between the various transformation options, and figure out how to generate our message with the correct headers, deal with message dispatch and error handling.

There are a variety of implementation options, and each developer will have their own approach to solving the above problems, which can lead to non standardized solutions, that overtime becomes difficult to maintain. Reducing the complexity, and standardising the way we implement integration requires a system that helps us to deliver a consistent solution to dealing with the above scenarios. 

A key component of this system is establishing a Siebel Integration competency centre (ICC), which acts to standardise Integration solutions. An ICC can be defined as team that is responsible for the Siebel EAI needs across different streams and projects. 

Another vital component is the integration framework. An integration framework encapsulates all common integration logic, implements standard design patterns, minimises customisation, coding, and minimize deviation from the standard design entry/exit points. A good integration framework provides the ability to integrate a lot of different technologies, and is instrumental in enabling projects to simply their Integration.

Reduce Integration expenditure

Some organisations approach integration on a case by case basis. The work is put together in an adhoc manner to achieve a certain result, and the grunt work is then repeated on the next project. Issues such as maintenance, error handing, and robustness, unfortunately is an after thought. This causes a lot duplication, waste, increases cost, maintainability, and risk.

An alternative approach is to look at introducing an integration factory. The concept of an integration factory, is not dis-similar to how car factories mass produce vehicles using standard core components, where robots perform the heavy lifting and mundane tasks on a production line, and engineers move in to perform the specialist tasks that require finesse and skill. This results in a consistent and quality deliverable, that is cost effective.

In the same way a Siebel integration factory, can delegate or automate certain integration chores, to free up the Siebel Integrator to perform more value added tasks. This factory consists of a set of tools and processes which allows projects to churn out interfaces using a cookie cutter approach to reduce integration build and test.

Under this approach, less experienced integrators can be used to safely deliver interface work, because the factory enforces a consistent approach to the build. Contrast this with an adhoc build approach, where a less experienced developer is provided with 101 ways to implement something simple like validation, and countless ways to trigger, and implement automation. We can imagine the outcome will be inconsistent, to say the least, and is likely to result in increase costs for the next project who has to maintain this work.
 
An Integration factory provides tools to work with messaging requirements, scaffolding for quick deployment of interfaces, and a controlled process to produce interfaces. Integration artefacts such as VBCs, Inbound, Outbound, Request/Response interfaces all have a certain flavour, and are produced with the same common components, and are orchestrated to meet a requirement. 

By applying standardisation, establishing reusable components, and using proven design patterns to solve known problems, we can reduce the cost and risk of implementing integration.

Agility and Time to market

Many Siebel projects need to support rapidly changing business requirements, and deliver on future initiatives at the same time. Integration is traditionally seen as risky, costly, and usually delegated to major releases, which limits the ability to be agile and deliver solutions quickly.

One of the keys to agility in Siebel is to keep logic out of the SRF, and fortunately Siebel provides a lot of options to configure EAI capability on the fly.

Client side business services

Client side business services allow Siebel customers to configure and deploy technical logic to a run time database. This capability allows project to change logic on the fly, and maintain a 24/7 application. There are customers that purely use Client side business service because of the agility advantages over eScript.

Siebel Workflows

Siebel workflows are the work horse of automation in Siebel, it provides a nice interface with a visual representation of customer logic. Workflows can be configured and deployed to a run time database, allowing projects to switch workflow definitions on the fly, and apply logic changes without downtime.

Business Rule Processor (BRP)

BRP was designed as declarative replacement for eScript, and allows projects to build application logic using a browser. These rules are then executed by a highly optimised engine that works beneath the Siebel BO layer to maximise logic execution. BRP rules can configured and deployed using the Siebel thin client.

Data Mapper

Datamapper is Siebel’s declarative engine that performs an object to object transformation. Data map transformations can be also configured using the Siebel thin client.

Runtime Integration Objects

Integration objects are representations of a model in Siebel, which is usually built using Siebel tools, and compiled into a SRF. However, with an appropriately connected thick client, Integration object definitions can be deployed to a run time database. When runtime Integration Objects are combined with the right mix of EAI technologies, Siebel customers can build and deploy interfaces without downtime.

XSLT

Siebel provides XSLT 1.0 as standard out of the box, but customers can easily implement an XSLT 2.0 engine to get access to an expanded set of transformation options, and speed benefits. XSLT provides a powerful declarative transformation alternative to eScript or Data mapper. 

The Siebel product has a solid range of construction tools out of the box, that allow for changes to be deployed without downtime. Siebel customers that make best use of these technologies, have the opportunity to be very agile and reduce the time to market for their solutions.

Summary

In this article we’ve introduced the high level challenges of Siebel Integration that organisations  face. This prepares us for the next set of articles, where we’ll dig deeper, go through real world scenarios, consider solutions that are aligned to the principles introduced above, walk through the features of a Siebel integration framework, and address the following low level challenges.

- Reducing technical burden
- Dependency on external interfaces
- Working in disconnected environments
- Working within constraints of Siebel product
- Reduce scripting and hard coded references
- Improving code quality 

How to create a VBC without Script - XML Gateway


This article is a continuation of the Impossible Solutions Poll Results post.

If you have been following this blog, it probably dosnt need any further introduction.

This solution has been contributed by Michael Feng, a respected colleague, who dosnt know the meaning of impossible and is an all round nice guy.

[ Michael's solution ]

Key Points:

  • Using XML Gateway Business Service to serve the VBC
  • Using Business Integration Manager (Server Request) as Transport Protocol
  • Create your own workflow to deal with the logic


Architecture:

  • VBC trigger XML Gateway: Init(), Query(), etc
    XML Gateway generates xml files corresponding to the command. Eg. It generates xml file

    <siebel-xmlext-fields-req>
    <buscomp id="1">Contact</buscomp>
    </siebel-xmlext-fields-req>


  • Matching Init() command
  • XML Gateway triggers Business Integration Manager to invoke SendReceive() method

  • Business Integration Manager sends the xml files generated by XML Gateway to Workflow

  • Workflow gets the xml file and passes it to external application like MQ Series, MSMQ, HTTP Web Application or processes it inside the Siebel

  • Workflow gets the result xml file from external application or Siebel Application and passes it back to Business Integration Manager (BIM)

  • BIM receives the result xml file and passes back to XML Gateway to populate the VBC



Points of configuration:

  • Create a BC of Class CSSBCVExtern

  • Configure the above BC with following user properties
    Service Name: XML Gateway
    Service Parameters: Transport=EAI Business Integration Manager (Server
    Request);ProcessName=<Name of WF>;

  • Create a process property as type of binary/string. Set the default to <Value>. It will hold the xml file generated by XML Gateway

  • Create a process property as type of binary and named <Value>. It will pass back to BIM and XML Gateway to populate the VBC

  • Analyse the xml file generated by XML Gateway to determine what action to be taken. (Query, Insert…)

  • Use XSLT to transform the result xml file to the format XML Gateway needs to populate the VBC



Sample Workflow Design


Workflow Process Properties



StepTypeMethodBusiness Service
SaveIncomingXMLBusiness ServiceSendEAI File Transport
Input ArgumentTypeValueProperty name
<Value>Process PropertyIncomingXML
FileNameLiteralC:\XMLGateway.txt
AppendToFileLiteralTrue






StepTypeMethodBusiness Service
Analyse Incoming XMLBusiness ServiceEchoWorkflow Utilities
Output ArgumentTypeValueProperty name
CheckPointExpressionInStr([&IncomingXML],"fields-req")







StepTypeMethodBusiness Service
Is Init Request?Decision Point
BranchConditionExpression
Is InitCondition(CheckPoint Greater Than('0'))
Not InitDefault




StepTypeMethodBusiness Service
Get Init XML ResponseBusiness ServiceReceiveEAI File Transport
Input ArgumentTypeValueProperty name
FileNameLiteralC:\TEMP\TestVBCInit.xml
Output ArgumentTypeValueArgument name
<Value>Output Argument<Value>






StepTypeMethodBusiness Service
Analyse Incoming Query XMLBusiness ServiceEchoWorkflow Utilities
Output ArgumentTypeValueProperty name
CheckPointExpressionInStr([&IncomingXML], "query-req")







StepTypeMethodBusiness Service
Is Query Request?Decision Point
BranchConditionExpression
Is QueryCondition(CheckPoint Greater Than('0'))
Not QueryDefault




StepTypeMethodBusiness Service
Get Query XML ResponseBusiness ServiceReceiveEAI File Transport
Input ArgumentTypeValueProperty name
FileNameLiteralC:\TEMP\TestVBCQuery.xml
Output ArgumentTypeValueArgument name
<Value>Output Argument<Value>


TestVBCQuery.xml

<?xml version="1.0" encoding="UTF-8" ?>
<siebel-xmlext-query-ret>
<row>
<value field="Title">Mr.</value>
<value field="First Name">Sara</value>
<value field="Last Name">Chan</value>
</row>
</siebel-xmlext-query-ret>

TestVBCInit.xml

<?xml version="1.0" encoding="UTF-8"?>
<siebel-xmlext-fields-ret>
<support field="Last Name"/>
<support field="First Name"/>
<support field="Title"/>
</siebel-xmlext-fields-ret>


This solution provides a proof of concept for you to build upon, and therefore dosnt include the steps needed to send/recieve or transform your XMLs and there are more elegant ways of querying your XML for a string, but that is left for the reader to play with.

Working with Transports, XML and VBCs are probably one of the most difficult areas of Siebel to work with, but Michael has provided us with a nice foundation for any of us to take this further, and all without writing a line of code.

Format DTYPE_PHONE EAI phone challenge - Part 2




This will be the conclusion to our series on the DTYPE_PHONE phone challenge.

This solution will pick up where the last article left of from and I am assuming that you already have a WF and have queried your IO to get your message.

For added fun, this is our new beefed up XML message.

<phone>
<home>+610296480999
(00) 0000 0000</home>
<work>+610296480888
(00) 0000 0000</work>
<mobile>+610401123456
0000 000 000</mobile>
<voip>+610296480222
00 0000 0000</voip>
<mum>+610296480111
(00) 00 00 00 00</mum>
<dad>+610296480333
0000 0000</dad>
<brother>+610296480444
00 0000 0000</brother>
<sister>+610296480555
000000000</sister>
</phone>

We will use the technique in the first article to split the phone and pattern using XSLT, and also apply the phone formatting in the same transaction!

Heres the new XSLT that will do the magic for us.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:variable name="CRLF"><xsl:text>&#10;</xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/home"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/work"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/mobile"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/voip"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/mum"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/dad"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/brother"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/sister"/></xsl:call-template>
</xsl:template>
<xsl:template name="applyPhoneFormat">
<xsl:param name="dtypephone"/>
<xsl:param name="output"/>
<xsl:param name="num" select="substring-before($dtypephone, $CRLF)" />
<xsl:param name="pattern" select="substring-after($dtypephone, $CRLF)" />
<xsl:param name="ploop" select="string-length($pattern)" />
<xsl:param name="nloop" select="string-length($num)" />
<xsl:variable name="patterncursor" select="substring($pattern, $ploop , 1 )" />
<xsl:variable name="numbercursor" select="substring($num, $nloop , 1 )" />
<xsl:choose>
<xsl:when test="$ploop > 0">
<xsl:choose>
<xsl:when test="$patterncursor = 0">
<xsl:call-template name="applyPhoneFormat">
<xsl:with-param name="dtypephone" select="$dtypephone"/>
<xsl:with-param name="ploop" select="$ploop - 1"/>
<xsl:with-param name="nloop" select="$nloop - 1"/>
<xsl:with-param name="output" select="concat($numbercursor,$output)" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="applyPhoneFormat">
<xsl:with-param name="dtypephone" select="$dtypephone"/>
<xsl:with-param name="ploop" select="$ploop - 1"/>
<xsl:with-param name="nloop" select="$nloop"/>
<xsl:with-param name="output" select="concat($patterncursor,$output)" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat($output,$CRLF)" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

To make this solution work, we needed to have cursors that loops through the phone pattern and build the phone string, but since there is no concept of looping in XSLT (we have the for-each, but that just iterates over the XML nodes, it dosnt do a custom for loop for us), i have used the next best thing, which is build a recursive template to give us the same effect.

I originally designed this solution 3 years ago, but sadly never kept a copy of it when i moved on. So the XSLT you see here is a re-write of the original.

Whenever we use a new technology in our environment, and especially when it uses loops, its prudent to do performance testing to ensure it runs as expected. When i did my testing on the original XSLT against the Xalan (Siebel's XSLT translator which uses the Xerces 1.1 parser) engine in version 7.5, i used a dummy XML with 100 phone numbers, and each phone number had between 8-10 characters for the phone number. When i analysed the logs, the transaction completed within a split millisecond.

This is only a proof of concept, and dosnt handle cases where the user enters the correct phone format, and the system needs to lookup the correct number format, and in the above solution i've chopped of the country code.

The XSLT above hasnt been performance tested, so before you use it in your environment take sometime to analyse the XSLT logic to ensure it meets your needs, and test its performance in your environment, you should be quite surprised by the Xalan engines efficiency.

In the example above, i've included the special formatting characters, but Alex from Siebel Essentials has requested that i show how to send only the numeric phone number.

This was achieved in the first article in the series, by using XSLT to split the phone and pattern portions.

To apply the correct format with spacing, but not non numeric characters such as (,),/,- etc. In other words, we are stripping off all the special characters and just applying the correct spacing.

To do this we just need to modify our XSLT a little.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:variable name="CRLF"><xsl:text>&#10;</xsl:text></xsl:variable>
<xsl:variable name="SP"><xsl:text>&#32;</xsl:text></xsl:variable>
<xsl:template match="/">
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/home"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/work"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/mobile"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/voip"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/mum"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/dad"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/brother"/></xsl:call-template>
<xsl:call-template name="applyPhoneFormat"><xsl:with-param name="dtypephone" select="phone/sister"/></xsl:call-template>
</xsl:template>

<xsl:template name="applyPhoneFormat">
<xsl:param name="dtypephone"/>
<xsl:param name="output"/>
<xsl:param name="num" select="substring-before($dtypephone, $CRLF)" />
<xsl:param name="pattern" select="substring-after($dtypephone, $CRLF)" />
<xsl:param name="ploop" select="string-length($pattern)" />
<xsl:param name="nloop" select="string-length($num)" />

<xsl:variable name="patterncursor" select="substring($pattern, $ploop , 1 )" />
<xsl:variable name="numbercursor" select="substring($num, $nloop , 1 )" />

<xsl:choose>
<xsl:when test="$ploop > 0">
<xsl:choose>
<xsl:when test="$patterncursor = 0">
<xsl:call-template name="applyPhoneFormat">
<xsl:with-param name="dtypephone" select="$dtypephone"/>
<xsl:with-param name="ploop" select="$ploop - 1"/>
<xsl:with-param name="nloop" select="$nloop - 1"/>
<xsl:with-param name="output" select="concat($numbercursor,$output)" />
</xsl:call-template>
</xsl:when>
<xsl:when test="$patterncursor = $SP">
<xsl:call-template name="applyPhoneFormat">
<xsl:with-param name="dtypephone" select="$dtypephone"/>
<xsl:with-param name="ploop" select="$ploop - 1"/>
<xsl:with-param name="nloop" select="$nloop"/>
<xsl:with-param name="output" select="concat($patterncursor,$output)" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="applyPhoneFormat">
<xsl:with-param name="dtypephone" select="$dtypephone"/>
<xsl:with-param name="ploop" select="$ploop - 1"/>
<xsl:with-param name="nloop" select="$nloop"/>
<xsl:with-param name="output" select="$output" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat($output,$CRLF)" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

Before we leave this topic, i want to touch on the original challenge, which was to retrieve the phone number portion from the DTYPE_PHONE field without using any scripting, and although we've achieved that, plus a whole lot more. Some could argue that the XSLT solution is a form of scripting, but without all the negative associations.

Its not quite black or white, so i'll leave that for you to think about.

Stay tuned for more Impossible solutions!


Format DTYPE_PHONE EAI phone challenge - Part 1




This is the followup article to Strip off Number format in DTYPE_PHONE field (No Script) and also Scriptless Siebel Challenge: Phone Numbers in EAI from Siebel Essentials.

I first came across this problem 3 years ago in a production environment. There was a complaint, that the phone numbers that we were sending across to the external system had inconsistent number formatting.

In Siebel, the phone formatting is controlled by the PHONE_FORMAT LOV. If the user enters in the correct number format, the system will store the number in a compressed format, and use the PHONE_FORMAT lookup to apply to the UI.

However if the user enters in a phone number different to the LOV, the system stores the phone number + the new format string.

The root cause of our problem 3 years ago, was that we had an EIM process that created new and updated existing records. Any phone numbers that were updated by EIM, took the literal value, and not the compressed value that the UI stored.

Example
02 1234 4567 // value from EIM
+611234567 // value from UI using default LOV format
+61021234567|(00) 0000 0000 //value with custom format

All these values could exist simultaneously in the same database column, because the physical type is a varchar(40).

We raised the problem with our TAM, and were told that no declarative means exists and needed to use a custom business service.

The solution that i'm about to share, involves no scripting, and can be applied to all sorts of string challenges.

It nicely meets all of Alex's pre-requisites for a non-scripting solution, ie. It dosnt introduce any custom code to the Applets, Application, BCs, BSs or even use obscure user properties.

Here's my thoughts on this challenge

The DTYPE_PHONE field is a proprietry Siebel format, so there are no standard string functions that will single handedly apply the formatting, there are no documented Siebel user properties that will apply the formatting for us, and to add more complexity the challenge, the user may not want the country codes to be sent across.

Heres how we solve it
Conceptully we need to implement a custom string function that does the following

  1. Split the TYPE_PHONE into a number and a pattern string
  2. Have a cursor that iterates through the pattern string

    • If character = 0 then and place the corresponding position on the number string into an Output property
    • Otherwise place the non numeric character from the pattern string into an Output property

  3. Loop through pattern string and concatenate the Output string until it has finished

I've highlighted key design concepts to solve this problem, now since we cannot use any scripting, the above concept seems impossible, but thats what we are all about.

In the next post i will provide the actual technical solution.


Strip off Number format in DTYPE_PHONE field (No Script)




There is an interesting post Scriptless Siebel - A Challenge over at Alex's Siebel Essentials blog.

One of his readers posts this challenge.

  • Scenario
    "We were sending a Contact Record to external system via HTTP.That contact Record had a field called Work Phone of Dtype_Phone.I guess you might be aware that Dtype_Phones are stored along with Format string which consists of zeroes, if user enterd some space in Phone number like - If User Enters +44123 456 789 then it will be stored in database as -
    +44123456789CRLF000 000 000.

    Now I was using a WF which use EAI Siebel adapter to get Siebel Message. Then I would convert that into xml and send to external system.External system said to remove those zeroes and send.Though there is a delimitter in form of new line between zeroes and actual number, I was unable to do this task in config."
If i am understanding the requirement correctly, it should be quite simple to transform the message in WF, before sending it to the external system.

Assuming our XML looks like this.

<phone>+44123456789
000 000 000</phone>
//Note: there this a real CRLF character between the phone and the phone format

We can use the following XSLT to split the field to return us just the phone number without the format.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="CRLF">&#10;
<xsl:variable name="num" select="substring-before(phone, $CRLF)" />
<xsl:variable name="pattern" select="substring-after(phone, $CRLF)" />
phone: <xsl:value-of select="$num" /> <xsl:value-of select="$CRLF"/>
pattern: <xsl:value-of select="$pattern" /> <xsl:value-of select="$CRLF"/>
</xsl:template>
</xsl:stylesheet>


However, i think we can make it better, so i would like to propose a new challenge.

Following the above scenario, get the DTYPE_PHONE value, extrapolate the pattern and apply it to the phone number on the fly before sending out to the external system (this of course must be done without any sort of custom script).

eg. The system must take this format "000 000 000" and apply it to "+44123456789" to output "+44 123 456 789"

Stay tuned to see the solution to the problem.