File integration
Learning objective
In this lesson, you will learn to:
- Create a CSV file that contains the contact details of some people.
- Write a script to parse and format the details to a message.
- Persist the message to the business model through a channel.
- Investigate how a service interacts with the file system.
- Configure a channel to use a service and interface to process and parse the message.
Creating a CSV message
Let's create a new message called training:PersonCSV
that stores the first name, last name, business phone number, home phone number, and email address of a person. The person's details are stored in a child message called rows
. A default mapping is applied to the training:PersonCSV
message. The default mapping specifies that the file has a header row and sets other default options. It looks similar to the following:
CVS message mapping options are described in detail in the Model Description Language Reference at CSVMapping (nexj.com)
Learning activity
To create the CSV message:
In the Integration layer, select the Messages tab.
Right-click the list area inside the tab and select New Message. The New Message dialog opens.
Name the message
training:PersonCSV
.Click Finish.
Do one of the following:
Enter or drag and drop the following code on the Source tab.
XML<Message format="CSV"> <CSVMapping/> <Parts> <Message maxCount="0" name="rows"> <Parts> <Value name="firstName" type="string"/> <Value name="lastName" type="string"/> <Value name="businessPhone" type="string"/> <Value name="homePhone" type="string"/> <Value name="email" type="string"/> </Parts> </Message> </Parts> </Message>
Configure the following settings:
In the Overview tab, select the
training:PersonCSV
root node.Set the Format to CSV.
Click Create Mapping. Do not change any of the CSV Mapping default values.
Right-click the
training:PersonCSV
root node, select Insert Child > Message, and specify the following details:Name:
rows
maxCount:
0
Right-click the
rows
node and select Insert Child > Value for each of the fields listed below. For each of these fields, set the name property and set the Type toString
.firstName
lastName
businessPhone
homePhone
email
10. Save your work.
Formatting and parsing the message
Using a scratchpad and Scheme script, you will create an unformatted message, format it, and then parse it into a defined message format. The first statement in the script creates two messages in the rows
collection and specifies values for the fields. The second statement converts the message into its wire format, a CSV string. The third statement parses the CSV string into the specified message format.
Learning activity
To format and parse the message:
Enter the following code in a scratchpad.
SCHEME; Unformatted original message (define om (message (: :class "training:PersonCSV") (: rows (collection (message (: firstName "Joe") (: lastName "Test") (: homePhone "(416) 555-1212") ) (message (: firstName "Jane") (: lastName "Doe") (: email "jane.doe@nexj.com") ) ) ) ) ) ; Formatted message (define fm (format-message om) ) ; Parsed message (define pm (parse-message fm "training:PersonCSV") )
Run your server.
In the Console, execute each of the statements from the scratchpad individually and review the results.
Execute the statement
(display fm)
to see the formatted message, and(display pm)
to see the parsed message.
Creating a service, channel, and interface for the message
You now need to create a channel that receives the incoming training:PersonCSV
message. The channel is bound to a service that processes the message using an interface that validates and parses it.
Learning activity
To create a new service called training:CSVImportService
:
In the Integration layer, select the Services tab.
Right-click the list area inside the tab and select New Service.
In the New Service dialog, name the service
training:CSVImportService
.Click Finish. The new service you created opens in an editor.
To create a new channel called training:CSVImportChannel
and bind the training:CSVImportService
to the channel:
In the Channels tab, right-click the list area inside the tab and select New Channel.
In the New Channel dialog, specify the following values:
Name:
training:CSVImportChannel
Type:
File
Click Finish. The channel opens in an editor.
Do one of the following:
Enter or drag and drop the following XML on the Source tab:
XML<File> <ServiceBindings> <ServiceBinding service="training:CSVImportService"/> </ServiceBindings> </File>
Configure the following settings:
In the Service Bindings tab, click the Add button . The new service binding is added to the list in the Service Bindings area.
Set
training:CSVImportService
as the Service.Leave the
Output
property blank.
Save your work.
To create a new interface called training:PersonCSVInterface
, format the interface as CSV, and set the training:PersonCSV
message as a request type:
In the Interfaces tab, right-click the list area inside the tab and select New Interface.
In the dialog, name the interface
training:PersonCSVInterface
.Click Finish. The interface opens in an editor.
Do one of the following:
Enter or drag and drop the following XML on the Source tab.
XML<Interface format="CSV"> <Requests> <Request message="training:PersonCSV"/> </Requests> </Interface>
Configure the following settings:
In the Format field, select CSV.
In the Requests area, click the Select button , add the
training:PersonCSV
message, and close the Select Messages dialog.
Save your work.
To set the interface and add a log to the service:
Open
training:CSVImportService
.Do one of the following:
Enter the XML code as follows, or drag and drop the XML on the Source tab.
XML<Service interface="training:PersonCSVInterface" layout="startX:133;startY:176;endX:400;endY:173"> <Log args="(this'rows)" id=""Incoming rows: {0}"" layout="x:240;y:176" level=""info"" name="log"/> </Service>
Configure the following settings:
In the Property Editor view, set the Interface to
training:PersonCSVInterface
.In the Palette, select Log and click a location on the line between the start and end of the service to place the log.
In the Property Editor view for the log, select the Parameters tab.
In the Level field, enter
"info"
.In the Id field, enter
"Incoming rows: {0}"
In the Arguments field, enter
(this'rows)
.
Save your work.
Adding the channel to the development environment
Connect the channel to the physical world by configuring a connection in your environment.
Learning activity
To add the channel to the development environment:
In the Deployment layer, select the Environments tab and double-click the Development environment to open it for editing.
In the Channel Connections tab, click the Select Channel Connections button and add
training:CSVImportChannel
.In the Channel Connections area, select the new channel and set the following properties. If necessary, substitute paths that are more appropriate to your system.
Incoming Directory:
C:\temp\CSVImport\in
Processed Directory:
C:\temp\CSVImport\processed
Temporary Directory:
C:\temp\CSVImport\temp
Outgoing Directory:
C:\temp\CSVImport\out
Interval:
5000
Incoming Message File Age:
5000
As an alternative to setting your properties individually, you can paste the following code into your environment file:
XML<FileConnection age="5000" channel="training:CSVImportChannel" incomingDirectory="C:\temp\CSVImport\in" interval="5000" outgoingDirectory="C:\temp\CSVImport\out" processedDirectory="C:\temp\CSVImport\processed" temporaryDirectory="C:\temp\CSVImport\temp"/>
In your computer's file system, create the corresponding folders. This is required because the folders specified in the channel connection must exist on your computer in order for the channel to operate correctly.
C:\temp\CSVImport\in
C:\temp\CSVImport\processed
C:\temp\CSVImport\temp
C:\temp\CSVImport\out
Save your work.
Testing the message processing
In this learning activity, you will test the message processing.
Learning activity
To test the message processing:
In your computer's file system, create a new file called
test.csv
and add the following text into it. Do not create this file in any of the folders you specified for the channel connection.TEXTfirstName,lastName,businessPhone,homePhone,email Joe,Test,,(416) 555-1212 Jane,Doe,,,jane.doe@nexj.com
Run the Server Console.
Once the Console has launched, copy the
test.csv
file to the Incoming Directory that you created in your computer's file system.
In the Console view, you should see processing information similar to the following:TEXTIncoming rows: #<[TO<, @1762367942>( lastName="Test", firstName="Joe", homePhone="(416) 555-1212" ), TO<, @2023541770>( lastName="Doe", firstName="Jane", email="jane.doe@nexj.com" )]>
In your computer's file system, inspect the
CSVImport
folder and its subdirectories. Thetest.csv
file was moved from thein
folder to theprocessed
folder, and the file now has a time stamp appended to its name.Stop the Scheme Console by clicking the Terminate button .
Persisting the message
Before persisting the data, you'll need to add some script steps to the service to persist the Person and Telcom information through the business model.
Learning activity
First, you'll need to add a user to the channel so you can do some data work. If the channel does not have a user associated with it, the message will be received and processed but the service fails when creating the Person
instances.
Open your environment file.
In the Channels tab, open
training:CSVImportChannel
.In the Overview tab, set the Default User to
nexjsa
.Click the Save button in the toolbar.
To persist the data:
In the
training:CSVImportService
, add a script step to the service diagram. Place it after the log step.In the General tab of the Property Editor for the script step, set Name to
createPersons
and Caption toCreate person records
.In the Script tab, enter the following code:
SCHEME(logger'debug "=====> this: " this) (logger'debug "=====> rows: " (this'rows)) (for-each (lambda (row) (logger'debug "=====> row: " row) (let ((person (Person'new (: lastName (row'lastName)) (: firstName (row'firstName)))) ) (when (not (null? (row'email))) (EmailAddress'new (: name "Email") (: address (row'email)) (: type (read-instance TelcomType '() '(= name "Email") '())) (: entity person) ) ) (when (not (null? (row'homePhone))) (TelephoneNumber'new (: name "Home") (: address (row'homePhone)) (: type (read-instance TelcomType '() '(= name "Home") '())) (: entity person) ) ) ) ) (this'rows) )
Save your work.
The service diagram should display as follows:
To test the training:CSVImportService
:
Run the Server Console.
After the Console launches, copy the
test.csv
file to the Incoming Directory.
You should see activity in the Console view. The file is taken from the in folder and output to the processed folder. The file now has a date-modified string appended to the file name.Inspect the Console output to see how the framework persisted the
Person
andTelcom
objects.Stop the Server Console.
You can use the user interface at http://localhost:7080/training/ui/portal
to look up contacts with the last names of Test or Doe.
Alternately, you can use the REST API with:http://localhost:7080/training/json/Person?attributes=(firstName lastName)&where=(or (= lastName "Test") (= lastName "Doe"))