The model-editor allows you to view and edit the model of your project. Changes to the model are automatically applied to the xml files after input.
Select an element in the tree view to start editing it. The form will appear in the right panel.
Adding new elements
Right click in the tree view to open a context menu. It will allow you to add additional elements.
Don't forget to click
An NS Application has the following structure:
- The application is represented by an Application element.
- Each Application can have multiple ApplicationInstances. An ApplicationInstance is a combination of settings to expand the application with.
- Each Application can have multiple Components, and Components can be reused among multiple applications. Components group Data, Task, Flow Elements and ValueFieldTypes.
- A Component can contains DataElements. These represent information in the system, which can be stored, queried and updated.
- A Component can also contains TaskElements. These represent executable pieces of logic. A task has a target DataElement. When executed, the task receives an instance of that DataElement as parameter.
- Next, a Component can contain Flow Elements. Flow Elements are linked to a DataElement with a dedicated
statusfield. The Flow Element describes a number of state transitions. Each transition has a begin-state and a TaskElement to execute if an instance of the DataElement reaches that state.
- Finally, there are ValueFieldTypes, which allow the implementation of custom types for ValueFields for the DataElements of the Component.
Create a new Application project
The functionality to create an application project in the µRadiant will only be enabled when a local installation of the NS Initializer is present.
To create a new NS application project, select
new application project on the
models page. (This is the first page you will encounter when opening the µRadiant or clicking on the logo.)
This will lead you to a page where you can input some basic details.
Start by selecting a directory. After, you will notice you will already be getting some suggestions for the different values.
You can then modify them wherever it is needed. Enable
docker if you wish to deploy locally using docker. (see Docker deployment with nsInit)
Creating a new Component
To create a new Component, select the new module tab:
You will be able to define to update the details for your new Component:
- The name of a Component is the main identifier for that component. It should be written in camelCase, starting with lowercase. The name should be unique to avoid any conflicts with other components.
- The version of a Component can be used to mark changes in the model or custom code.
After creating a Component, make sure to add it to the Application. Select the Application in the first tab and tick the checkbox next to your next Component under components:
You can add a dependency from one component to another. When a Component A depends on a Component B, elements in Component A can reference elements in Component B.
- DataElements in A can have a LinkField referencing DataElements in B.
- DataElements in A can have a ValueFields using ValueFieldTypes provided by B.
- TaskElements in A can target DataElements in B.
- Flow Elements in A can target DataElements in B.
Some considerations on Component dependencies:
Flow Elements targeting DataElements in another Component
Having a Flow Element in one Component (A) that targets a DataElement in another Component (B) is considered dirty. This is because the Flow Element requires changes in the DataElement. The Flow Element will also start actively managing the state of the DataElement. Hence, B is not in control of its own DataElement.
Often, changes in logic behind the Flow Element will also require changes in the DataElement, i.e. the two will be tightly coupled.
A better alternative is to introduce a DataElement in A, which references the DataElement in B and acts as target for the Flow Element. The DataElement in A will thus act as a proxy for the DataElement in B.
TaskElements targeting DataElements in another Component
Similar to the Flow Element, having a TaskElement target a DataElement in another Component increases coupling. Also note that TaskElements are typically part of a Flow Element, which means having such a TaskElement should be seen in the broader picture of how it may force some decisions that increase coupling.
In case of a TaskElement that is designed to be executed outside of the scope of a Flow Element (e.g. triggered by a UI action), it is possible to create a TaskElement that only adds functionality on top of the original Component. In this case the coupling in minimal.
Component Dependency Cycles
Components cannot have cyclical dependencies. They should always be one-directional.
Cutting the Gordian Knot
When encountering issues with dependency between components, consider the following:
- Make a clear inventory of the interactions between the Components. Can they be minimized? Or maybe decide on a 'formal contract' between the Components. E.g. this DataElement will not change, so it can be used by other Components.
- If the connections between two Components are numerous and hard to separate, perhaps the Components should be merged? Sometimes a tight coupling between two Components can point towards a lack of identity for the separate Components.
Deleting a Component
To delete a Component, right-click the Component tab and select delete.
If you have a component that could be used by multiple projects, the best way to reuse this component is by creating an expansion-resource with a model-resource.
DataElements are used to model information in an NS application. When expanded, they will generate classes to store and retrieve data, and view artifacts to show tables, forms etc.
To create a DataElement, right-click the Component in the tree view and select
Then, provide the details of your DataElement:
- The name of a DataElement should be in pascal case (camel case, but with the first letter in uppercase).
- The packageName should be a valid java package.
Each DataElement can have a type, of which the options are listed here.
You can then use this type to filter DataElements:
Each DataElement should have a number of fields.
There are 2 types of fields:
- Value Fields: simple attributes with a Value Field Type, like
- Link Fields: fields representing references to other DataElements
When creating a field, select either valueField or linkField.
- For ValueFields, select the ValueFieldType
- For LinkFields, select the LinkFieldType and target element (DataElement)
Then, there are some flags you can enable for each field:
- isInfoField: Adds the field to the info projection, which is used to display the table.
- isListField: (String ValueField only) Replaces the input field in the view with a dropdown. Uses TagValuePairs.
- calculatedField: (ValueField only) Value Fields which are not stored in a database, but rather calculated when needed.
Link Field Types
There are 6 Link Field Types:
- Ln01: many-to-one, code-managed
- Ln02: many-to-one, JPA-managed
- Ln03: many-to-many, JPA-managed, owning side
- Ln04: one-to-many, JPA-managed
- Ln05: one-to-many, code-managed
- Ln06: many-to-many, JPA-managed, other side
Code-managed vs JPA-managed
When selecting a Link Field Type, you can choose between code-managed (Ln01 and Ln05) or JPA-managed (Ln02 and Ln04).
- Code-managed links will be generated as
Longvalues in de Data layer. The generated code will then resolve the links through lookups. Code-managed links work for links between Components, since they do not require the tables to be in the same database or schema.
- JPA-managed links are generated as references to JPA objects. The resolving is provided by the JPA implementation. JPA-managed links only work within Components, since other Components can have different schema's or databases.
If you have a many-to-one link, you may want a one-to-many link in the other direction. There are some requirements to get this to work:
- The links should both be either code-managed (Ln01 and Ln05) or JPA-managed (Ln02 and Ln04).
- The many-to-one side (Ln01 or Ln02), should be named after the target DataElement (with first letter lowercase).
- The DataElement on the many side should also have a Finder defined, called
<element>is the field on the one side.
Ln04 and Ln05 links need a reverse link to work.
If you have an Ln03 (many-to-many) link and wish to add the reverse link, you can add an Ln06 link on the other DataElement. In this case, the name of the Ln03 field needs to be identical to the name of the element where the corresponding Ln06 link is specified, followed by the character "s".
There is currently no support for one-to-one links. The best option is to use Ln01 or Ln02 on one side.
Finders represent ways to query the stored data.
Finders can have multiple Field Operator Pairs, each defining a constraint on the data. You can start adding Field Operator Pairs to the finder and the name will update automatically.
There are a number of supported Operators.
|Equal, true if the data value is equal to the search value.|
|Strictly Equal (Strings only), true if the data value is exactly equal to the search value. Disables the wildcard search of |
|Like (Strings only), true if the data value is equal to the search value, ignoring casing.|
|Not Equal, true if the data value is not equal to the search value.|
|Greater than (or equal), true if the data value is greater than (or equal to) the search value.|
|Less than (or equal), true if the data value is smaller than (or equal to) the search value.|
|In, true if the data value is equal to one of the (multiple) search values.|
|Nin, true if the data value does not match any of the (multiple) search values.|
A Data Command represents an action that can be performed related to a DataElement.
hasTargetInstanceif the command should be performed on a single instance of the DataElement
- A Data Command can have any number of Connector Fields. These are similar to regular Fields, except they cannot be calculated.
A Data Projection can be used to create a different representation of the data.
- A Data Projection can have multiple reference fields. They include the target field in the projection.
- A Data Projection can also have Calculated Fields, which are not stored, but calculated when the data is projected.
Add a Reference Field for each Field you wish to add by editing the Data Projection.
Then add any Calculated Fields by right-clicking the projection in the tree view.
How to model Calculated Fields
A Data Projection can add calculated fields in 2 ways:
- Add a Calculated Field directly to Data Projection, or
- Add a Field with the calculatedField flag to the DataElement and add it to the Data Projection with a Reference Field.
The first option defines the field only for the projection, the second allows for reuse among other projections.
To create a TaskElement, right-click the Component in the tree view and select
Then, provide the details of your TaskElement:
- The name of a TaskElement should be in pascal case (camel case, but with the first letter in uppercase).
- The packageName should be a valid java package.
Each TaskElement can have a type, of which the options are listed here.
You can then use this type to filter TaskElements:
A TaskElement can also have a transaction type. This will define how a TaskElement in executed in the context of a Flow Element.
You can find the different types here.
Many of the elements can have options. These options will then enable features in the expanders.
Options have an option type and, optionally, a value.
To add an option, edit the element and find the options section in the form. There is an input with a dropdown.
You can either select an option type from the list:
Or, if the option type is not in the list, write the name of the option type and confirm with
Some option types also support values. You can type the value next to the option type.
To remove the option, simply tick the checkbox next to the name of the option type.
After making changes to your model, you can expand the application to get the generated code.
Expanding your Application
To expand an Application, navigate to the expansion page by selecting it in the menu on the left.
You can then expand and harvest your application.
- Expand generates your Application code in the expansion directory
- Harvest extracts any customizations to the code and moves them to the source directory
There are also some flags you can enable.
- Clean will make sure the target directory is cleaned before expansion or harvest. This is useful when making a lot of changes in the model, or after pulling changes from version control.
- Quiet will ignore all logs from maven, thereby reducing the output to the output of the expanders.
- Debug can be used to debug your own expansion resources to find errors. Provide a debug address e.g.
localhost:5005and then connect remotely with a debugger.
Building your Application
After expanding, you can build the application using the Build button, or open the expansion directory in a file explorer.
- Clean will run
mvn cleanduring the build, removing the
targetdirectory. In case you are not familiar with maven, this is a good option to enable by default.
- Install will run
mvn installduring the build, so the artifacts will be available in the local repository.
- Quiet will show only warning and error logs.
You can find the results of your
Build jobs on the history panel.
Click on one of the jobs to see the log.
Adding Expansion Resources
Expanders come in bundles called expansion-resources. Anyone can create an expansion-resource and publish it on the nsx nexus repository for other to use. You can read more about expansion-resources here
To add an expansion-resource to your project, go to the model editor and select the settings tab. You can add new expansion-resources in the form under expansionResources.
Configuring your Application
Settings for your application are kept in the ApplicationInstances.
You can edit them by going the first and selecting one of the instances under applicationInstances in the tree view.
Here you can select the globalOptionSettings, presentationSettings, businessLogicSettings or technicalInfrastructure.
- Business Logic Settings: groups the technologies to use in the application
- Presentation Settings: defines technologies used by the view layer and control layer
- Global Option Settings: groups a variation on settings
- Technical Infrastructure: defines several versions
Editing settings elements
To modify one of the settings elements (or add more instances), go to the settings tab. Here you can find the different settings in the tree view:
To add a new settings, e.g. a new GlobalOptionSettings, right-click in the tree view.