# Developing codeunits

# Steps for creating a new codeunit

1. Create a new Java project in your favorite IDE
2. Import the p2eShared.jar in the project
3. Create a new class: 
    1. The abstract parts are found in: dk.p2e.blanket.codeunit
    2. Implement all abstract methods
    3. Code the method bodies (normally "execute")
4. Compile and build
5. Deploy to webservser: \[Application\]\\WEB-INF\\lib

After first test of the codeunit a server reboot is needed for each redeployment, as there is no way of removing the loaded classes from memory.

# Different codeunit types

Most likely you will need to create a [Formevents](https://docs.tsnocode.com/books/codeunit-reference/chapter/formevents) that will allow specific changes for a solution, during views, updates or exports.

Most interactions wil require interaction with the following objects

- [Security](https://docs.tsnocode.com/books/java-api/page/security)
- [Command](https://docs.tsnocode.com/books/java-api/page/command)
- [Session](https://docs.tsnocode.com/books/java-api/page/sessions)
- [Context](https://docs.tsnocode.com/books/java-api/page/context)
- [DbConnection](https://docs.tsnocode.com/books/java-api/page/dbconnection)
- [EventHandler](https://docs.tsnocode.com/books/java-api/page/eventhandler)

# Error handling

Exceptions are handled by themselves using the errorRegistration(Exception e) method.

In case the errors are not caught by the codeunit itself, the generic error handler takes over

1. Logs the error in the eventlog
2. Returns a standard error page to the user

Other debugging options include log4j and specialized TempusServa **Systemout.print** functions (yes, the class name is "Systemout").

```java
Systemout.println("hello world");
Systemout.printSql(myStatment);
```

# Configuration / parameters

Parameters are delivered through the method call, packed in a nice &lt;String&gt; Hashtable for easy access.

Please note that values are sent as-is, so make sure to escape values before DB operations using

```java
DbConnection.escapeSql(String s);
```

Configurations can be stored using the getConfiguration methods of the command object. These values can be editedthrough the designer, depending on the Codeunit type

- System configurations: Designer &gt; Modules &gt; Static content
- Solution configurations: Designer &gt; \[Solution\] &gt; Advanced &gt; Configurations

Value names will be prefixed with Class simple name - example + "."

```
 com.tsnocode.MyExampleCodeunit.myParameter
```

# Variables

Variables can have a scope of either

- Request
- User session
- Application

For permanent variables user server configurations.

### <span class="mw-headline" id="bkmrk-request-variables-1">Request variables</span>

Request scope variables should be stored in the Hashtable **sharedObjects** in the **Command** object.

Note that the HTTP request parameters are stored in **requestParameters**.

### <span class="mw-headline" id="bkmrk-user-session-variabl-1">User session variables</span>

Acces the **sessionValues** attribute in the **Security** object

- boolean hasSessionValue(String name)
- void setSessionValue(String name, boolean value)
- int getSessionInteger(String name, int defaultValue)
- int getSessionInteger(String name)
- void setSessionInteger(String name, int value)
- String getSessionString(String name, String defaultValue)
- String getSessionString(String name)
- void setSessionString(String name, String value)

All variables her are serilizable and will survive server restarts.

Certain special user properties can also be accessed from the **Security** object

- boolean hasProperty(String name)
- String getProperty(String name)

Finally it is possible to store objects in the Hashtable **sessionObjects** in the **Security** object, but be aware that data are transient and **will not survive server restarts**.

### <span class="mw-headline" id="bkmrk-application-variable-1">Application variables</span>

Application variables are persistent and accessed through the **Command** object

Their storage position depends on wether theres is a solution context or not:

- Solution present: Variables are saved to the solution **Configurations**
- None (SagID = 0): Variables are saved to the **Static content**

Access the the variables goes through get methods with default values.

- String getConfigurationValue(String name)
- String getConfigurationValue(String name, String defaultValue)

If the variable does not exist it will be created, and set to the default value (if present).

Note that it is possible to force the use of Statis content by explicitly calling

- String getSystemConfigurationValue(String name)
- String getSystemConfigurationValue(String name, String defaultValue)

# Using the provided Dev-image

We provide a ready-to-go image of a virtual machine, running Debian 12, for [VirtualBox](https://www.virtualbox.org/wiki/Downloads).

The machine is set up with all the required software and helper scripts, to enable development of custom codeunits.

The image is setup with MariaDB, Tomcat 8, Netbeans 11.3 and a java-project that automatically deploys to the local Tomcat instance and has access to the TS-API with javadoc.

If the image is connected to a bridged network, the database and webserver are accessible from other machines (port 3306 and 8080 are open). use the command `ip a` to find the IP of the machine.

The image is running Debian 12 with a custom LXDE interface.

### <span class="mw-headline" id="bkmrk-getting-the-image-ru-1">Getting the image running</span>

The image is buildt for VirtualBox, so install that.

Once you have the image downloaded, start the import wizard in VirtualBox (ctrl + i) and follow it.

Now you should be able to boot the VM. The username and password for the user is noted in the comment on the VM.

The machine includes the following programs:

- Firefox, to access the local Tomcat server
- NetBeans 11.3, to develop codeunits
- DBeaver CE 24, to access the local DB

### <span class="mw-headline" id="bkmrk-deploying-codeunits-1">Deploying codeunits</span>

To deploy your code to the local Tomcat instance do the following:

1. Open Netbeans
2. Build the project (right-click the project in the project-browser on the left and select build)
3. Copy the generated .jar file from `/home/developer/NetBeansProjects/[ApplicationName]/dist` to `/mnt/sda/deploy`
4. Clear the cache (open [http://localhost:8080/app/service?CacheClear](http://localhost:8080/app/service?CacheClear)) or go back to the app in firefox and select Administrator -&gt; Services -&gt; Cache control -&gt; Cache clear

### <span class="mw-headline" id="bkmrk-debugging-codeunits-1">Debugging codeunits</span>

Attach the NetBeans debugger to the local Tomat server:

Click "debug" in the top-left menu -&gt; click "attach debugger" -&gt; click "OK", the default settings should work

Add a breakpoint to your code by selecting the line number and try to invoke it from the browser.

### <span class="mw-headline" id="bkmrk-updating-the-api-and-1">Updating the API and platform</span>

To update the local environment to the latest version of the TS-API and TS Platform, open a terminal and execute the following commands.

```bash
updateAPI
ts -w app upgrade-alphaapp
```

You will be prompted to input the password for the user.