Data as a Service (DaaS) provides Onit clients easy access to their data from Onit’s data warehouse. This enables clients to build their data sources and develop their reporting solutions. DaaS uses the Open Data Protocol (OData), which provides a low-overhead secured data gateway with a modernized API-driven approach to enable broad integration across products such as PowerBI Tableau and Excel.
Clients can also utilize DaaS to gain data access and incorporate it into their existing data lakes for enterprise-level reporting using the latest security protocols.
For more detailed information on the DaaS architecture, please refer to the Data as a Service Architecture Guide.
What to expect from DaaS provisioning
Provisioning of DaaS entails setting up the client as a tenant within the DaaS portal and creating an admin user for the client. Once DaaS is provisioned for the client, the admin user will receive the following information within the email, which will allow clients to self-serve the setup for a successful DaaS connection and data retrieval into the client’s reporting environment:
1. A welcome email from Onit with the link to connect to the DaaS portal and the following steps to connect to DaaS through BI tools.
2. A data dictionary outlining the app/field relationship within Onit to enable clients further to create the joins based on their reporting needs.
3. DaaS User Guide outlining different steps to cover various connection scenarios.
Pre-Requisites
Onit data warehouse needs to be in place, including all the default applications and fields from App Builder and Billing Points systems. Any additional applications or fields required in the Onit data warehouse must be enabled for reporting within the App Builder application.
Before You Begin
Before you start accessing the OData endpoints, you must change the password for the useradmin.
Note: This useradmin only has the privilege of adding new DaaS users. These additional users should be used to connect to the OData API endpoints via BI tools.
Follow the below steps to change the password.
Steps to Change the Password
1. To change the password, use your web browser to open the below OData endpoint. https://odata.onit.com/hdpui/login.jsp
2. Enter the username and password for your OData user/useradmin, shared by Onit through OData Welcome Provision mail.
3. Click on the authenticate button. A change password screen will appear to set the new password.
4. Enter the Current Password, new password and confirm new password. Click Save to change the password.
Create a New User for a Tenant
This section describes how to add a new user for a tenant. For this, we will use the useradmin credentials, as the useradmin will be responsible for adding new users.
1. Login to the below OData endpoint using the useradmin credentials. https://odata.onit.com/hdpui/login.jsp
If the useradmin is logging in for the first time, the useradmin needs to reset the password. Refer to the “Steps to change the password” section of the document.
Once logged in, the “Manage User” page of the OData endpoint will open. This page contains a list of this tenant's available users.
2. Click on the “+ New User” button. This will open the “Create User” page.
3. In the “Create User” page, there are two sections to fill:
- General
- Authentication Setup
On the “General” tab, enter your username in the “User Name” field and select the appropriate role from the “Role” dropdown. There are three roles available in the “Role” dropdown.
- User Role: Users with this role can access the data from the OData endpoint.
- UserAdmin Role: Users with this role can create a user for a tenant.
- Tenant Administration Role: Users with this role can manage the tenant. Currently, Onit manages this role.
Here, we will create a new user named “onituser” for awsustau tenant, and the role for this user will be “User Role."
In the “Authentication Setup” tab, provide the password for the new user and click on the “Save” button, as shown in the below screenshot. When clicking the “Save” button, the page will be redirected to the “Manage User” page.
4. The useradmin should now be able to see the newly created user added in the “Manage User” page. The useradmin needs to share the credentials with the new user.
5. The new user needs to log in to the OData endpoint and change the password. A guide to changing the password for a user is provided in the “Steps to change the password” section of the document.
6. Once the password is changed, the user can connect to the OData endpoints using any of the methods mentioned in the later sections of the document.
Note: Once the password has been set, useradmin would not have the permissions to reset the password.
Connect Tableau to OData
Tableau & OAuth authentication for OData
As of now, Tableau does not support OAuth 2.0-based authentication for OData. Please refer to the OAuth Connections link for more details about the other connectors supported by Tableau.
Connect using basic authentication
This section describes how to connect Tableau to an OData data source. Tableau connects to OData V1, V2, and V4. Onit supports OData Version V4.
1. Start Tableau, and under Connect, select OData. For a complete list of data connections, select More under To a Server. Then do the following:
In the Server, type one of the following:
- A service URL to access all feeds inside the service.
- A feed URL to access a specific data feed.
From the Authentication dropdown, select the authentication mode for this connection.
- If you select Username and Password, type a username and password.
Select Sign In.
Note: If Tableau can't connect, verify that your credentials are correct. If you still can't connect, your computer may be having trouble locating the server, and you should contact your network administrator.
2. Click on OData, enter the OData endpoint URL with username and password, and click Sign In.
3. Once the connection is successful, all the apps will be visible in the Tableau table panel. You can drag and drop the tables to include them in the data source.
4. The data source can include more than one entity and the relationship between them can be specified using the joining fields.
5. Once the data source is designed, you can use the worksheet to build the Tableau dashboards/reports.
Note: OData users can only create extract connections for data sources.
Connect PowerBI to OData
Connect Using OAuth 2.0-Based Authentication
This section describes connecting PowerBI to an OData data source using OAuth 2.0-based authentication.
1. Open Visual Studio and Create New -> Project. In the left pane, choose Power Query under templates. Choose Data Connector Project and create a New Project named ‘HdpOAuth 2.0Connect’.
2. In the Solution, find HDPOAuth 2.0Connect.pq file and change the below configurations:
- Onit OData Service URL
- Client ID
- Client Secret
- Authorize URL
- Token URL
3. Save the file and Build the Solution. This should create a HDPOAuth 2.0Connect.mez file in the bin folder. This is the Power BI extension.
4. On your PC, Go to Documents and create a Microsoft Power BI Desktop folder.
5. Under the folder Microsoft Power BI Desktop, create another folder, Custom Connectors
6. Copy the HDPOAuth 2.0Connect.mez to the folder Custom Connectors.
7. Start PowerBI Desktop. Under Get Data, select HDPAOuthConnect and click Connect.
8. In the HDPAOuthConnect dialog, click Sign In.
9. This should open the login page for you to authenticate. Enter the Username and password. Click the Authenticate button.
10. If the username and password are correct, you should see the below authorization screen. Click on the Allow button.
11. Click on Connect to see your data.
Connect Using Basic Authentication
This section describes how to connect PowerBI to an OData data source.
1. Start PowerBI Desktop, and under Get Data, select OData feed.
2. In the OData Feed dialog, type the following:
• Select the Basic option, enter the OData Endpoint URL, and Click OK. (https://odata.onit.com/api/odata4/all_apps_{subdomain})
3. Enter the username and password on the OData Feed dialog and Click Connect.
4. Once the connection is successful, all the apps/entities will be visible in PowerBI's navigator panel. Select the apps/entities that you want to include as part of the data source.
5. Once complete, Power BI Desktop makes the selected tables and other data elements available in the Fields pane, found on the right side of the Reports view in Power BI Desktop.
6. You can use the Manage Relationship option to create and manage relationships between entities.
Model your Business Data
Introduction to Entities
Entities are used to model and manage business data in Onit. An Onit app or database view can be considered an entity with a set of attributes, and each attribute represents a data item of a particular type.
For example, within Onit’s Enterprise Legal Management (ELM) product, the following Entity Relationship Diagram represents apps and relationships that may fit a client-specific business need for reporting.
Onit ELM-owned entities include matters, invoices, vendors, vendor_assignment_to_matters, and billing_authorization_requests. BillingPoint-owned entity is bp_invoices_line_item_cube. Relationships can be of various types and, for the most part, are defined in your Onit configuration and are available from the custom data dictionary provided during provisioning. This includes:
- One-to-One: This relationship indicates that a single record in one entity is related to a single record in its related entity (Onit relationship type belongsTo)
- One to Many: This relationship indicates that a single record in one entity can be related to many records in its related entity (Onit relationship type belongsTo)
- Many to Many: This relationship indicates any record in either entity can be related to many records in the related entity (Onit relationship type ManyToMany)
Many-To-Many Relationships
A many-to-many relationship occurs when multiple rows in an entity are associated with multiple rows in a related entity. To identify unique pairs of records, this relationship type needs to be split into two one-to-many relationships, with a new data warehouse join table. The join table simply contains foreign key columns for the two related tables' (built from entities) primary keys.
A typical generic example of a many-to-many relationship is between students and courses. A student can register for many courses, and a course can include many students. We need to identify each student/course pair through a join table to get information from both student and course. In the data warehouse, a join table is created, but views that have appropriate names are also used to guide the correct join through this view. See the Tableau join example below for joining students through student_courses by id and then to the courses table through the m2m_courses column.
In Onit, be sure to enable the required ManyToMany relationship fields for reporting so that the join table is created in the data warehouse and made available in Data as a Service.
Limit Unnecessary Data at the Source
Whether creating data sources for BI tools or accessing data from the APIs, we strongly encourage selecting attributes and filtering rows to meet a specific business need for optimal performance. Consider filtering by phases, statuses, dates, or other attributes that meet your needs as efficiently as possible. For example, in ELM, you may never want to see voided invoices, so you can filter invoices.curr_state_name and exclude the voided state. You can also exclude rejected matters by filtering matters.curr_state_name and exclude the rejected state.
OData Endpoints
The following tables describes the resources and the corresponding URLs in the data warehouse.
In addition to the metadata you can get from the endpoint, you can also request a data dictionary from support for your apps available in DaaS.
NOTE: Unless specified explicitly, the order of columns is not guaranteed so be sure to reference columns by name and not position.
Use Postman App to Access OData
Connect Using OAuth 2.0-Based Authentication
This section describes connecting Postman to an OData data source using OAuth 2.0-based authentication.
1. Open Postman and send a POST REQUEST as shown below; the Response from the Server will contain your Client Key and Client Secret and should be like something below.
Fetch OData Data Using OAuth 2.0-Based Authentication
This section describes how to fetch OData data using OAuth 2.0-based authentication.
1. Open Postman and send a POST REQUEST using the User in the welcome email. The server response will contain your Client Key and Client Secret and should look like the below.
2. Open Postman and send a POST REQUEST using the User in the welcome email. The server's Response will contain your Access Token and Refresh Token.
3. Open Postman and send a GET REQUEST as shown below using Access Token generated in the second step to fetch data using Postman.
4. OData Enpoint Data can be fetched using python. Below is the code snippet:
Connect using basic authentication
This section describes how to connect Postman App to an OData data source.
- Start the Postman app and add a new request. Then do the following:
- In the Request URL, type the below endpoint"https://odata.onit.com/api/odata4/all_apps_{subdomain}
Note: Replace the {subdomain} with the name of your subdomain - On the Authorization tab, type as Basic Auth and enter the username and password provided to you.
- Press Send button. It should return the list of apps/entities that are available as part of the OData API
Get the List of Entity/App Metadata
- Start the Postman app and add a new request. Then do the following:
- In the Request URL, type the below endpoint: https://odata.onit.com/api/odata4/all_apps_{subdomain}/#metadata
Note: Replace the {subdomain} with the name of your subdomain - On the Authorization tab, type as Basic Auth and enter the username and password provided to you.
- Press the Send button. It should return the list of apps/entities metadata that are available as part of the OData API
Get the Data for an Entity/App
- Start the Postman app and add a new request.
- In the Request URL, type the below endpoint: https://odata.onit.com/api/odata4/all_apps_{subdomain}/{entity_name}
Note: Replace the {subdomain} with the name of your subdomain. Replace {entity_name} with the entity's name that was returned as part of the list of entities. - On the Authorization tab, type as Basic Auth and enter the username and password provided to you.
- Press Send button. It should return the list of apps/entities metadata that are available as part of the OData API
Generate Code to Connect to OData API
- Start the Postman app and add a new request. Then do the following:
- In the Request URL, type the below endpoint: https://odata.onit.com/api/odata4/all_apps_{subdomain}/{entity_name}
Note: Replace the {subdomain} with the name of your subdomain. Replace {entity_name} with the name of the entity that was returned as part of the list of entities. - On the Authorization tab, type as Basic Auth and enter the username and password provided to you.
- Press the Send button. Click on the Code icon to generate the code in the language of your choice.
Use Python to Access OData
Below are several Python code snippets for connecting to the OData API using basic authentication, pulling incremental data, and updating a target database.
Connect Using Basic Authentication
import http.client
import base64
# Connect to the odata endpoint host
conn = http.client.HTTPSConnection("odata.onit.com")
# Keep the payload as empty string
payload = ''
# Pass the Authorization header with Basic authentication
# The user name and password should be encoded as Base64
# Create a base64 encoded authorization header "subdomain_user:password"
# Replace the user name and password below. It is better to store the username and password in config file or password vault
auth_string = "subdomain_user:password"
# convert to Base64 encoded authorization string
base64_bytes = base64.b64encode(auth_string.encode("ascii"))
base64_string = base64_bytes.decode("ascii")
# Prepare the request header for basic authorization
headers = {
'Authorization': f"Basic {base64_string}"
}
# Make the HTTP request. Replace the endpoint with your subdomain e.g. all_apps_subdomain
conn.request("GET", "/api/odata4/all_apps_awsustau/matters", payload, headers)
# get the response
res = conn.getresponse()
# Read the json data from the response
data = res.read()
# Print the json data
print(data.decode("utf-8"))
Note: Update the highlighted code with the connectivity details for your subdomain.
Select and Update Incremental Data
import http.client
import base64
# Connect to the odata endpoint host
conn = http.client.HTTPSConnection("odata.onit.com")
# Keep the payload as empty string
payload = ''
# Pass the Authorization header with Basic authentication
# The user name and password should be encoded as Base64
# Create a base64 encoded authorization header "subdomain_user:password"
# Replace the user name and password below. It is better to store the username and password in config file or password vault
auth_string = " "
# convert to Base64 encoded authorization string
base64_bytes = base64.b64encode(auth_string.encode("ascii"))
base64_string = base64_bytes.decode("ascii")
# Prepare the request header for basic authorization
headers = {
'Authorization': f"Basic {base64_string}"
}
# Create the connection configuration based on the Database where the odata endpoint data is stored
connection = get_db_connection(dbName, username, password)
# Fetching max updated_at present in the DB for that particular entity
entity_max_updated_at = connection.execute('''SELECT MAX(updated_at) FROM matters''')
# Fetching max calculated_at present in the DB for that particular entity. Calculated_at is set when a recalc is performed on an atom
entity_max_calculated_at = connection.execute('''SELECT MAX(calculated_at) FROM matters''')
# odata api url to fetch the count of incremental data
incr_dataCount_endpoint_url = f' incr_dataCount_endpoint_url = f'/api/odata4/all_apps_awsustau/matters/$count?$filter=updated_at%20gt%20{entity_max_updated_at}%20 or%20calculated_at%20gt%20{entity_max_calculated_at}'
# Make the HTTP request to get the incremental data count from odata endpoint.
conn.request("GET", incr_dataCount_endpoint_url, payload, headers)
# Get the incremental data count response
incr_dataCount_res = conn.getresponse()
# Read the incremental data count from the response
incr_dataCount = incr_dataCount_res.read()
incr_dataCount = int(incr_dataCount.decode("utf-8"))
if incr_dataCount > 0:
# odata api url to fetch the incremental data
incr_data_endpoint_url = f'/api/odata4/all_apps_awsustau/matters? ?$filter=updated_at%20gt%20{entity_max_updated_at}%20or%20calculated_at%20gt%20{entity_max_calculat ed_at}'
# Making the HTTP request to fetch the incremental data for that particular entity from odata endpoint
conn.request("GET", incr_data_endpoint_url, payload, headers)
# Get the incremental data response
incr_res = conn.getresponse()
# Read the incremental json data from the response
incr_data = incr_res.read()
# Print the incremental json data
print(incr_data.decode("utf-8"))
# Implement the delete-insert function. This function will perform below activities.
# 1. Incremental Records that are new, will be inserted into the DB.
# 2. Incremental Records that are already present in the DB, will be first deleted from DB, and then the updated version of those records will be inserted into the DB.
delete_insert_incremental_data(incr_data, connection)
else:
print("No incremental data found in odata endpoint for this entity. Hence, the data load for this entity will be skipped.")
Note: Update the highlighted code with the connectivity details for your subdomain
Select and Insert to target DB based on batch size
import http.client
import base64
import json
import logging
logger=logging.getLogger(__name__)
def load_odata_data(entity_url, conn, payload, headers,batch_size):
'''
function that fetches the data from OData endpoint url and insert to target db in batch
'''
conn.request("GET", entity_url, payload, headers)
i=0
# get the response
res = conn.getresponse()
# Read the json data from the response
data_dict = json.loads(res.read())
#Entity Records
records = data_dict['value'] #OData Record list
odata_rec=[]
#Loop to process odata records and insert into target db in batch
connection=None
for rec in records:
i=i+1
odata_rec.append(rec)
if i>=batch_size:
i=0
load_target_db(connection,odata_rec)
odata_rec=[]
if len(odata_rec)>0:
load_target_db(connection,odata_rec)
def load_target_db(connection,odata_rec):
'''
Add a logic to insert the data in to target db
'''
logger.info("Total Records available for insertion : {} ".format(len(odata_rec)))
# Connect to the odata endpoint host
conn = http.client.HTTPSConnection("odata.onit.com")
# Provide the tenant and entity details here
tenant_name = 'awsustau'
entity_name = 'matters'
# Keep the payload as empty string
payload = ''
# Pass the Authorization header with Basic authentication
# The user name and password should be encoded as Base64
# Create a base64 encoded authorization header "subdomain_user:password"
# Replace the odata_username and password below. It is better to store the username and password in config file or password vault
auth_string = "awsustau_useradmin:{password}"
# Convert to Base64 encoded authorization string
base64_bytes = base64.b64encode(auth_string.encode("ascii"))
base64_string = base64_bytes.decode("ascii")
# Prepare the request header for basic authorization
headers = {
'Authorization': f"Basic {base64_string}"
}
# Make the HTTP request. Replace the endpoint with your subdomain e.g. all_apps_subdomain
entity_url = f"/api/odata4/all_apps_{tenant_name}/{entity_name}"
try:
# Batch size to load data in target db
batch_size=10
# Fetch records from odata endpoint & load to target db based on batch size
load_odata_data(entity_url, conn, payload, headers,batch_size)
except Exception as exc:
logger.error(f"{tenant_name}: Unable to fetch the data for entity '{entity_name}' : {str(exc)}")
finally:
conn.close()
Construct a URL into Onit
To create a URL into an Onit single atom page, use the app id and atom id available as system fields as noted above with a format similar to: https://mycorp.onit.com/apps/{app_id}/atoms/{_id}
Supported Features from OData Specification
The following are the high-level features enabled for the OData service, per the OData specification.
Available query options
- $filter
- $count
- $orderby
- $skip
- $top
- $select
Built-in operators for $filter
- Equals (eq)
- Not equals (ne)
- Greater than (gt)
- Greater than or equal (ge)
- Less than (lt)
- Less than or equal (le)
- And
- Or
- Not
For more information, see OData operators.
OData Query Examples
Here are a few examples of the various query features that can be used as part of OData. Please refer to OData specification for more details about querying and filtering data using OData specification.
- Get the count of rows for a given entity. https://odata.onit.com/api/odata4/all_apps_awsustau/matters/$count
- Get the top 5 rows. https://odata.onit.com/api/odata4/all_apps_awsustau/matters?$top=5
- Skip the first 5 rows and get the top 5 rows. https://odata.onit.com/api/odata4/all_apps_awsustau/matters?$skip=5&$top=5
- Order by field name in descending order. https://odata.onit.com/api/odata4/all_apps_awsustau/matters?$orderby=created_at desc
- Filter data using the filter expression. https://odata.onit.com/api/odata4/all_apps_awsustau/matters?$filter=area_of_law eq 'Commercial'
- Select specific fields from a given entity. https://odata.onit.com/api/odata4/all_apps_awsustau/matters?$select=id,status,atom_number
DaaS Troubleshooting
This section describes how to troubleshoot Onit Data as a Service and potential connectivity issues
Communication error while connecting with Tableau or PowerBI
When a user tries to log in to https://odata.onit.com/api/odata4/all_apps_awsustau/, even with the correct credentials, Tableau or PowerBI can still sometimes face communication issues with OData. Ensure there are no leading or trailing spaces, which can sometimes happen when copying/pasting.
Timeout Session
An idle browser window (20+ minutes) will lose connectivity, and subsequent use of the UI will result in session timeout (Error 408). Close and re-open the browser to start a new session to resolve this issue.
Fields not Selected for Reporting but are in DW and DaaS
Even if relationship fields are not selected for reporting, they are always pulled in by the DW refresh. Hence, they are available for joins to their related app either by a BelongsTo or ManyToMany relationship.