Your SlideShare is downloading. ×
  • Like
  • Save
Dev buchan leveraging
Upcoming SlideShare
Loading in...5

Thanks for flagging this SlideShare!

Oops! An error has occurred.


Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Dev buchan leveraging



Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads


Total Views
On SlideShare
From Embeds
Number of Embeds



Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

    No notes for slide


  • 1. © 2007 Wellesley Information Services. All rights reserved.LeveragingLotusScript forDatabaseConnectivityBill BuchanHADSL
  • 2. 2Why Are We Here?• What is the target audience? Lotus Notes developers who use server-based agents• What is this talk about? Lotus Notes is often perceived as a data “silo” … Difficult to get data into And difficult to get data out of … this is not the case This presentation explores a multitude of ways of interfacingNotes databases with enterprise relational databases
  • 3. 3Who Am I?• Bill Buchan• Dual Principal Certified Lotus Professional (PCLP) in v3,v4, v5, v6, v7• 10+ years senior development for Enterprise customers Learn from my pain!• 5+ years code auditing• CEO of HADSL Developing best-practice tools
  • 4. 4What We’ll Cover …• Overview• LSX• LS:DO• DCR• Wrap-up
  • 5. 5Overview• This session: Is mostly about code Lots of take-home code examples Is a deep-dive in terms of theory
  • 6. 6Connections: Overview• “Lotus Notes cannot share its data with otherdatabases” Absolutely not Support for this dates back over 10 years!• Multiple methods This presentation leads you through some of the morepopular ones Highlights the pros and cons of each
  • 7. 7Connections: Overview (cont.)LSX LS:DO DCR JNDI/XMLPerformance High Low Med HighODBC Connection Required No Yes Yes NoNative Client Required Yes No No YesPlatform Independent Yes Yes Yes YesLotusScript Only Yes Yes Yes NoSupported Yes No Yes YesRuns on Client Yes Yes Yes YesRuns on Server Yes Yes No Yes
  • 8. 8Tips: General• In all of these examples, I shall hard-code user namesand passwords for simplicity This is NOT a good production best practice! Use encryption keys, profile documents, etc., to soft-codethese in production• Any attempt by LotusScript to access data outside thecurrent database may result in error Error handling is therefore mandatory Logging of scheduled agents is mandatory
  • 9. 9What We’ll Cover …• Overview• LSX• LS:DO• DCR• Wrap-up
  • 10. 10Overview: LSX• LotusScript-based Such a small learning curve• Relies on native client support So you have to install your database client and/or drivers• Is fast This doesn’t have to use ODBC But ODBC is used for MS SQL and Access Remember, ODBC v2 doesn’t like Unicode This technology is used in the Lotus Enterprise Integrator Formerly “Notespump” Good for bulk transfer-style applications
  • 11. 11Methodology• We shall attempt to: Test this against a local Access database using ODBC Test this against an Oracle database• Our data looks like:• And for Access, we need an ODBC connection
  • 12. 12Demo: Read Table to Log• Let’s get a feel for what we are doing• In this demonstration, we will: Connect, using ODBC, to an Access database Collect all records in a CUSTOMERS table Pull ALL fields from all records Write all this information to a Notes log
  • 13. 13DemoDemoRead Table to Log
  • 14. 14Architecture Design Goals• When we write LSX applications, we should: Write as little code as possible Create comprehensive error handling Create logs of both success and failure Try not to hard-code the database structure Try and reuse and componentize After all, we might change databases later! Ensure that our top-level logic is: Focused on the business rules for data transfer Is maintainable After all, this will change!
  • 15. 15Architecture Design Overview• In order to access data, we must: Connect to the database provider And then connect to the data itself• Object-oriented LotusScript lends itself to this model We shall create a: baseClass: This handles logging baseConnectionClass: This handles the connection to thedata source baseConnection<DB>Class: These are database-specificclasses Operation classes These should NOT be database specific
  • 16. 16Architecture Design Results• This means that we separate: Logging Basic connection Operation• Thus, reusing lots of code• All database-specific code is held in a single library Can be easily “swapped” for another Platform and database differences can exist during ouroperations Test on the platform, version, and database that you willimplement on
  • 17. 17Class Inheritance and Code UseBaseClassBaseConnectionClassBaseConnectionOracleClassBaseConnectionODBCClassReadTableClassLogging, Error HandlingOperations ClassOracle-Specific CodeLogic for ConnectionCodeAgentODBC-Specific CodeExample agent uses aspecific databaseconnection and one ormore helper functionclasses
  • 18. 18Connecting to Oracle• Now, let’s try connecting to Oracle We need to: Install the Oracle client Connect it to the Oracle database server
  • 19. 19Some Oracle Tips• Setting up an Oracle server is not trivial Oracle is an enterprise-strength database system As big, complex, and difficult as a dozen mother-in-laws So give yourself time!• Some tips: The Connection string in Oracle looks like: CUSTOMERS_oracle02.marykirk.local This is: The name of the application — in our case “Customers” And then the network host address Either as a Domain Name System (DNS) host addressor as an Internet Protocol (IP) address
  • 20. 20More Oracle Tips• Try to use some Oracle tools to validate that you have: A proper connection Sufficient access to the application Sufficient access to the tables• Remember, you can use DCR to validate connections
  • 21. 21Network Architecture• If you run Lotus Connector (LC) LSX code on the server: The server must have: A connection to Oracle The Oracle Client software drivers• If you run LC LSX code on the Notes client: The client must have: A connection to Oracle The Oracle Client software• Installing Oracle Client on all workstations is not trivial! Consider using LC LSX on the servers only
  • 22. 22The Base Class• Our base classcontains all“Infrastructure”support, such as: Logging Error trappingClass baseClass‘ returns true if this class is validPublic Property Get Valid As Boolean‘ Our constructor. Sets up loggingSub new()‘ Class destructor ensures proper closure of LogSub delete()‘ Log a messagePublic Function logEvent(msg As String) As Integer‘ Handle run-time errorsPrivate Function raiseError() As StringEnd Class
  • 23. 23Class baseConnectorClass This class extends our BaseClass and adds the capability to open and close a connection Note that this is never used directly – and is overridden by our database-specific classes.‘ This provides the business logic framework for our database specific connection classesClass baseConnectorClass As BaseClass‘ Expose some propertiesPrivate Function getServer As StringPrivate Function getUserName As StringPrivate Function getPassword As StringPrivate Function getTable As StringPublic Function getSession As LCSessionPublic Function getConnection As LCConnection The base constructor for this class. Note that it doesnt actually do any connection work - it just sets up the base variablesSub new(srv As String, un As String, pw As String, tb As String), baseClass()‘ And the destructor. This ensures that the connection object is closedSub delete()End Class
  • 24. 24Class baseODBCConnectorClass• All of our business logic is held in baseConnectorClass We need to put the database-specific code in only this class In this case, it is all implemented in the constructor• If we change the business logic later on: We have to change only baseConnectorClass This class extends our BaseConnectorClass and adds the‘ capabilty to open and close an ODBC ConnectionClass baseODBCConnectorClass As BaseConnectorClass‘ Supply a new constructor for this classSub new(srv As String, un As String, pw As String, tb As String)End sub
  • 25. 25Insulating Database Connections from Business Logic• One main goal is to insulate our database-specificconnection information from our business logic It makes it easier to switch databases in the future, ifnecessary• In this database, I hold all database-specific informationin a profile documentSet docProfile = dbThis.GetProfileDocument("Profile")Dim Connection As VariantSelect Case docProfile.Database(0)Case "ODBC"Set connection = New baseODBCConnectorClass _(docProfile.System(0), "", "", "")Case "Oracle"Set connection = New baseOracleConnectorClass _(docProfile.System(0), docProfile.UserName(0), docProfile.Password(0), docProfile.MetaData(0))End Select
  • 26. 26Class fieldClass• fieldClass Helps us define whichfields we want returnedfrom our data object Used to extract dataClass FieldClass‘ Our two members – a name and a fieldPublic FieldName As StringPublic Field As LCField‘ get the value of this fieldProperty Get Value As Variant‘ Construct this field classSub new(fName As String, F As LCField)End Class
  • 27. 27Class baseODBCConnectorClass — Constructor• This pseudo-codeshows the stepstowards connectingto our LC LSXtarget data server• Differences from anODBC connection The connection tokenis “oracle8” The username andpassword arespecifiedSet Me.lc_Session = New LCSession()If ( Me.lc_Session.Status <> LCSUCCESS ) Then‘ Bale out of the function…‘ Check to see that the odbc2 LSX Support is available.If (lc_Session.LookupConnector ("odbc2")) Then…‘ Now set up our ConnectionSet me.lc_Connection = New LCConnection ( "odbc2" )‘ Set up our data source nameMe.lc_Connection.Server = Me.getServer()‘ And finally connectMe.lc_Connection.Connect‘ Check to see that the connection has workedIf (Me.lc_Connection.isConnected = False) Then…
  • 28. 28ReadTableClass• ReadTableClass Allows us to read the resultof an SQL Query Returns each table row as aLIST of FieldClass itemsClass ReadTableClass As baseClass‘ Our constructor. Pass in our‘ database connection objectSub new(newConn As Variant) set up our read operation‘ by passing in an SQL statemementPublic Function getRecords( _strSelection As String) As Long‘ Call this till it returns false, return‘ each row of the table as a list‘ of resulting fieldsPublic Function getNextRecord( _index As Long, returnedFields _List As FieldClass) As IntegerEnd Class
  • 29. 29Using ReadTableClass• Our controlling code Set up a databaseconnection Create a ReadTableClassobject Check to see whetherit’s valid Run some SQL Process the results‘ set up our database connectionSet connection = New _baseODBCConnectorClass( _“CUSTOMERS”, "", "", "")‘ set up our ReadTableClass objectDim rc As New ReadTableClass(connection)‘ Check to see its validIf Not rc.Valid Then…‘ Do our SQL thingIf (rc.getRecords( _"SELECT * from CUSTOMERS")) ThenWhile rc.getNextRecord(index, returnedValues)…
  • 30. 30Processing the Results from ReadTableClass• It’s a case of: Retrieving each ROW of data Iterating through the LIST offieldClass items andprocessing them• Agent “Read Tables to Log”just prints themForall thisF In returnedValuesCall rc.logEvent(" " + thisF.fieldName + Space(30-Len(thisF.fieldName)) + _Chr(9) +" [" + Cstr(thisF.Field.DataType) + "]" + Chr(9) + _Implode(thisF.Field.Text, ", "))End Forall------------------ New Record retrieved ----------ID 1Name LotusContact Mike R.hodinAddress Lotus HouseCity WestfordState MAZIP 90210Country USAdateFirstContact 01/01/1990 00:00:00CreditLimit 5000000.0000Employees 1000…
  • 31. 31Demo: Read Table to Documents• Let’s use the same underlying code: Synchronize this information with Notes data Use the ID field to match up SQL entries with Notes entries For simplicity, we shall just overwrite the Notes data withthe SQL data Note we are not requesting specific fields We write ALL field information to a Notes database We use the same field name in SQL and Notes This might not be good in production Consider pre-fixing the Notes field names to avoidname collisions
  • 32. 32DemoDemoRead Tableto Documents
  • 33. 33Let’s Write to SQL• In this case, we need to define which fields we shallupdate This information is used to define: The SQL target field Which field in Notes we pull data from The data type This had better match the SQL data type! Again, we want the operations class to do all the hard work!
  • 34. 34insertTablesClass• Our class allows us to: Define a series of fieldnames we shall writedata to Pass a variant array ofvalues (in the same orderas our fields wereappended)• This is still pretty hardwork We have to track allfields, etc.Class InsertTableClass As baseClass Our constructor. Pass in the Connector.Sub new(newConn As Variant) Call this for each field we wish to append,‘ passing in a name and a typePublic Function appendField( _fieldName As String, fieldType As Long) _As Integer Commit to inserting these records. This returns the number of records successfully‘ inserted, NOT true or false.Public Function insertRecord( _values() As Variant) As IntegerEnd Class
  • 35. 35insertFieldClass• insertFieldClass Helps define thefields, field types,and values totransfer from theNotes document tothe SQL table For simplicity, in thiscode instance we areassuming that thefield names areidentical in Notesand SQLClass insertFieldClass‘ Our constructor. Pass in our InsertTableClassSub new(newIT As Variant)‘ Append a field name and an LSX field typePublic Function appendField( _strName As String, Ltype As Long) As Integer‘ Call this once you have set all your field namesPublic Function setUpFields() As Integer Using our fieldList, save the field values‘ from this document to to our InsertTableClassPublic Function saveFieldsFromDocument( _doc As NotesDocument) As IntegerEnd Class
  • 36. 36insertTableClass and insertFieldClass Usage• Define a newInsertTableClass• Define a newInsertFieldClass• Define our fields• Freeze the definition• Push the data‘ Create a new InsertTable ClassDim it As New InsertTableClass(Connection)‘ And create a InsertFieldClass, associating‘ it with our table Class.Dim ic As New InsertFieldClass(IT)‘ Define the fieldsCall ic.appendField("ID", LCTYPE_NUMERIC)Call ic.appendField("Name", LCTYPE_TEXT)…‘ And “freeze” it there.Call ic. setUpFields()‘ And for one or more Documents, push the‘ Data across.Call ic.saveFieldsFromDocument(doc)
  • 37. 37DemoDemoInsert Rowsinto SQL
  • 38. 38Performance• Creating LCField items is expensive We define our LCFields before inserting data Instead of creating new LCField items within the loop foreach iteration, we create them ONCE outside the loop andreuse them Adds slightly to the complexity Hence the requirement for insertFieldsClass
  • 39. 39What We’ll Cover …• Overview• LSX• LS:DO• DCR• Wrap-up
  • 40. 40Introducing LotusScript Data Object (LS:DO)• LS:DO was the first data interface And is reportedly no longer supported You may find some code that still relies on this• LS:DO uses ODBC v2 drivers to access data You cannot access Unicode data This was introduced in ODBC v3.5 The client must have an ODBC definition for the target datasource on his machine, if you are running client-based code• Let’s dive straight into a demo …
  • 41. 41DemoDemoRead TableDefinition
  • 42. 42Using LS:DO• Create a new connection• Create a query and link it to ourconnection• Create a result set and connect itto our query• Set the SQL query• Execute the queryConst SQL_TABLE = "CUSTOMERS"Const SQL_QUERY ="SELECT * FROM CUSTOMERS"Set Connection = New ODBCConnectionConnection.ConnectTo(SQL_TABLE)If Not Connection.IsConnected Then…Dim Query As New ODBCQuerySet Query.Connection = ConnectionDim Result As New ODBCResultSetSet Result.Query = QueryQuery.SQL = SQL_QUERYResult.Execute
  • 43. 43LS:DO Result Set Processing• The ODBCResultSet Object now contains all the results You can extract field information You can extract actual values This code extracts field name and size informationIf Not Result.IsResultSetAvailable ThenMessagebox "I failed to get results from SQL Query: “ + _SQL_QUERY, 48, "Failed to get Results"Exit SubEnd IfDim fields List As StringDim i As IntegerFor i = 1 To Result.NumColumnsPrint "Field: " + padString( result.FieldName(i), 30) + _"Size: " + padString(Cstr(Result.FieldSize(i)), 5)fields(result.FieldName(i)) = result.FieldName(i)Next
  • 44. 44LS:DO Result Set Processing (cont.)• To extract the result rows themselves, use: Result.getNextRow Result.IsEndOfDataID 1Name LotusContact Mike R.hodinAddress Lotus HouseCity WestfordState MAZIP 90210Country USAdateFirstContact 01/01/1990CreditLimit 5000000Employees 1000While Not result.IsEndOfDataForall thisField In fieldsPrint " " & padString( "" + thisField, 30 ) & Chr(9) & Result.GetValue(thisField)End ForallCall Result.NextRow()Wend
  • 45. 45LS:DO Tips• LS:DO supports transaction processing You could — if your SQL data source allowed — switch onTransaction mode odbcConnection.IsSupported(DB_SUPP_TRANSACTIONS) You could then perform multiple updates Commit them all at once odbcConnection.CommitTransactions
  • 46. 46LS:DO Summary• LS:DO was a fairly simple, robust ODBC connection You might have some code that relies on it• I would advise you to: Identify any code that relies on LS:DO Refactor that code to use LSX
  • 47. 47What We’ll Cover …• Overview• LSX• LS:DO• DCR• Wrap-up
  • 48. 48Introducing DCR• Data Connection Resources (DCR) New in Domino 6 Allows you to perform real-time, user-based SQL databaseaccess Very useful for front-end applications• However: It requires constant access to the target database It requires Domino Enterprise Connection Services (DECS) Running on the server on which your application is hosted It pools all SQL database access via the DECS server
  • 49. 49Create a New Shared Resource — Data Connection• Set a name and alias• Set the data connection type• Enter username and password, if required• Choose the data source• And choose the object• Use Browse metadatato validate the connection
  • 50. 50Link the Data Source to Your Form• On the Form Properties — advanced tab, click Browse Choose the data connection and the metadata object
  • 51. 51Link the Fields to the Data• On the field properties: Check “External data source” At the bottom, use the Browsebutton to select the data source,metadata• One field needs to be defined asthe key field• Remember to check “Store datalocally” if you want to see thisdata on views!
  • 52. 52DCR: What Would I Use It For?• Very useful for: Applications that are permanently connected Applications that require instant lookup of external data• You could use Notes information and … Perform lookups to populate the document Update status information on user request
  • 53. 53Form Manipulation• Bear in mind that all this logic is held on the Formdesign element You could use one Form to populate/refresh data And allow users to work another Form Which just displays the data on the document
  • 54. 54Demo: DCR• In this demo, I will: Demonstrate data being updated in Notes and pushed to SQL Demonstrate data being updated in SQL and pushed to Notes Show you the DCR common element, as well as the Fielddefinition
  • 55. 55DemoDemoDCR demo
  • 56. 56What We’ll Cover …• Overview• LSX• LS:DO• DCR• Wrap-up
  • 57. 57Resources• Constantin Florea, Notes and Domino Connectivity: ACollection of Examples (IBM Redpaper, March 2001). Check out the abstract here:• Brian Benz and Rocky Oliver, Lotus Notes and Domino 6Programming Bible (Wiley, 2003).
  • 58. 58Resources (cont.)• Object-Oriented LotusScript:!OpenDocument• The Notes FAQ!• Notes.Net (of course)
  • 59. 597 Key Points to Take Home• Domino can easily interact with other data sources• LS:DO, whilst powerful and easy to use – is no longersupported Consider refactoring this• LSX performs bulk updates between Domino and otherdata sources Simple, fast, efficient• DCR allows real-time update in user context And centralizes data lookup via the server
  • 60. 607 Key Points to Take Home (cont.)• Consider that the target data source will change• Logging and error trapping Mandatory Ensure that you know of issues before your users Monitor this interface• This interface code will change often Write for maintainability!
  • 61. 61Your Turn!How to contact me:Bill