Using and generating versioned APIs to invoke model services
NexJ CRM provides versioned APIs for model services that you can leverage to ensure integration compatibility across multiple NexJ releases.
You can also generate your own customized versioned APIs.
When NexJ publishes an API release, it contains API attributes that are either backwards compatible or deprecated. Each API has a name and version. For example, the format for the API name is <exampleAPI>.<versionNumber>. Deprecated API attributes still work until the release version that they belong to is retired.
To develop with a newer version of the APIs, select the next version supplied by NexJ. For example, you can replace http://localhost:7080/nexj/api/finance.1/json/Person with http://localhost:7080/nexj/api/finance.2/json/Person.
Example of differences between versioned APIs
The following example responses show how NexJ can change APIs between versions and provide different data.
Differences in responses between versioned APIs
The finance.1.api
contains the initials attribute, as shown in the following example response for http://localhost:7080/nexj/api/finance.1/json/Person?$indent:
[
{
"$class": "Person",
"$oid": "10031EB22558AF415592879A4E51B344E0",
"firstName": "Kristine",
"initials": null
},
{
"$class": "Person",
"$oid": "10C859B98830D04A96B2F7C39C0A77760E",
"firstName": "Zineea",
"initials": null
},
{
"$class": "Person",
"$oid": "100FF7F923BFF54FD0AF218422A5869517",
"firstName": "Asma",
"initials": "H"
},
...]
For finance.2.api, the
initials attribute has been retired and the lastName
attribute has been added, and is now available for use, as shown in the following example response for http://localhost:7080/nexj/api/finance.2/json/Person?$indent:
[
{
"$class": "Person",
"$oid": "10031EB22558AF415592879A4E51B344E0",
"lastName": "Abrams",
"firstName": "Kristine"
},
{
"$class": "Person",
"$oid": "10C859B98830D04A96B2F7C39C0A77760E",
"lastName": "Ahmed",
"firstName": "Zineea"
},
{
"$class": "Person",
"$oid": "100FF7F923BFF54FD0AF218422A5869517",
"lastName": "Akbar",
"firstName": "Asma"
},
...]
Example of a versioned API
This topic provides an example of a versioned API.
Versioned API for the Person
metaclass
The following code snippet shows an example of a versioned API for the Person
metaclass. The example shows deprecated attributes that can be used for development but they may be retired in the near future. For example, for the Person
class, affix
, fullName
, goesBy
, householdName
, lastName
, and smsEmail
are deprecated attributes. The firstName
, homeAddress
, household
, and user
attributes are backwards compatible and can be used for development.
<API>
<Classes>
...
<Class name="Person">
<Attributes>
<Attribute name="affix" type="string" deprecated="true"/>
<Attribute name="firstName" type="string" required="true"/>
<Attribute name="fullName" type="string" deprecated="true"/>
<Attribute name="goesBy" type="string" deprecated="true"/>
<Attribute name="homeAddress" type="Address"/>
<Attribute name="household" type="Household"/>
<Attribute name="householdName" type="string" deprecated="true"/>
<Attribute name="lastName" type="string" required="true" deprecated="true"/>
<Attribute name="smsEmail" type="EmailAddress" deprecated="true"/>
<Attribute name="user" type="User"/>
</Attributes>
<Events>
<Event name="firstNameSearch" static="true">
<Arguments>
<Argument name="attributes" type="any"/>
<Argument name="where" type="any"/>
<Argument name="orderBy" type="any"/>
<Argument name="count" type="any"/>
<Argument name="offset" type="any"/>
<Argument name="xlock" type="any"/>
</Arguments>
</Event>
<Event name="read" static="true">
<Arguments>
<Argument name="attributes" type="any"/>
<Argument name="where" type="any"/>
<Argument name="orderBy" type="any"/>
<Argument name="count" type="any"/>
<Argument name="offset" type="any"/>
<Argument name="xlock" type="any"/>
</Arguments>
</Event>
</Events>
</Class>
<Class name="Portlet">
<Events>
<Event name="readList" static="true">
<Arguments>
<Argument name="attributes" type="any"/>
<Argument name="where" type="any"/>
<Argument name="orderBy" type="any"/>
<Argument name="count" type="any"/>
<Argument name="offset" type="any"/>
<Argument name="xlock" type="any"/>
</Arguments>
</Event>
</Events>
</Class>
...
<Class name="UserPerson">
<Attributes>
<Attribute name="affix" type="string" deprecated="true"/>
<Attribute name="firstName" type="string" required="true"/>
<Attribute name="fullName" type="string" deprecated="true"/>
<Attribute name="goesBy" type="string" deprecated="true"/>
<Attribute name="homeAddress" type="Address"/>
<Attribute name="household" type="Household"/>
<Attribute name="householdName" type="string" deprecated="true"/>
<Attribute name="lastName" type="string" required="true" deprecated="true"/>
<Attribute name="smsEmail" type="EmailAddress" deprecated="true"/>
<Attribute name="user" type="InternalUser" required="true"/>
</Attributes>
<Events>
<Event name="firstNameSearch" static="true">
<Arguments>
<Argument name="attributes" type="any"/>
<Argument name="where" type="any"/>
<Argument name="orderBy" type="any"/>
<Argument name="count" type="any"/>
<Argument name="offset" type="any"/>
<Argument name="xlock" type="any"/>
</Arguments>
</Event>
<Event name="read" static="true">
<Arguments>
<Argument name="attributes" type="any"/>
<Argument name="where" type="any"/>
<Argument name="orderBy" type="any"/>
<Argument name="count" type="any"/>
<Argument name="offset" type="any"/>
<Argument name="xlock" type="any"/>
</Arguments>
</Event>
</Events>
</Class>
</Classes>
</API>
Consuming versioned APIs
This section describes how to consume the versioned APIs provided by NexJ.
Using Swagger UI to view versioned APIs operations
This topic shows how to use Swagger UI, which is provided by SmartBear Software, to view operations for the Person
metaclass using a versioned API example.
To view all available operations for a metaclass in an easy-to-read format without having to paste the raw Swagger Interface Definition Language (IDL) into an API editor, add the following mixin to your environment file in NexJ Studio and then restart your application server.
<Mixin namespace="nexj:openapi" version="0"/>
To view operations for the Person
metaclass using Swagger UI and a versioned API:
- Open Swagger UI by entering the following URL in your browser:
http://<application-server>/<context-root>/openAPI.html - Enter the following in the Swagger UI search field and click Explore. This example uses finance.6 as the API name.
/nexj/api/finance.6/json?filter=Person/0
Swagger UI opens and displays the operations you can access for thePerson
metaclass. - [Optional] To see all of the information for contacts with the last name of Lamont, enter
(= (@ lastName)“Lamont”)
in the where field for theGet /Person
command and click Execute.
The following response displays all of the contacts with the last name of Lamont: - [Optional] To see all of the compatible events and methods for the
Person
metaclass, enter the following in the search field and click Explore./nexj/api/finance.6/json?filter=Person/0 &compatible=false
- [Optional] To see all of the attributes and values with compatibility for contacts with the last name of Lamont,
enter(= (@ lastName) “Lamont”)
in the where field for theGet /Person
command and click Execute.
The following response displays the attributes and values for contacts with the last name of Lamont: [Optional] To see information for individual contacts in the database, enter the following URL in your browser:
http://localhost:7080/nexj/api/finance.6/json/Person
The following code snippet shows an example of the response that displays contact information:SCHEME[{"$class":"Person","$oid":"106EDB6271733F479CB2290E658F027844","affix":null, "lastName":"Abrams","smsEmail":null,"homeAddress":null,"user":null, "firstName":"Kristine","goesBy":null,"household":null}, {"$class":"Person","$oid":"107A78F93BDB704FBFB7EFDAD67FB27502","affix":null, "lastName":"Ahmed","smsEmail":null,"homeAddress":{"$class":"Address", "$oid":"1067A6F5559A96405B978C8530A75B98AD"},"user":null, "firstName":"Zineea","goesBy":null,"household":null}, {"$class":"Person","$oid":"107C632209808E4F2388FD1EB542CEC72B","affix":null, "lastName":"Akbar","smsEmail":null,"homeAddress":{"$class":"Address", "$oid":"105729222190A64494AEA3AF4053D113B8"},"user":null, "firstName":"Asma","goesBy":null,"household":null}, {"$class":"Person","$oid":"1008CF37BCBBB744C38C702B537357A5C7","affix":null, "lastName":"Alpers","smsEmail":null,"homeAddress":null,"user":null, "firstName":"Lakisha","goesBy":null,"household":null}, {"$class":"Person","$oid":"106C5B923EBA3E4FF4A996BBB60D966AB9","affix":null, ...}]
- [Optional] To see all the attributes and events with compatibility for the classes in
finance.6.api
, enter the following URL in your browser:
http://localhost:7080/nexj/api/finance.6/json
A response will display the attributes and events with compatibility for the classes infinance.6.api
.
You have used Swagger UI to view operations for the Person
metaclass using a versioned API.
Using RESTful XML calls to invoke model services
You can access RESTful XML calls using versioned APIs provided by NexJ.
To invoke versioned model services using RESTful XML calls:
- Send the following URL to NexJ Server using a GET request for a metaclass:
http://<application-server>/<context-root/>api/<exampleAPI.1>/xml/<metaclassName> You will receive a response that shows an XML object containing the metaclass. For example, the following code snippet shows a response with people data for the
Person
metaclass.XML<_Collection><item xi:type="Person"><_version>0</_version><_oid>106EDB6271733F479CB2290E658F027844</_oid><_keys>affix</_keys><_keys>smsEmail</_keys> <_keys>homeAddress</_keys><_keys>user</_keys><_keys>goesBy</_keys><_keys>household</_keys><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><firstName>Kristine</firstName><lastName>Abrams</lastName></item><item xi:type="Person"><_version>0</_version><_oid>1008CF37BCBBB744C38C702B537357A5C7</_oid><_keys>affix</_keys><_keys>smsEmail</_keys> <_keys>homeAddress</_keys><_keys>user</_keys><_keys>goesBy</_keys><_keys>household</_keys><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><firstName>Lakisha</firstName><lastName>Alpers</lastName></item><item xi:type="Person"><_version>0</_version><_oid>106C5B923EBA3E4FF4A996BBB60D966AB9</_oid><_keys>affix</_keys><_keys>smsEmail</_keys> <_keys>homeAddress</_keys><_keys>user</_keys><_keys>goesBy</_keys><_keys>household</_keys><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/><_values xi:nil="true"/> ... </_Collection
You have accessed a versioned API through a REST endpoint.
Using SOAP to invoke versioned model services
You can use SOAP to invoke versioned model services.
Before starting this task, install SoapUI, which is provided by SmartBear Software.
To use SOAP to invoke versioned model services:
- Copy and paste the link to the http://<application-server>/<context-root>/<exampleAPI.1>/soap endpoint into your browser.
When you open the link, your browser generates an XML file. - Save the XML file with a WSDL extension. For example, save the file with the following name:
fin2.wsdl
. - To display a sample request with the endpoint that you opened in your browser, open the WSDL file in SoapUI.
Create your SOAP request. The following code shows an example SOAP request that asks the
Person
class for the specific attributes that are marked as backwards compatible or deprecated with the compatibility flag set tofullName
andfirstName
in this case. The code also contains a count parameter, which specifies that two instances should be returned for thePerson
class.TEXT<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:x-="http://www.example.com/xml-soap" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <soapenv:Header/> <soapenv:Body soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <x-:invoke> <request xsi:type="x-:Request"> <version xsi:type="xsd:string">2</version> <async xsi:type="xsd:boolean">false</async> <commit xsi:type="xsd:boolean">true</commit> <!--Optional:--> <invocations xsi:type="x-:Invocation-array" soapenc:arrayType="x-:Invocation[1]"> <Item> <object> <class xsi:type="xsd:string">Person</class> <version xsi:type="xsd:int">2</version> </object> <event>read</event> <arguments xsi:type="x-:anyType-array" soapenc:arrayType="x-:anyType[6]"> <Item xsi:type="x-:Expression"><text>(fullName firstName)</text></Item> <Item xsi:type="x-:Expression"><text></text></Item> <Item xsi:type="x-:Expression"><text></text></Item> <Item xsi:type="xsd:int">2</Item> <Item xsi:type="xsd:int">0</Item> <Item xsi:type="xsd:boolean">0</Item> </arguments> </Item> </invocations> </request> </x-:invoke> </soapenv:Body> </soapenv:Envelope>
- Send the request to the server endpoint in SoapUI using an HTTP POST request.
The response returns the attributes queried in the request if they are marked as compatible in the class. The response is contained in an XML file inside a SOAP response envelope. The following code shows an example response that returns two instances of the Person
class with the attributes that are marked as backwards compatible, in this case the fullName
and the firstName
attributes. If a user requested that this version of the API provide an attribute that is not marked as backwards compatible in the SOAP request, the user would instead receive an error in the SOAP response.
<nv:Envelope xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:nv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:nc="http://schemas.xmlsoap.org/soap/encoding/">
<nv:Body nv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns="http://www.example.com/xml-soap">
<ns:invoke-response>
<response>
<results nc:arrayType="xs:anyType[1]">
<Item href="#a"/>
</results>
</response>
</ns:invoke-response>
<ns:Array id="a">
<items nc:arrayType="xs:anyType[2]">
<Item href="#b"/>
<Item href="#c"/>
</items>
</ns:Array>
<ns:TransferObject id="b">
<class>Person</class>
<version>0</version>
<oid>
<values nc:arrayType="xs:anyType[1]">
<Item xi:type="xs:base64Binary">nx6aP5iPQlycGtYlkMfPPA==</Item>
</values>
</oid>
<keys nc:arrayType="xs:string[2]">
<Item>fullName</Item>
<Item>firstName</Item>
</keys>
<values nc:arrayType="xs:anyType[2]">
<Item xi:type="xs:string">Abrams, Kristine</Item>
<Item xi:type="xs:string">Kristine</Item>
</values>
</ns:TransferObject>
<ns:TransferObject id="c">
<class>Person</class>
<version>0</version>
<oid>
<values nc:arrayType="xs:anyType[1]">
<Item xi:type="xs:base64Binary">YrZA3EAISJO/a0bnRzN3cg==</Item>
</values>
</oid>
<keys nc:arrayType="xs:string[2]">
<Item>fullName</Item>
<Item>firstName</Item>
</keys>
<values nc:arrayType="xs:anyType[2]">
<Item xi:type="xs:string">Agena, Michael</Item>
<Item xi:type="xs:string">Michael</Item>
</values>
</ns:TransferObject>
</nv:Body>
</nv:Envelope>
Providing versioned APIs
You may want to provide your own customized versioned APIs by generating them.
Generating versioned APIs
You can generate your own customized versioned APIs.
Before starting this task, create a meta/api
folder in your project.
To generate API metadata specifying members, which are attributes and events:
- Navigate to the NexJ Studio Business Model layer and select the Classes tab.
- Double-click the required metaclass to open it. For example, open the
Person
metaclass. - On the Overview tab, set the metaclass to be available to the API by selecting
backwards compatible
ordeprecated
- For the members that you want to be compatible, select either backward for
backwards compatible
ordeprecated
in the Compatibility drop-down as the value for the related compatibility property. For example, to change compatibility for an event, select the Events tab, select the required event, and in the Common tab, select a value in the Compatibility drop-down. - Save your changes.
- Click the down arrow beside the Run Tool button and select Generate API.
The Generate API dialog opens. - Complete the Generate API dialog as required. Ensure you specify the following information for your API:
- Name
- Version
- Output directory
- [Optional] You can choose to overwrite a previously generated API file by selecting Overwrite Existing File.
- Click Run.
- Move the newly generated API into the
meta/api
folder in your project folder.
Restart your server. You can now invoke remote procedure calls with the specified /api
endpoint; for example, localhost:7080/nexj/api/enterprise.1/json/LocalUser
. You will only have access to the attributes marked as compatible.