Enterprise Integration with Azure Logic Apps
Understand Enterprise Integration Pack (EIP) The Enterprise Integration Pack is Microsoft’s cloud-based solution for seamlessly enabling Business-to-Business (B2B) communications. EIP is new features in Logic Apps which adds B2B and XML capabilities. Enterprise Integration Pack brings some of the enterprise B2B capabilities like AS2 and X12, EDI standards support (with EDIFACT coming shortly) and new set of XML capabilities like XML Validation, XSLT Transformation and Flat file to XML encode/decode. Why should you use Enterprise Integration? You can keep all your artifacts at one place like partner, schema, mapping. i.e. Integration Account. You can simply use all the connectors available to build B2B workflows and integration with 3rd Party SaaS applications. You can also test the Azure functions. Enterprise Integration supported standard Enterprise Integration supports these industry standards: EDI – Electronic Data Interchange EAI – Enterprise Application Integration Minimum Requirement An Azure subscription with an integration account Visual Studio 2015 to create maps and schemas Microsoft Azure Logic Apps Enterprise Integration Tools for Visual Studio 2015 2.0 You can refer this link to understand in the details. Entities Involved in the Enterprise Integration Enterprise Integration Architecture Integration account An integration account is an Azure Account which allows to store all the artifacts required to run the Enterprise Integration for example, schema, mapping, partner agreements, certificates. You need to include this integration account while developing the logic otherwise you will not be able to use the Enterprise Integration features To understand in the details, you need to refer here. Partner Partner is the entity that takes part in the integration process for which the data exchange process works. Before creating a partner participating organization needs to agree to share the information which will help both identify and validate messages that are sent by each other. Partners are used to create agreements. An agreement defines the details about the messages that will be exchanged between partners There must be two partners and one of them must be your own organization. The partner which represents your organization is known as host partner and the second partner is known as the guest partner. The guest partner can be another company, or even a department within your own organization. For more information on the partner and how to create a partner, you can refer this link. Agreements Agreements allows to communicate using the industry standard protocols. It makes is easy for different organization to send the data in the know format which improves the efficiency of data exchange. It is very easy to create and manage the agreements. The standard protocols that are used to Enterprise Integration AS2 X12 EDIFACT For more information on the partner and how to create a partner, you can refer the below link: https://docs.microsoft.com/en-us/azure/app-service-logic/app-service-logic-enterprise-integration-agreements Data Manipulation and Editing Schemas Many times it happens that while sending the data from one system to another the data format for both the system may differ. In that case, you may not be able to process the data on the target system. In that case you can create a schema which will validate the data structure received from the source system. To learn, how to create a schema you can refer the this link. Maps Map is a XML documents which transfers the document from one format to another format. Let’s assume that you are sending data from SalesForce to Dynamics 365. The two systems have different formats of data structures of date ‘DDMMYYYY’ and you want that to be in ‘MMDDYYYY’, then you can use the map to format the data. You can refer this link to understand the maps. XML message validation In B2B scenarios, the partners are need to have agreement to validate the XML message(s). In Enterprise Integration, you can validate the XML using the predefined XML schema XML transform XML transform provides the ability to convert an XML message based on the requirements of a destination endpoint. Other Terminology AS2 AS2 (Applicability Statement 2) is a specification about how to transport data securely and reliably over the Internet. Security is achieved by using digital certificates and encryption. MDN The Message Disposition Notification (MDN) is the acknowledgment sent in response to an AS2 message. If an MDN is enabled, the AS2 transmission is not complete until the MDN has been received and verified. BizTalk Server will always attempt to return an MDN to indicate the status of message processing, even if an error occurred in processing the AS2 message. Features and use cases The AS2 and X12 decode and encode actions allow you to receive data from and send data to trading partners using industry standard protocols using Logic apps. You can use AS2 and X12 with or without each other to exchange data with trading partners as required. The B2B actions make it easy to create partners and agreements in the Integration Account and consume them in a Logic app. By extending your Logic app with other actions you can send and receive data to and from other applications and services such as SalesForce. Sample code You can refer the below link for the AS2 send and receive, this sample code uses the AS2 technology the exchange the message: https://github.com/Azure/azure-quickstart-templates/tree/master/201-logic-app-as2-send-receive You can use the below sample code the use the schema and map validation: https://github.com/Azure/azure-quickstart-templates/tree/master/201-logic-app-veter-pipeline
Share Story :
Relevance Search in Dynamics 365
Introduction: Relevance Search brings the Global Search Experience powered by Azure Search. It uses scoring concepts where score is the indicator of the item’s relevance i.e. higher the score, more relevant the item. Users will get the comprehensive search results quickly in a single list that is sorted by relevance. How it Work’s Basically when a user looks for something like “Nancy ran in the retail store in New York”, the search is executed against the Azure Search Index and the results are returned with a match to any word present inside that particular sentence. This search will also look for the inflectional words like in our case words like running, run, runner and then will display the results accordingly. No wild cards are required to search anywhere in the text. Enhancements in Dynamics 365 Earlier Relevance Search was enabled only in web Browser but now it is enabled for Mobile Client i.e. on Mobile and Tablets. Explore results using Filters and Facets Global Facets Users will be able to see the refined search by Record Type based on following categories like Entity, Owner, Modified On and Created On. These categories cannot be changed as they are predefined by the system as shown in the leftmost image shown below. Entity Specific Facets When user clicks on particular record type such as Account, then user can see the additional facets specified for that particular entity as shown in the rightmost image attached below in our case Primary Contact and Industry. These Entity Level Facets are customizable based on the personal choice i.e. they can facet fields that they would like to see for every searchable entity in their Personal Options. Search within the Documents in Dynamics 365 Relevance Search will now search within the documents that are attached in Notes on a particular record. Relevance Search will also search in the attachments that are added in the Email in CRM. Search in the records that are being shared with you Search in the text of Option set and Lookup fields on any entity. Set Up and Configuration Enable Relevance Search Only System Administrators can enable Relevance Search. Configure Fields in Quick Find View The fields that are added in Quick Find View becomes the part of External Search Index. There is no limit on how many searchable fields can be added for a particular entity. However, there is a limit on total number of indexed fields i.e. maximum of 1000 fields can be added in an organization. Set Managed Properties System Customizer needs to check the managed properties on the entity. As the “Can Enable sync to External Search Index” option must be true. Configure Entities for Relevance Search The System Customizer can add entities that should be enabled for external searching in the Default Solution. So when a user selects the entity, the number in the parentheses indicates the number of fields of entity that will be synced to external search index shown in image below. Below the progress bar of Total Fields shows the percentage of indexed fields to maximum number of fields allowed of searchable fields. Configure Facets and Filters Facets and Filters refines the search in the organization. They are available on the left hand side of the pane immediately after user searches for some term. As mentioned above they can be customized based on the personal requirements. They can be configured from the Personal Settings as shown in the images given below. Drop down list contains the entities that are enabled for Relevance Search. And for a particular entity up to four facets fields can be selected accordingly. Users can modify the preference of the fields based on their choice. Key Take Away Relevance Search is only available for Dynamics 365 Online and now on Mobile Clients too. By Default, Relevance Search is disabled and can be enabled only by System Administrator. Enabling Relevance Search has no impact on the storage consumption and cost for Dynamics 365 database. Facets and Filters can be configured according the User Preference and can redefine the search as per the user’s personal choice. Thus, above are some highlights for Relevance Search in Dynamics 365.
Share Story :
Steps to create Table Extension Object and Page Extension Object Using Visual Studio Code in NAV
Introduction: Table Extension and Page Extension are two new objects introduced in the Microsoft Dynamics NAV TENERIFE Developer Preview (Visual Studio Code) release. Table Extension allows to add more fields to an existing table and to change properties of certain fields of a table. Page Extension object allows to add additional fields and actions to an existing page and extends Dynamics NAV page object. This article will provide the basic steps to create a Table extension object and Page extension object using Visual Studio Code in NAV. Prerequisite: 1. Visual Studio Code 2. Microsoft Dynamics NAV TENERIFE (Developer Preview) Purpose: To create a table extension object and page extension object using Visual Studio Code in NAV. To demonstrate this, I will be adding an additional field on Item card. Steps: Create a new folder for a new project. Fig 1: New Folder created for the Project Open this folder in Visual Studio Code Create a new file within this folder in Visual Studio Code Fig 2: Create a new file in the newly created folder Let’s name this file ‘ItemTableExt.al’ Typing the shortcut ‘ttableext’ will create the basic layout for a table extension. Fig 3: Shortcut ttableext Fig 4: Basic layout of a table extension Replace ‘id’ with a unique table id. It should be in the range from ‘70000000’ to ‘74999999’. Replace ‘MyExtension’ with a unique name of the table extension and ‘MyTargetTable’ with the name of the table where these additional fields have to be added. This is shown in the below Screenshot. After entering the ‘MyTargetTable’ name, Press ‘Ctrl+Shift+B’ to build the solution which will create app.json file. Here, I will be creating a Decimal Field ‘Control Sample Qty’. To create a table field, type the shortcut ‘tfield’. Fig 5: Basic layout of a table field Replace ‘id’ with a unique field id. Replace ‘MyField’ with a unique field name and mention the type of the field viz. Decimal, Integer, etc. Mention the properties of the field below. Fig 6: New field ‘Control Sample Qty’ with ID ‘70000000’ of type ‘Decimal’ is added to ‘Item table’ which is highlighted in red colour. Property of this field i.e. ‘Editable=False’ is highlighted in lime colour. Hence the table extension has been created. To create a page extension, create a new file. Let’s name this file as ItemPageExt.al. Type the shortcut ‘tpageext’ to create a basic layout of a page extension. Fig 7: Basic layout of a page extension. In the layout section, you can use the following functions to place page fields and groups on the page. Similarly, in the actions section, you use these functions to place actions in the ribbon. (Note: General and AddressDetails are group names) addfirst(General) – Applies to Groups only addlast(General) – Applies to Groups only addafter(AddressDetails) – Applies to Fields and groups addbefore(AddressDetails) – Applies to Fields and groups movefirst(General) – Applies to Groups only movelast(General) – Applies to Groups only moveafter(AddressDetails) – Applies to Fields and groups movebefore(AddressDetails) – Applies to Fields and groups Replace id with a unique page extension id in the range from ‘70000000’ to ‘74999999’. Replace ‘MyExtension’ with the name of the page extension. Replace ‘MyTargetPage’ with the name of the existing page in which additional functionality has to be added. The following page extension extends Item card and adds field ‘Control Sample Qty’ to the ‘InventoryGrp’. Fig 8: Field is added to the page using Page extension Hence, page extension is created. Build the solution using ‘Ctrl+Shift+B’. Hence ‘navx file’ will be created. Press F5 to create launch.json file or manually create launch.json file. Thus launch.json will be created. Fig: launch.json In the NAV Web client, in Extensions Management, the published extension will be displayed. Fig 9: Extensions Management Thus, the newly created field i.e. ‘Control Sample Qty’ will be displayed in Item card. Fig 10: New field ‘Control Sample Qty’ field has been added to Item card. Conclusion: Thus, Table extension is used when additional fields are to be added to an existing table or any properties of the fields have to be changed and Page extension is used to add additional functionality to existing pages like extra fields and actions.
Share Story :
Understanding Subgrid functions in CRM Online
Using the new subgrid functions, there are 2 ways to get count of the subgrid data. Based on requirement, we have to use one or the other way for achieving the requirement. getTotalRecordCount(): It determines the total no. of records that match the filter criteria of the view. Features: 1. The count is NOT limited by the current page size. You will get the total size across all pages. 2. You may not also get the latest count of the records using this function if new records are added on the subgrid. How to get around #2 above to get correct count: The idea is to make the grid refresh before executing the “getTotalRecordCount” function, which will enable us to get the correct count. We also have to add an onload event handler for the grid control. Whenever grid is refreshed through code or manually, the onload function will trigger. Note that we cannot do this without onload event. If we try to execute “getTotalRecordCount” just after the refresh line without onload event handler, you will get an error as the grid refresh happens asynchronously and it may not be ready. Sample Code var myContactsGridOnloadFunction = function () { console.log(“Contacts Subgrid OnLoad occurred”); var count = Xrm.Page.getControl(“Contacts”).getGrid().getTotalRecordCount(); }; /// bind an onload event to the grid control Xrm.Page.getControl(“Contacts”).addOnLoad(myContactsGridOnloadFunction); /// refresh the grid. This will trigger onload event. Xrm.Page.getControl(“Contacts”).refresh() getRows().getLength() getRows() will return collection of all gridrows in the grid. Features: 1. It will only return the rows currently visible on the grid. 2. getRows().getLength() will return the count of rows currently visible 3. Unlike getTotalRecordCount, we need not refresh the grid to get the correct row length using this function. Uses: In cases, where we want to know if the grid is empty we can use “getRows().getLength()” instead of getTotalRecordCount to know if the count is 0 or Not. Sample code: var rows = Xrm.Page.getControl(opptyProductSubGridName).getGrid().getRows(); var rowLength = rows.getLength();
Share Story :
‘Item Classification’ in NAV using Visual Studio Code (VS Code)
In this article, we create an extension of standard Page ‘Item Card’ in NAV using Visual studio code (VS Code). To implement the extension, I have created a field ‘Item Classification’ whose Data type is an Option in the table extension in Visual Studio Code. We use app.json (Cltl+shift+B) to build and create a .navx package and launch.json(F5) to publish the extension on the NAV Web Client. Business Requirement Item classification field classifies the raw materials whether it is an Active Pharmaceutical Ingredient(API), Excipient, Pallet, Capsules, Finished Good and Ingredient. This is used by the Production Department to issue Raw Materials from the Warehouse. They classify the items they need by using the Item classification field. Prerequisites: 1. Visual Studio Code 2. Microsoft Dynamics Web Client. Steps: We Create a folder named ‘Item Extension’ in which we place all are codes. Open the visual studio code, click on Explorer and then click on ‘Open folder’. Click on new file and rename it with a name with extension .al e.g ItemTabExt.al Now we create a table extension of standard table ‘Item’. Typing the shortcut ‘ttableext’ creates a basic layout for the table extension object. We provide an id and extends the table name in this case it is the Item The table id range is from 70000000 to 74999999. While saving, it throws error like ‘The target page Item for the extension is not found’ for this we need to create the app.son file by building the solution (Cltl+Shift+B). app.json is automictically created with a 16 byte binary data type which is a GUID. Enter the extension name and publisher for the same. Below is the app.json file The package Cache path is the path to the folder where referenced symbol package files are located. The path could be absolute or relative to the current extension working directory. Now here the package is created Chris_Item extension_1.0.0.0.navx This removed the error on extension table name. Typing the shortcut ‘tfield’ creates the basic layout for the fields. Enter the field id, name and data type in this case the field name is ‘Item Classification’ and data type is ‘Option’. We enter the Caption and the Option string for it. To create the page extension, we type the shortcut tpageext which will create the basic layout for page object using AL extension in Visual Studio code. Edit the id and name and extends Page Name in this case it is ‘Item Card’. We use the function name addlast(Group Name) to add the field at the last of the Group Name Specified.typing the ‘tfieldpage’ automatically creates the layout, we edit MyField and write the field name , edit the source and write the Caption for it. Publishing the extension(F5) will generate the launch.json file Open the Web client and in the search bar type ‘Extension Management’. Click on the installed app. It gives you the details of the Extension name,version and Publisher name. Browse to the Item Page, the field ‘Item classification’ is added. Conclusion: We created table and Page extensions using visual Studio for Standard Table 27 Item and Page 30 Item Card.
Share Story :
Comparing Integration Platforms – TIBCO Cloud Integration and Microsoft Flow
In this article, we are going to compare features of TIBCO Cloud Integration and Microsoft Flow. This will help partners and customers, select the right platform based on their integration needs. Comparing TIBCO Cloud Integration and Microsoft Flow: 1. Real- Time Process: TIBCO Cloud Integration: For real-time integration, a Request/Reply Map needs to be created. This map produces a URL which can be called from any system. For example: To trigger any request-reply map on creation of an Account in Microsoft Dynamics 365, you need to write a plugin which will call the Map Endpoint URL. Image 1: Endpoint URL of Request/Reply Map Microsoft Flow: Flow gets automatically triggered based on create/update/delete record defined in the workflow. For example: Flow for Create Account in Microsoft Dynamics 365 is triggered as soon as the Account is saved. No plugin is required. Image 2: Auto trigger based on record create, delete or update 2. Scheduled Process: TIBCO Cloud Integration: Maps can be scheduled by month, week, day, hour, minute, seconds based on Recent processed date time. We can even run a Solution On Demand. Image 3: On Demand or Scheduled Process Image 4: Scheduling Details Microsoft Flow: Flow can be scheduled by day, hour, minute, seconds. Recurrence action is used for the same. Image 5:Scheduling Details 3. Lookup Records: TIBCO Cloud Integration: Records can be looked up using any condition. If the condition is not satisfied, number of records retrieved will be NULL. Image 6:Lookup criteria based on name of Unit Group Microsoft Flow: Records can be looked up using GUID / Unique Identifier of the record. If Flow couldn’t find the record, then it will throw an error and the proceeding steps will be skipped. Image 7:Lookup criteria based on GUID of required Unit Group 4. Handling mandatory auto-initialized fields: TIBCO Cloud Integration: If mandatory fields are not filled, then TIBCO Cloud Integration shows a warning but lets you save and execute the Map. For example: We are integrating Customers(Accounts) from Microsoft Dynamics 365 to Dynamics 365 Operations. In Operations, CustomerAccount is auto-initialized on create (Number sequence is setup) and it is a mandatory field. When we integrate customers through Scribe, CustomerAccount is not mapped and this field gets initialised. We bring back this CustomerAccount to Microsoft Dynamics 365. Image 8:Mandatory field ‘CustomerAccount’ warning Microsoft Flow: If mandatory fields are not filled, Flow doesn’t allow you to save the workflow. This is a limitation as it ignores the significance of auto-initialisation. For example: We are integrating Customers(Accounts) from Microsoft Dynamics 365 to Dynamics 365 Operations. Since it is mandatory field, we must pass this number from Microsoft Dynamics 365. Image 9: Mandatory field ‘CustomerAccount’ Error 5. Data Formatting/Calculating Functions: TIBCO Cloud Integration: Often, we need to format source data before sending it to target data or do some calculations. TIBCO Cloud Integration provides a Formula Editor for this purpose. There many functions defined in the Formula Editor like DateTime Functions, Logical Functions, Math Functions, Text Functions etc. Image 10: Formula Editor Microsoft Flow: There is no provision for editing the source data yet. It is simply one to one mapping. 6. Error Handling: TIBCO Cloud Integration: Errors can be captured in Scribe and sent across to source system; so, we don’t need to login into Scribe to monitor the errors. Errors can be captured /monitored using Results fields. Image 11: Result fields Microsoft Flow: Errors cannot be captured in Flow. All the steps proceeding the failed step is skipped. Errors can be monitored in Activity section in Flow. Image 12: Activity log on Failure 7. Debugging feature: TIBCO Cloud Integration: We can debug a Map and do a step-by-step analysis/execution. Debugging is very useful from a developer’s perspective. You can analyse Inputs, Results, Errors and even add Breakpoints. Image 13: Debug Mode Microsoft Flow: No Debug Feature is available yet. Though, after execution you can get output of each step. Image 14: Output Conclusion: Using TIBCO Cloud Integration: Scribe is suitable for any kind of integration ranging from simple to very complex Integrations involving direct mapping as well as formatting/editing/calculating source data and sending it across the target. For example: Bi-directional Integration of Customers, Shipping Addresses, Products, Sales Order from Dynamics 365 CRM to Dynamics 365 Operations. Using Microsoft Flow: Microsoft Flow is currently suitable for simple integrations where one to one mapping / direct mappings are the only thing required. For example: Integrating Accounts from Dynamics 365 Financials to Microsoft Dynamics 365.
Share Story :
Power BI new updates: Dropdown slicer, Matrix Conditional Formatting and Hierarchical axis
In this blog article, we will explain about the new updates of Power BI related to Dropdown slicer, Matrix Conditional Formatting and Hierarchical axis. Dropdown slicer: In Slicer, earlier there were only one option to show the data i.e. list. But now we have one more option as dropdown. Means now we have two option on Slicer as List and dropdown. This slicer is very useful when we have lots of category items in our slicer. When we create a normal list slicer, we can change it into drop down by using dropdown option. After selecting the dropdown option, the slicer will look like below: And after click on Drop down arrow Matrix Conditional Formatting: Matrix Conditional Formatting is a new feature. Using this feature we can change the various setting like we can change the colour of cell based on the value. We can set different colour to lowest and highest value in particular category. Refer the below figures for better understating. After click on Conditional formatting you will get the below window than choose whatever colour you want for minimum and maximum value and then click on ok. Once you click ok, you’ll see the formatting applied as below. Hierarchical axis: Hierarchical axis allows us to clearly see the hierarchy within the visual. We can use hierarchical labels by turning off the label concatenation in the formatting pane. Below figure show result when the concatenation label is on. To turn off the concatenation label select visualization and then click on format then expand the X-axis. After turning off the concatenation label you will see the formatting applied as below.
Share Story :
Modular Business apps, App Designer and Sitemap Designer
Before the introduction of Business Apps, Designer and Sitemap designer, we have to take care of following things: We have to manage the security role of users otherwise they will be able to access all the records. If a user wants to design the site map, then user needs to either edit the site map XML or use the third party application to edit it. Introduction: After reading this blog user will able to design their own app with the required component. Description: A new app designer that lets you quickly create simple (single entity) or complex (multi-entity) modular apps. The app designer, which is a tile-based information structure, makes the process of designing apps much simpler because of its intuitive interface. You can simply pick the required set of components such as form, views, dashboard, charts and process flows. Privileges Make sure that you have the System Administrator or System Customizer security role or equivalent permissions Any user with the following privileges can also access the apps: Create, Read, and Write privileges on the App entity Read and Write privileges on the Customizations entity Read privileges on the Solution entity Create an App If you want to create a new app you need to navigate to the below path Go to Settings> My Apps, and then click Create New App. Under My Apps you will able to see all the apps you have. Click on Create App Provide the app details as show below and save the app. Name Unique Name Description Icon App URL And more fields Define Site Map As soon as you will create an app, you’ll need to first define the site map. You can add the below components in the site map Area Group Sub Area You can either add the below components directly by clicking on the + sign or simply by dragging and dropping. You can also put the components by dragging and dropping Below are the components that can be added to the Sub Area Dashboard Entity Web Resource URL Here, I have added the Contact entity and a Dashboard Once you have added all the components, you need save the site map and close it. You can also see the status of your app as to whether it available to other user or not. If the status of an app is Published, then user with the proper role can see but if it is in Draft then only it is available in Edit area. App being edited App designer: You need to specify the components that user must be able to see under the site map. You can add the below components in app designer Dashboard Entity Entity form Entity views Business process flows If you would not specify the above components, then it will add all the above components by default. You can see the below app designer after adding your form, views Validate You need to validate if we need to add any component(s) that are missing. You need to click on the Validate. If there is any issue you will be able to see the as a notification. Publish Once your issue is resolve you can publish your app Once it is published the status of your change to published. App permission: App runs on the base of security role if the current logged in user does not have same role as that of app that then he will not be able to access the app. As in CRM Once it has been published, you will see your app in the Dynamics 365 You can see this app in the CRM as show It shows only the component(s) that we have added during the app design. Now you know about Modular business apps, the App Designer and the Sitemap Designer. You can start using this functionality!
Share Story :
Create item from description NAV 2017
New parameter “Create Item from Description” has been added in Sales and Receivable setup in NAV 2017. By enabling this option user can create new item by adding description on Sales Quote lines, Sales Order lines or Sales Invoice lines. 1) Go into Sales and Receivable Setup and enable Create Item from Description field. 2) When user enter description in Sales quote lines, sales order lines or sales invoice lines for item which is not exist then system will give pop up to create new item or select an existing item. Create new item from Sales Quote line. Create new item from Sales Order line Create new item from Sales Invoice line. 3) When you select Create new item card, System will open template for new item. Select template and click on OK. 4) New Item will create based on item template. User can specify other fields which are require. Conclusion: By using this feature user can create new item by using description and use it for transactions.
Share Story :
Access Dynamics 365 without consuming user License
Scenario: We have a requirement to access Dynamics 365 environment from a custom application hosted outside D365 environment but we do not want to consume the D365 license. We want the user to have all privilege required to perform all task which administrator can do. Solution: Please follow below steps to create user Login to Dynamics 365 portal (Global administrator User) Login to Dynamics 365 portal (https://portal.office.com/adminportal/home) and create new user with minimum user level access. Assign Dynamics 365 license to the user Assign security role to the user Assign System Administrator role to the user. Change Access Mode to Non-Interactive Remove Dynamics 365 user license Now remove D365 license assigned to integration user If you observed, you can see integration user as “Enabled User” in the Dynamics 365 Environment after removing D365 license.