Lesson 3 : Creating a Customer entity

 

The Plan

 

  • Getting to know our working environment.
  • Building an adapter to create a customer entity.
  • Making a document to validate the input.
  • Create a table in the database via the Ibis console.

To test your adapter, we need access to a HTTP-client like Postman, and your personal version of the framework. When you don’t have credentials yet please ask an admin to email you a password and an Ibis instance name.

What’s that? An Ibis

In an Ibis you have different configurations, which in turn consist of one or more adapters. Each adapter has three base components : A sender, the pipes in a pipeline, and a receiver.

The receiver handles the incoming message that triggers the pipeline. You could think of situations when a message comes in, when somewhere a modification has taken place, when in a database there was a change, or a certain time interval that is completed.

Then there’s a series of pipes within the pipeline. They actually manipulate the incoming message, transformation, modification, anything can happen. Java-code is doing the powerlifting here, although we write our code in xml.

At the end of a pipeline you have the sender, who sends our modified message to yet another component. One could think of insertion of the transformed data into a database.

 

Files

 

 

Create this file structure in your editor, and add the following files and directories. The actual adapter resides in the file ConfigurationCreateCustomer.xml ; our process consists of sending a piece of xml that needs to be validated against a template input.xsd ; Our Ibis needs one Configuration.xml which functions as a container for all our adapters. When the app launches, this file is consulted to see which adapters there are.

You can grab a copy of klant.xsd here but when you read the next piece you can give it a go on your own.

 

 

 

Planning

As developers we’re very greedy to start coding at this point, cause we know what we want to do. So why wait any longer? One sound argument for doing some more planning is that we have to consider our datamodel at this point. Later, when we have 10000 customers in our db, we could regret it that we made the postal code optional. But that is dependent of your specific situation. One should discuss the datamodel in the development team and stick to it throughout the project.

So have a look at this table : We have a source file that we want to place in our destination, the customers table in the db. For now our source file is an xml but the IAF framework can handle other inputs also. We’ll come back to this later on.

 

 

Destination: table customers Source
Element Level M/O Type Path Element M/O Type Condition
ClientNr 1 /Klant/ Klantnummer
Initials 1 O /Klant/ Voorletters
FirstName 1 O /Klant/ Voornaam
LastName 1 /Klant/ Achternaam
Title 1 O /Klant/ Titel
Street 1 O /Klant/ Straat
Postalcode 1 /Klant/ Postcode
HouseNr 1 O /Klant/ Huisnummer
Addition 1 O /Klant/ Huisnummer2
City 1 O /Klant/ Plaats
CreationDate 1 O /Klant/ $Systemdate

table sql to source xml; note O stands for optional

 

A possible xml input file would look like this. We only have to make sure that this is valid. Therefore we will must construct an xsd validation file.

<?xml version="1.0" encoding="UTF-8"?>
<Klant>
    <Klantnummer>2</Klantnummer>
    <Voorletters>A</Voorletters>
    <Voornaam>Arend</Voornaam>
    <Achternaam>Arendse</Achternaam>
    <Titel> </Titel>
    <Straat>Arendshof</Straat>
    <Postcode>1234 AA</Postcode>
    <Huisnummer>20</Huisnummer>
    <Huisnummer2></Huisnummer2>
    <Plaats>Arnhem</Plaats>
</Klant>

We now have to create a Configuration.xml. For now just grab the contents, and get some more explanation at another time. Make sure to fill in your own Ibis name as the name of your configuration.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration [
    <!ENTITY CreateCustomer SYSTEM "ConfigurationCreateCustomer.xml">
     ]>
<configuration name="YOUR CONFIGNAME HERE">
    <jmsRealms>
        <jmsRealm realmName="jdbc" datasourceName="jdbc/${instance.name.lc}" />
    </jmsRealms>
    &CreateCustomer;
</configuration>

 

 

 

Question Time

 

Copy the setup from below and start building Klant.xsd in the editor. Use the mapping table above as a  reference.

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="Klant">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Klantnummer">
                    <xs:simpleType>
                        <xs:restriction base="xs:positiveInteger">
                            <xs:totalDigits value="10" />
                        </xs:restriction>
                    </xs:simpleType>
                </xs:element>
              
              ........... try to complete the rest of Klant.xsd here ...................
              
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

 

 

 

Through the pipeline !

 

 

 

Let’s start coding!

STEP 1   First we have to create a database table for our virtual customers. Open up the Ibis console by extending your Ibis url with “/iaf/gui/”, so that you have something like http://myibis4education/iaf/gui . Now find the tab “jdbc” and select the option “Execute  Query”.

Now create a table with the following columns : initialcode, postalcode, housenr, creationdate, clientnr, city, lastname, addition, firstname, title, street. Make ClientNr and HouseNr Int, CreationDate Date and all the other entries of type VARCHAR. Now look at the table and see which values must be included in the request.  When you have done this successfully you can browse your table at the tab “Browse Tables”. Try this first on your own but copy the necessary sql here when necessary.


`An sql query from the console.

STEP 2  Now in the editor you can open up Configuration.xml. This file has a fixed structure where entities are references to your individual adapters. In the next lesson, you will have to insert the names of the other adapters in this file.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration [
    <!ENTITY CreateCustomer SYSTEM "ConfigurationCreateCustomer.xml"> ]>
<configuration name="YOUR CONFIGNAME HERE">
    <jmsRealms>
        <jmsRealm realmName="jdbc" datasourceName="jdbc/${instance.name.lc}" />
    </jmsRealms>
    &CreateCustomer;
</configuration>

STEP 3  Now open up ConfigurationCreateCustomer.xml ; First we make the basic structure of an module, adapter, a receiver and a listener inside it. The receiver is the part where we tell the framework where to find its input. Accordingly the system will listen for messages there. For now we will choose for an ApiListener that sits in a GenericReceiver. That means that our customer-creating message will come in via http, so we need to specify what Content-type to expect, which http-method that is, and at which url-endpoint this will be.

The rule for this url is as follows: Location of frontend + “/api/” + {yourname} + {possible requestparameters} .  For example http://myibis4education/api/createcustomer or http://myibis4education/api/getcustomer/123

<?xml version='1.0' encoding='UTF-8'?>
<module>
    <adapter name="CreateCustomer" description="Adapter to create customers in a backend system.">
        <receiver className="nl.nn.adapterframework.receivers.GenericReceiver" name="CreateCustomer_Receiver">
            <listener className="nl.nn.adapterframework.http.rest.ApiListener"  uriPattern="createcustomer" 
                     method="POST" 
                     consumes="XML" 
                     produces="XML"/>
        </receiver>
        
    </adapter>
</module>

STEP 4   In our pipeline we’re going to  specify the operations we want to perform on our input. As it can be any xml that is sent we want to validate it, to make sure we can insert something sensible later on. The framework supplies us with an XmlValidator pipe. We just have to specify the location of our input.xsd file and we’re done. After validation we want to insert our data. This is maybe not a realistic scenario, because maybe our record is already there and we just want to update it. Pipelines can be built implementing if-else logic, but we will reserve that topic for later.

<pipeline firstPipe="ExecuteInsertQuery">
            <exits>
                <exit path="EXIT" state="success"/>
            </exits>
            
            <inputValidator
                className="nl.nn.adapterframework.pipes.XmlValidator"
                schema="CreateCustomer/xsd/klant.xsd"
                root="Klant"
                throwException="true">
            </inputValidator>
                        
            <pipe name="ExecuteInsertQuery" 
                className="nl.nn.adapterframework.pipes.GenericMessageSendingPipe">
                <sender name="ExecuteInsertQuery" 
                    className="nl.nn.adapterframework.jdbc.FixedQuerySender" 
                    query="INSERT INTO CUSTOMERS (ClientNr, Initials, Firstname, LastName, Title, Street, Postalcode, HouseNr, Addition, City, CreationDate)    VALUES (?,?,?,?,?,?,?,?,?,?,SYSDATE);" 
                    jmsRealm="jdbc">
                    <param name="Klantnummer" sessionKey="originalMessage" xpathExpression="Klant/Klantnummer"/>
                    <param name="Voorletters" sessionKey="originalMessage" xpathExpression="Klant/Voorletters"/>
                    <param name="Voornaam" sessionKey="originalMessage" xpathExpression="Klant/Voornaam"/>
                    <param name="Achternaam" sessionKey="originalMessage" xpathExpression="Klant/Achternaam"/>
                    <param name="Titel" sessionKey="originalMessage" xpathExpression="Klant/Titel"/>
                    <param name="Straat" sessionKey="originalMessage" xpathExpression="Klant/Straat"/>
                    <param name="Postcode" sessionKey="originalMessage" xpathExpression="Klant/Postcode"/>
                    <param name="Huisnummer" sessionKey="originalMessage" xpathExpression="Klant/Huisnummer"/>
                    <param name="Huisnummer2" sessionKey="originalMessage" xpathExpression="Klant/Huisnummer2"/>
                    <param name="Plaats" sessionKey="originalMessage" xpathExpression="Klant/Plaats"/>
                </sender>
                <forward name="success" path="EXIT"/>
            </pipe>
        </pipeline>

The framework has some keywords that you need to remember : the original message can be stored as a key value pair in a sessionKey. The name “originalMessage” obviously refers to our input data.

 

 

Testing the app

 

You have to post your adapter now to the framework. Push the upper right send button and wait for the little green ball. Your Ibis has stored your adapter now, and you are almost ready to post your first customer! Only first we must make sure that all our code is working okay. Go to the console and make sure we have no red messages. Under the tab “Ibis4Student” you can see what you have posted.
For a collection of Troubleshooting cases open this page. When in your console all is green you can give it a try in Postman, cUrl, or some other http-client. The result should look similar to this. Check in the console that there is a received message now. Also note the message in the response box; you can have a 200 response, but yet  failed in your insertion attempt. See for examples in the troubleshooting page.

 

Solutions

ConfigurationCreateCustomer.xml

klant.xsd

troubleshooting

 


Leave a Comment